Add your own alternative version
Stats
78.6K views 3.7K downloads 123 bookmarked
Posted
19 Sep 2007

Comments and Discussions



Hello
I am a student "Moscow Power Engineering University"
Help me please. In the case of "Rectangular" I need a coordinate system in which the axes of the image at the edges.
Thank you very much.
email: nguyentiyen@mpei.ru
Nguyen TS





Hi Syed,
Excellent piece of work.
Is it possible to extend this control to have discrete points platted, instead of expressions? That would be great. Then one can use it to plot any type of data / time series.....something that is widely used in business and academia.
Best wishes/Rajeev





did u had any upgrade at your quest? because i want the same .. and you want it since 2011 soo...
if u can help me
regards
Daniel





Hi Daniel,
I did not find anything that suited my requirements....had to use a chart control in the end. ComponentOne...though I am not so enamoured by it.....perhaps there are better ones available now.
Hope this helps.
Rajeev





Hello Syed,
Take 5 from me for your great control. I have a suggestion. Why not use the FLEE (Fast Lightweight Expression Evaluator)[^] library it's published under the LGPL and compiles the expressions given making it very fast. What I don't know about though is how this affects an article. Expression evaluation is not a small part of building a control as you did, so I'm not sure how it is received by the community if such a (really great) library would be used.
You should still take a look at it, even if you wont or can't use it for your control.
What do you think?
Cheers!





Hello Manfred,
Thanks for the link. I did take a quick look and it seem interesting. Will take a detailed look later and consider to use it in the control in some future version.
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





Good one! I like your article.





Thanks very much, Manfred. I am glad you liked the article.
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





I want to change background image for Expression Plotter Control.
Please, help me.





Hi,
In the OnPaint override, you need to comment the line that clears the surface and fills it with white color:
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





I want to shade the common intersection of two graphs. Integral calculation? Are you help Me? http://euphrates.wpunj.edu/courses/maen509/unit04/images/LI2v05b.gif





Hi,
Unfortunately, I can't think of any such possibility right now.
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein






Hi,
The control can only work with expressions in the form y=f(x) . So if you have some other expressions like the ones you mentioned, perhaps you need to work out some equivalent y=f(x) expressions. e.g.
x = y * y
=> y = (+/) sqrt(x)
So you need to create two expressions, sqrt(x) and sqrt(x) .
Hope that makes sense.
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein






it does not understand the expression y = x * x.





Works for me. Did you enter "x*x" as the expression text?
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





Thank You...
Very nice...





Thanks.
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





I did a function plotter in Java once. The functions were compiled into tree structures by a lexer/parser combination generated with JFlex and Cup (an LALR(1) parser generator).
In order to speed up (re)drawing of graphs I implemented something that I'd like to call "adaptive plotting": My program recursively divided the xrange of the plot into halves and at some point decided that the subdivision was good enough (for that function) to allow it to draw a straight line instead of doing further subdivisions. Basically the subdivision algorithm had to guess something like the second derivative of the function. (Since the function is already represented by an expression tree structure, it would not be all that difficult to generate the expression tree of the second derivative automatically  but I did not try to got that far, especially since an automatically generated second derivative is likely result in a rather complex expression tree, except if one is able to do a reasonable amount of algebraic simplification.)
So for graphs of linear functions, this was really, really fast! Also it was fast and accurate for reasonably slow changing functions. Plotting something like y=sin(1/x) around x=0 was more problematic, to be sure, but that kind of function doesn't look too nice when plotted with most other function plotters either. The problem lies in the criteria that the subdivision algorithm has to use in order to decide whether the subdivision happens to be "good enough" to draw a straight line instead of doing further subdivisions of the xrange. I don't think there is a perfect solution for this. Sometimes my algorithm produced graphs with artifacts (straight lines where they did not really belong), but I could always remove such artifacts by slightly modifying the xrange to be plotted.
Right now I plan to do another function plotter, in C# this time, that's why I was searching the internet for good examples and finally hit upon your very nice article. Since I would like my new function plotter to deliver graphs as vector drawings (XAML) that can be pasted into the InkCanvas of my shared whiteboard that I use for onlinemath tutoring, I cannot possibly just use your plotter control as is. But it sure helps as a source of inspiration.
Thanks,
Christian





Hi Christian,
Thanks for reading the article and leaving a comment. The idea of adaptive plotting using range splitting is awesome. I will think of incorporating it in this control at some later stage. Are you planning to write an article about your XAML version? I really look forward to reading that.
Good luck for your control and have a great day.
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





Hi Syed,
I now have a first version of a function plotter that produces XAML which I can paste into my shard whiteboard (which was the goal of the entire exercise). Looking back I think this approach has many advantages as compared to using raster graphics operations to draw the function graphs: The coordinate grid, and the graphs of the functions are separate canvases (the graphs are children of the grid canvas). If a graph is added or removed from the plot, neither the grid nor the other graphs need to be recalculated or even redrawn (the WPF rendering engine does all the relevant fancy footwork, instead). Real recalculation only takes place if the user changes the plot window, i.e. xmin, xmax, ymin, and ymax.
The points of the graph that are joined by line segments for drawing and the generation of XAML are held in a List> structure, called "components".
Generating the XAML for a function graph, once its components have been determined, looks as simple as this:
public override string ToXaml()
{
if (components.Count == 0)
return "";
StringBuilder sb = new StringBuilder();
sb.Append(String.Format("<Canvas Width=\"{0:0.00}\" Height=\"{1:0.00}\" Clip=\"M 0,0 L 0,{1:0.00} {0:0.00},{1:0.00} {0:0.00},0 z\">", grid.Width, grid.Height));
double sx = grid.Width / (xmax  xmin);
double sy = grid.Height / (ymax  ymin);
sb.Append(String.Format("<Path Stroke=\"{0}\" StrokeThickness=\"{1}\" StrokeDashArray=\"{2}\"><Path.Data><PathGeometry Figures=\"", options.PenColorName, options.Width, options.StrokeDashArray));
foreach (List<Point> s in components)
{
if (s.Count == 0)
continue;
sb.Append(String.Format("M {0:0.00},{1:0.00} ", (s[0].X  xmin) * sx, grid.Height  (Math.Max(NINF, Math.Min(PINF, s[0].Y))  ymin) * sy));
for (int i = 1; i < s.Count ; i += 1)
{
sb.Append(String.Format("L {0:0.00},{1:0.00} ", (s[i].X  xmin) * sx, grid.Height  (Math.Max(NINF, Math.Min(PINF, s[i].Y))  ymin) * sy));
}
}
sb.Append("\"></PathGeometry></Path.Data></Path></Canvas>");
return sb.ToString();
}
The adaptive plotting function GetComponent(), that determines one single List, i.e. one single "component" of the graph, is ridiculously simple, too (leaving aside the problem of getting outofrange or undefined values of the function at the points under consideration), it reduces to this:
if (Math.Abs(ym  (yl + yh)/2.0) < EPSILONY)
{
component.Add(new Point(xh, yh));
}
else if (xm  xl < EPSILONX)
{
component.Add(new Point(xm,ym));
component.Add(new Point(xh, yh));
}
else
{
GetComponent(xl, xm);
GetComponent(xm, xh);
}
where xl,xh are parameters of GetComponent() and xm=(xl+xh)/2, ym=f(xm), yl=f(xl) and yh=f(xh). The values EPSILONY and EPSILONX can be influenced by the user who enters the plot command for the function, if need be. (I use a small command shell to enter definitions of functions and plot / unplot / delete/ commands. The plot function takes a list of function names and may specify plot options that override the defaults. Having such a shell gives me a handy calculator as a side effect.) Of course, by a stroke of bad luck, the points (xl,yl), (xm,ym) and (xh,yh) may lie on a straight line without the actual graph between those points looking at all like a straight line. In such cases, the ability to force sufficiently small line segments to be generated, by specifying plot options for such a function, comes in handy.
But although I like the function plotter as it is now, it would not be ready for publication. Also, I think the relevant parts (the generation of XAML and the basic adaptive plotting idea shown above) are so simple that they don't seem to warrant the writing up of an entire article.
Regards,
Christian





x+(2+(x+2)*(x+3)) > (x+(2+((x+2)*(x+3))))
InsertPrecedenceBrackets > (x+(2+((x+2)*(x)+3)))





Hi,
The evaluation technique used in the control gives equal priority to all the operators. So we solve this by inserting some brackets in the expression and the method InsertPrecedenceBrackets() is used to insert those brackets. Have a look at the example here.
Hope that makes sense.
Regards,
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





thank,but it is not correct in a few cases
test x+(2+(x+2)*(x+3))
x+(2+(x+2)*(x+3)) > (x+(2+((x+2)*(x+3))))
x =0 >y = 8 (correct)
InsertPrecedenceBrackets > (x+(2+((x+2)*(x)+3)))
x =0 >y = 5 (incorrect)





Ah..I see. Thanks for reporting. I will have a look at this and will get back to you.
Syed Mehroz Alam
My Blog  My Articles
Computers are incredibly fast, accurate, and stupid; humans are incredibly slow, inaccurate and brilliant; together they are powerful beyond imagination.  Albert Einstein





Can this software be used from Visual C++ 2005?





It is not possible to use floating numbers in the expression. E.g. you want to write x + 2.45 , it is interpreted as x + 245 . You have to modify the EvaluateInternal function of the Expression class
here is a solution (I didn't test it very well)
if (char.IsDigit(chCurrentChar))
{
while (char.IsDigit(textInternal[i])  textInternal[i] == '.')
i++;
string toConvert = textInternal.Substring(startIndex, i  startIndex).Replace('.', ',');
dOperand = Convert.ToDouble(toConvert);
i;
}
But your class is great!!!





The reason is that I didn't handle globalization in my parsing. Since at your culture you use a comma for decimal place and my code looks for a dot so the results were wrong. I will handle this aspect in some future update.
Thanks for pointing out.
Syed Mehroz Alam





Nice work.
If expression gets too complex, it would be nice to hide it in the delegate, and plug it to graph (specifying name to display, too).





Cool..its better to evaluate expressions asynchronously using delegates. Thanks for the idea.
Cheers,
Syed Mehroz Alam.






Thanks chap..
Syed Mehroz Alam





Is it possible to show control without same width and height?





Currently, no, as it needs some remapping of plotting equations and loops. I hope I shall be including this feature in the next update.
Regards,
Mehroz





The control now supports any rectangular size. Hope this will help you.
Regards,
Syed Mehroz Alam
modified on Wednesday, June 4, 2008 1:01 PM





Hi Syed,
I am unable to add teh control in a VB.NET 1.1 project. Can you suggest a work around?
Would be of great help.
Rajeev





Hi Rajeev,
I don't think you can use a .Net 2 Control in a .Net 1.1 project. If you still want to use it, you must port the control code to .Net 1.1.
Regards,
Mehroz





Good work, Would love to get my teeth into it, and use it somewhere.
Rajeev
Rajeev





full marks
Sacha Barber
A Modern Geek  I cook, I clean, I drink, I Program. Modern or what?
My Blog : sachabarber.net







General News Suggestion Question Bug Answer Joke Praise Rant Admin Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

