-
Notifications
You must be signed in to change notification settings - Fork 241
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Plotting Utility #170
base: develop
Are you sure you want to change the base?
Conversation
Hi Jakob, |
Mark, Sounds great, let me know what you think! Also let me know if you have any Perhaps we should make a "plots" branch rather than have it in develop I definitely think I/we need to figure out what saving/exporting types we Jakob On Thu, Oct 13, 2016 at 9:20 AM, Mark Rogoyski [email protected]
|
Hi Jakob, Cool stuff. I was able to follow your examples and get it to plot things. I can just basically give it a function and it plots it! Pretty simple and straightforward. I like it. Now if you don't mind, let's talk about how you can make it even better. I'd like to talk about design and role of the classes. It makes sense that there is a Canvas, and you draw Plots on the canvas. And if you add the functionality to plot multiple Plots on a single canvas, that'd be cool and it works with the design. One thing that seems a little confusing is that Let me know what you think about this idea, taking into consideration the possibility of future functionality to have multiple Plots in a Canvas. What if the Canvas object had the attributes for canvas size (width, height), x range, grid, title, and labels. If a Canvas can contain multiple Plots, they would have to share the same space and be plotted against the same x range. And it wouldn't make sense (I think) to have multiple overlapping titles and labels. So The Canvas controls that stuff and all Plots added to the Canvas conform to those attributes. The Canvas would then draw the axes, labels, title, etc., and then when it called draw() on each Plot, it would pass in things like width in height as parameters to the Plot's draw method. I imagine the Canvas would have to ask each Plot for their min and max Y values and adjust the y-axis according to the max values. In code, it would probably look something like this: $canvas = new Canvas();
$canvas->size(320, 240);
$canvas->xRange(-10, 10);
$canvas->grid(true);
$canvas->yLabel('Y Label goes here');
$canvas->xLabel('X Label goes here');
$canvas->title('Graph Title');
$sin_plot = new Plot(function ($x) { return sin($x); });
$sin_plot->color('red');
$sin_plot->thickness(5);
$cos_plot = new Plot(function ($x) { return cos($x); });
$cos_plot->color('red');
$cos_plot->thickness(5);
$canvas->addPlot($sin_plot);
$canvas->addPlot($cos_plot);
$canvas->draw(); As a quick aside, it might be beneficial to add a fluent interface (Each setter returns $this) to make the initialization take less code: $canvas = new Canvas();
$canvas->size(320, 240)
->xRange(-10, 10)
->grid(true)
->yLabel('Y Label goes here')
->xLabel('X Label goes here')
->title('Graph Title');
$sin_plot = new Plot(function ($x) { return sin($x); });
$sin_plot->color('red')
->thickness(5);
$cos_plot = new Plot(function ($x) { return cos($x); });
$cos_plot->color('red')
->thickness(5);
$canvas->addPlot($sin_plot)
->addPlot($cos_plot);
$canvas->draw(); Does this idea make sense? Let me know what you think. It's just an idea, and first I'd like to hear more about your design decisions and where you were thinking of going with it as well. Some other minor improvements: File type File name Unit tests Random In Canvas' Btw, I've merged it into a feature branch Thanks. And again, great stuff! |
Mark, Thanks for taking to time to look through this and give such thorough I definitely understand many of the points you are making. Let me spend a One quick note: In developing the class hierarchy, I considered three types
The reason I tried to keep Canvas as minimal as possible is to accommodate Jakob On Thu, Oct 13, 2016 at 11:51 PM, Mark Rogoyski [email protected]
|
OK interesting. I didn't consider multiple independent plots drawn together side by side. |
Mark, I've been thinking more about your comments, and I definitely agree with a lot of your points! First, as you recommended, it makes sense to pass in the canvas height and width as an argument in the Also, I like your approach of defining In terms of haveing multiple independent plots, I definitely think this would be an important feature to consider. I think it'd be useful so a user can generate related (but still distinct) plots without requiring them to open and image editor to put them all together (if we only generate single plots). For example, if we wanted to make an image that shows "Contributions to Math PHP", we could have it contain three subplots: Commits vs. Time, Additions vs. Time, and Deletions vs. Time. In this example, it makes sense to give each subplot its own set of parameters (axis labels, title, etc.). However, also in this example, it could also make sense to give the canvas itself a title, for example, "Contributions to Math PHP". Therefore, I feel like we should give the Consider how this example could look:
In the above example,
Using the above approach, we could simply the example:
And to demonstrate how this would look for a single plot, consider just plotting commits:
What do you think of this approach? To make an image that contains a single plot with multiple functions, we would simply use the In this way, we could redo your example as follows:
Notice that I am using the We can extend this even further by building another class
Let me know if any of this is consfusing, or if it seems I'm adding any unecessary level of complexity. I also think it'd be useful to make a logic and consistent terminology, as With regards to your other comments (file type, file name, unit tests, and random), I completely agree with all your points. Jakob |
Hi Jakob, Thanks for the detailed explanation of how you might organize everything. For the option of doing multiple subplots, I think I like the second simpler method of declaring the arrangement in the canvas and then just adding the plots. In the Plot object, I think it would be clearer if you changed the proposed plot() method to be addFunction() or addCurve() or something. I think if you want to have multiple functions on a single plot and be able to give them different colors and thicknesses, then it does make sense to have those defined individually. I'm not sure if Curve, or Function, or something else is a better name for that class, but that is just a detail you can change later. I think you have the right approach, regardless of what the name ends up being. Thanks for putting a lot of thought into the design. |
Sounds good! I'll use this feedback to make an update. I'll give a bit more thought to appropriate terminology, but as you said, we can adjust this later. |
In Summary:
Canvas
, andPlot
Canvas
is the parent class, and is use for creating the base image that a plot is built onPlot
is used for holding method/paramters for a plot, and physically drawing the plot on a canvas objectFor an example of how this looks, try the following. Also, try to change the inputs for methods in order to get a feel for how they work (and let me know if things are not obvious).
It would also help to read the descriptions for both classes, the description of the
__construct()
method for both classes, and the description of thesave()
method for Canvas.