I'm using .NET Compact and creating a log scale. I currently have a List holding the values to be drawn, which will then get converted to an array of Points, whereupon the Graphics.DrawLines() method will take them and draw a line between each point. However, as you can imagine, this can look jagged and erratic. Since .NET Compact does not have a Graphics.DrawCurve() method or such, I wondered if anyone knew of a good way to create points between the points which could emulate a curved graph? Ideally, something to create the points that might appear on a spline between the points.
-
1Are you asking "How to find a Function that matches your data points?" – Aug 15 '12 at 18:43
-
No... I have Points which create a jagged graph. I'm asking how to add more points to soften the points, to essentially replicate what Graphics.DrawCurve() does when supplied an array of Points, which unfortunately .NET Compact Framework is missing. As the screen display is quite small, even if it were just 2 extra points between each point, that would be fine. – MrShoes Aug 16 '12 at 07:46
-
1If you're not worried about the graph being precise, you could use some sort of interpolation with more control points (cos, for example). – ssube Aug 16 '12 at 15:00
2 Answers
Well, I can't say that I spent the time to go into this and understand the Math behind everything that is going on, but I was able to find a post on a VB forum that splits up a spline into segments to make a plot.
I took a hack at massaging the code to get it to C# for Windows Mobile.
It compiles, but I don't know what to do with it.
private void Spline(Graphics g, Pen pen, Point[] points, double tx) {
int arrayLength = points.Length;
int max = arrayLength - 4;
if (3 < arrayLength) {
for (int i = 0; i < arrayLength; i++) {
int n1, n2, n3, n4;
if (i == 0) {
n1 = i + 0;
n2 = i + 0;
n3 = i + 1;
n4 = i + 2;
} else if (i < max) {
n1 = i + 0;
n2 = i + 1;
n3 = i + 2;
n4 = i + 3;
} else {
n1 = max + 1;
n2 = max + 2;
n3 = max + 3;
n4 = max + 3;
}
Segment(g, pen, points[n1], points[n2], points[n3], points[n4], tx);
}
}
}
private void Segment(Graphics g, Pen pen, Point pt0, Point pt1, Point pt2, Point pt3, double tx) {
int pointCount = 4;
double sx1 = tx * (pt2.X - pt0.X);
double sy1 = tx * (pt2.Y - pt0.Y);
double sx2 = tx * (pt3.X - pt1.X);
double xy2 = tx * (pt3.Y = pt2.Y);
double a1 = sx1 + sx2 + 2 * pt1.X - 2 * pt2.X;
double a2 = sy1 + xy2 + 2 * pt2.Y - 2 * pt2.Y;
double b1 = -2 * sx1 - sx2 - 3 * pt1.X + 3 * pt2.X;
double b2 = -2 * sy1 - xy2 - 3 * pt1.Y + 3 * pt2.Y;
double c1 = sx1;
double c2 = sy1;
double d1 = pt1.X;
double d2 = pt1.Y;
for (int i = 0; i < pointCount; i++) {
double x = (double)i / pointCount;
double xSq = x * x; // x^2
double xCu = x * xSq; // x^3
double f1 = a1 * xCu + b1 * xSq + c1 * x + d1; // f(x) = A x^3 + B x^2 + C x + D
double f2 = a2 * xCu + b2 * xSq + c2 * x + d2; // f(x) = A x^3 + B x^2 + C x + D
double dx = Math.Floor(f1);
double dy = Math.Floor(f2);
g.DrawRectangle(pen, (int)dx, (int)dy, 1, 1); // calculated points
}
g.DrawRectangle(pen, pt0.X, pt0.Y, 1, 1); // original point
}
I do not know what values to suggest for you for double tx
. You'll just have to play around with that.
This might get you some mileage, but I don't really know how this would add points for you ...unless you edited the code to include some mid points.
Once you get it solved, edit your post with a few screen captures of the end result (if you don't mind).
-
That answer is absolutely brilliant. I'm pretty sure I can use this as the foundation for a solution to the problem. I've been asked to focus less on it and leave it until the end of the project as a "nice to have", but if complete I will definitely update you. – MrShoes Aug 17 '12 at 14:43
You want to look at implementing some of your own graphics methods then. Depending on the exact results you want, there are a variety of existing and well documented methods you can use. There are plenty to be found both in books on general computer graphics and online. For example, refer to the stack overflow article at the link below for one example as a starting point: