As the user drags their stylus across the tablet, you receive a series of coordinates. You want to approximate the pen's path with a smooth line, trailing only a few sample points behind it. How would you do this?
In other words, how would you render a nice smooth responsive line as a user draws it with their tablet? Simply connecting the dots with straight lines is not good enough. Real drawing programs do a much better job of curving the line, no matter how close or far the sample points are. Some even let you give them a number to indicate the amount of smoothing to be done, accounting for jittery pens and hands. Where can I learn to do this stuff?
I know this is an old question but I had the same problem and I came with 2 different solutions:
The first approach is use two resolutions: One , when the user is inserting the path points connecting them with straight lines. Two , when the user finish the stroke delete the lines and draw the spline over. That should be smoother than the straight lines.
The second approach it is to smooth the new points with a weighted mean of the sampled points. So each time you get a new point [x1,y1] instead of painting it directly, you take the previous points [x2,y2] and create a new intermediate point with the weighted mean of the two points. The pseudocode could be something like:
newPoint = [x1,y1];
oldPoint = [x2,y2];
point2Paint = [(x1*0.3) + (x2*0.7), (y1*0.3) + (y2*0.7)];
oldPoint= newPoint;
Being 0.7 and 0.3 the coefficients for the weighted mean ( You can change them to get your desired smoothing :)
I hope this would help
UPDATE Dec 13: Here it is an article explaining different drawing methods, there are good concepts that can be applied (edge smoothing, bezier curves, smooth joints)
http://perfectionkills.com/exploring-canvas-drawing-techniques
I never had to implement these (only for academic purposes), but you may want to take a look at wikipedia's interpolation article.
Extracted from the article:
interpolation is a method of constructing new data points within the range of a discrete set of known data points.
In engineering and science one often has a number of data points, as obtained by sampling or experimentation, and tries to construct a function which closely fits those data points. This is called curve fitting or regression analysis. Interpolation is a specific case of curve fitting, in which the function must go exactly through the data points.
Hope it helps.
Related
I have got a binary image/contour containing four human beings, and I want to detect/count all humans. Since there are occlusions, so I think it is best to get the head/maxima in the contour of all the humans. In that case human can be counted.
I am able to get the global maxima\topmost point (in terms of calculus language), but I want to get all the local maximas
The code for finding the topmost point is as suggested by Adrian in his blogpost i.e.:
topmost = tuple(biggest_contour[biggest_contour[:,:,1].argmin()][0])
Can anyone please suggest how to get all the local maximas, instead of just topmost location?
Here is the sample of my Image:
The definition of "local maximum" can be tricky to pin down, but if you start with a simple method you'll develop an intuition to look further. Even if there are methods available on the web to do this work for you, it's worth implementing a few basic techniques yourself before you go googling.
One simple method I've used in the path goes something like this:
Find the contours as arrays/lists/containers of (x,y) coordinates.
At each element N (a pixel) in the list, get the pixels at N - D and N + D; that is the pixels D ahead of the current pixel and D behind the current pixel
Calculate the point-to-point distance
Calculate the distance along the contour from N-D to N+D
Calculate (distanceAlongContour)/(point-to-point distance)
...
There are numerous other ways to do this, but this is quick to implement from scratch, and I think a reasonable starting point: Compare the "geodesic" distance and the Euclidean distance.
A few other possibilities:
Do a bunch of curve fits to chunks of pixels from the contour. (Lots of details to investigate here.)
Use Ramer-Puecker-Douglas to render the outlines as polygons, then choose parameters to ensure those polygons are appropriately simplified. (Second time I've mentioned R-P-D today; it's handy.) Check for vertices with angles that deviate much from 180 degrees.
Try a corner detector. Crude, but easy to implement.
Implement an edge follower that moves from one pixel to the next in the contour list, and calculate some kind of "inertia" as the pixel shifts direction. This wouldn't be useful on a pixel-by-pixel basis, but you could compare, say, pixels N-1,N,N+1 to pixels N+1,N+2,N+3. Or just calculate the angle between them.
There are a lot of curve fitting questions on SO but I can't seem to find one that addresses what I'm looking for.
The scenario is simple: I capture X/Y points on a tablet screen. I'd like to draw the resulting line segments as a smooth curve instead of a series of line segments. Many apps do this, for example: Penultimate (sketching demo at 0:36) or Autodesk Sketchbook.
Bezier curve algorithms take a fixed number of points to draw a curve and don't seem to work well with numerous multiple points. Can anyone point to an algorithm which does this well?
Fit-Curve is a Spline and not a Bezier Curve in fact. However, you can make a Bezier Curve to look like your Spline (Splines have no control points). I've searched a lot on this problem and introduced/implemented a lot of too-complex algorithms to myself, and finally I found that the task is much easier than I supposed (I do felt it must to, I swear :) )
Here is the best description on that, I'll take an excerpt from this article:
In most implementations, Bezier Curve drawing function takes two control points and a point itself (for a segment) as an arguments, so everything you need is just iteratively finding the control points for new segments (I think it is best to update last segment and draw a new one in the end of curve for every new point):
Here comes the JavaScript code (t for a simplest case is a constant smoothness of your curve):
function getControlPoints(x0,y0,x1,y1,x2,y2,t){
var d01=Math.sqrt(Math.pow(x1-x0,2)+Math.pow(y1-y0,2));
var d12=Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
var fa=t*d01/(d01+d12);
var fb=t*d12/(d01+d12);
var p1x=x1-fa*(x2-x0);
var p1y=y1-fa*(y2-y0);
var p2x=x1+fb*(x2-x0);
var p2y=y1+fb*(y2-y0);
return [p1x,p1y,p2x,p2y];
}
Please be sure to read and understand the article, I think it is a best, shortest and clearest one.
Check out splines. They basically take a set of control points as input and output a set of cubic curve where each curve is tangent to the previous one giving a smooth outline.
See this: http://en.wikipedia.org/wiki/Cubic_Hermite_spline
I am doing alphabet tracing application for kids. I have given the dotten points. how to identify that am moving over that points. using Touches moved, i want to write.If moved incorrectly, i dont like to draw lines. plz share ur ideas
The simple version is:
Record the initial touch-point on touchesBegan.
On each touchesMoved call, do:
Interpolate a reasonable number of points (a dozen or so should be sufficient) between the initial touch-point and the current touch-point.
For each interpolated point, perform a hit-test against your "dot" locations. This can be done by computing the linear distance between the point and the "dot" location, and counting any distances closer than some threshold as a "hit".
Set the initial touch-point to the current touch-point.
On touchesEnded, perform one final round of interpolation and hit-test, and then clear your initial touch-point.
Of course you may want to add some extensions of your own to the basic algorithm, such as keeping an array of all the contacted points to check at the end of the event to help discriminate coordinated interactions from random nonsense, and so on.
I have N points in 3-dimensional space. I need to join them using a line. However, if I do that using a simple line, it is not smooth and looks ugly.
My current approach is to use a Bezier curve, using the DeCasteljau algorithm for 4 points, and running that for each group of 4 points in my data set. However, the problem with this is that since I run it on say points 1-4, 5-8, 9-12, etc., separately, the line is not smooth between 4-5, 8-9, etc.
I also looked for other approaches; specifically I found this article about Catmull-Rom splines, which seem even better suited for my purpose, because the curve passes through all control points, unlike the Bezier curve. So I almost started implementing that, but then, I saw on that site that the formula works "assuming uniform spacing of control points". That is not the case for my problem.
So, my question is, what approach should I use -- Bezier, Catmull-Rom, or something completely different? If Bezier, then how to fix the non-smoothness between 4-5, 8-9, etc.? If Catmull-Rom, why won't the formula work if points are not evenly spaced, and what do I need instead?
EDIT: I am now pretty sure I want the Catmull-Rom spline, as it passes every control point which is an advantage for my application. Therefore, the main question I would like answered is why won't the formula on the link I provided work for non-uniformly spaced control points?
Thanks.
A couple of solutions:
Use a B-spline. This is a generalization of Bezier curves (a Bezier curve is a B-spline with no internal knot points.)
Use a cubic spline. Cubic splines are particularly easy to calculate. A cubic spline is continuous in the zero, first, and second derivatives across the control points. The third derivative, the cubic term, suffers a discontinuity at the control points, but it is very hard to see those discontinuities.
One key difference between a B-spline and a cubic spline is that the cubic spline will pass through all of the control points, while a B-spline does not. One way to think about it: Those internal control points are just suggestions for a B-spline but are mandatory for a cubic spline.
A meaningful line (although not the simplest to evaluate) can be found via Gaussian Processes. You set (or infer) the lengthscale over which you wish the line to vary (i.e. the smoothness of the line) and then the GP line is the most probable line through the data given the lengthscale. You can add noise to the model if you don't mind the line not passing through the data points.
Its a nice interpolation method because you can also obtain the standard deviation of your line. The line becomes more uncertain when you don't have much data in the vacinity.
You can read about them in chapter 45 of David MacKay's Information Theory, Inference, and Learning Algorithms - which you can download from the author's website here.
one solution is the following page in wikipedia: http://en.wikipedia.org/wiki/Bézier_curve, check the generalized approach for N control points.
I am currently working on a data visualization project.My aim is to produce contour lines ,in other words iso-lines, from gridded data.Data can be temperature, weather data or any kind of other environmental parameters but only condition is it must be regularly spaced.
I searched in internet , however i could not find a good algorithm, pseudo-code or source code for producing contour lines from grids.
Does anybody knows a library, source code or an algorithm for producing contour lines from gridded data?
it will be good if your suggestion has a good run time performance, i don't want to wait my users so much :)
Edit: thanks for response but isolines have some constrains like they should not intersects
so just generating bezier curves does not accomplish my goal.
See this question: How to approximate a vector contour from an elevation raster?
It's a near duplicate, but uses quite different terminology. You'll find that cartography and computer graphics solve many of the same problems, but use different terminology for them.
there's some reasonably good contouring available in GNUplot - if you're able to use GPL code that may help.
If your data is placed at regular intervals, this can be done fairly easily (assuming I understand your problem correctly). First you need to determine at what interval you want your contours. Next create the grid you are going to use to store the contour information (i'm assuming just a simple on/off or elevation at this contour level type of data), which should be one interval smaller than the source data.
Now the trick here is to offset the 2 grids by 1/2 an interval (won't actually show up in code like this, but its the concept I'm dealing with here) and compare the 4 coordinates surrounding the current point in the contour data grid you are calculating. If any of the 4 points are in a different interval range, then that 'pixel' in the contour grid should be set to true (or the value of the contour range being crossed).
With this method, there will be a problem when the interval is too fine which will cause several contours to overlap onto each other.
As the link from Paul Tomblin suggests, Bezier curves (which are a subset of B-splines) are a ripe solution for your problem. If runtime performance is an issue, Bezier curves have the added benefit of being constructable via the very fast de Casteljau algorithm, instead of drawing them according to the parametric equations. On the off chance you're working with DirectX, it has a library function for the de Casteljau, but it should not be challenging to brew one yourself using the 1001 web pages that describe it.