Drawing a bezier from multiple points - iphone

I have a set with 50 points in x,y. I need to draw the smoothest bezier that passes in all points, or in other words, the bezier that will best fit the points.
How do I do that? thanks

I am undergoing a similar problem in 3D. It is slightly easier in 2D because lines will always intersect if not parallel.
Firstly, read up on quadratic bezier curves. Each curve is represented by three points. The line will not pass through the middle point. Thus, your middle point cannot be one of the points you are trying to fit, or it won't go through it.
Instead, the beginning and end point of your quadratic bezier curve must be two consecutive points you want it to pass through. So what is your middle point going to be?
One way of solving this (never tried it myself HENCE it might not look perfect, but Im thinking off the top of my head) is to calculate the tangents from your -1st data point to your 0th data point, and find the intersection between that and the 1st data point to the 2nd data point. Then draw the line between the 0th data point and the 1st data point using this intersection as the middle bezier curve value.
Obviously you may have trouble at the ends of the curves, that may require some inventive thinking to make them look good. (the first point has no -1st point).
Sorry about the lack of diagrams. I would draw one but I'm on an iPad.

Imagine 3-point bezier curve (start-A, middle-B, end-C)
Imagine a straight line from A to C.
Imagine a straight line that is perpendicular to AC and goes through point B.
Those two lines cross in point D.
Bezier curve will go through EXACTLY half way from D to B. In other words if you want bezier curve that goes through 3 points, you must make the second point 2 times further from start and end than the actual second point.

Related

Can I compute contour orientation without using polygon area sign?

Most of the times, I determine contour orientation generating 2D points and computing the closed polygon area. Depending on the area value sign I can understand if the contour is oriented clockwise or not (see How to determine if a list of polygon points are in clockwise order?).
Would it be possible to do the same computations without generating 2D points? I mean, relying only on geometric curve properties?
We are interested in determining the orientation of contours like these ones without sampling them with 2D points.
EDIT: Some interesting solutions can be found here:
https://math.stackexchange.com/questions/423718/general-way-to-find-out-whether-a-curve-is-positively-oriented
Scientific paper: Determining the orientation of closed planar curves, DJ Filip (1990)
How are those geometric curves defined?
Do you have an angle for them? The radius doesn't matter, only the difference between entry-angle and exit-angle of each curve.
In that case, a trivial idea crossing my mind is to just sum up all the angles. If the result is positive, you know you had more curves towards the right meaning it's a clockwise contour. If it was negative, then more curves were leftwards -> anti-clockwise contour. (assuming that positive angels determine a right-curve and vica versa)
After thinking about this for awhile, for polygons that contain arcs I think there are three ways to do this.
One, is to break the arcs into line segments and then use the area formula as described above. The success of this approach seems to be tied to how close the interpolation of the arcs is as this could cause the polygon to intersect itself.
A quicker way than the above would be to do the interpolation of the arcs and then find a vertex in the corner (minimal Y, if tie minimal X) and use the sign of the cross product for that vertex. Positive CCW, negative CW. Again, this is still tied to the accuracy of the interpolation.
I think a better approach would be to find the midpoint of the arc and create two line segments, one from the beginning of the arc to the midpoint and another from the midpoint to the end of the arc and replace the arc with these line segments. Now you have a polygon with only line segments. Then you can add up all the normalized cross products of all the vertices. The sign will tell you the direction. Positive is counter-clockwise, negative is clockwise. In this case it doesn't matter if the polygon self-intersects.

how to perform hough transformfor finding hand curve

hi i want to detect fingertips point and valleypoint of hand by using hough transform.Simply the Question is what is the [H,theta,rho]=hough(BW) is good for extract these point.
the image is here:
https://www.dropbox.com/sh/n1lz7b5eedzbui7/AADwy5O1l7sWf5aOx7KWAmhOa?dl=0
tnx
The standard hough transformation is just for detecting straight lines. Not more and not less. The Matlab function hough (please see here) returns the so-called hough space H, a parametric space which is used to find these lines and the parametric representation of each line: rho = x*cos(theta) + y*sin(theta).
You will have to do more than this to detect your desired points. Since your fingers usually won't consist of straight lines, I think you should think of something else anyway, e.g. if you can assume such a perfect curve as the one in your image maybe this is interesting for you.
Another simple technique you might consider is to compare the straight line distance between two points on your hand line to the distance between those two points along the perimeter (geodesic distance). For this you would need an ordered list of points along the perimeter.
Along regions of high curvature, the straight line distance between two points will be smaller than the number of pixels between those two points along the perimeter.
For example, you could check perimeter pixels separate by 10 pixels. That is, you would search through the list and compare the point at index N and the point index N+10. (You'll need to loop back around to the beginning of the list as you approach the end.) If the straight line distance between these two points is nearly 10 pixels as well, then you know those points lie on a straight section of the perimeter. If the straight line distance is much smaller than 10, then you know the perimeter curves in some fashion between those points. Whether you check pixels that are 5, 10, 20, or 30 items apart in the list will depend on the resolution of your image and the curves you're looking for.
This technique is useful because it's simple and quick to implement. Maybe it would work well enough for your needs.
Yet another way: simplify the outline to small line segments, and then you can calculate the line-line angle between adjacent segments. To simplify the curves, implement the Ramer-Douglas-Puecker algorithm. A little experimentation will reveal what parameter settings will work for your application.
https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
Finally, you could look into piecewise curve fitting: a curve would be fitted to small segments of the outline. This can get very complicated, and researchers continue to find ways to decompose complex figures into a limited number of more basic shapes or curves. I recommend trying the simplest technique and then only adding complexity if you need it.

Given a CGPath, how to make it curve?

In the following screen shot:
when you drag the tail of the word balloon (the thing that connects from the balloon to the persons mouth), the shape curves (as illustrated by the difference between the two balloon tails in the picture). I'm wondering, how is this done? I'm assuming you need to start with a CGPath and do something to it, does anyone happen to know what this is?
Update: So if I wanted to curve the following shape:
Would I use the following code:
CGPathAddCurveToPoint(mutablePath, NULL, x1, y1, x2, y2 + constant, x5, y5);
CGPathAddCurveToPoint(mutablePath, NULL, x3, y3, x4, y4 + constant, x5, y5);
Where the constant readjusts the y position of point 2 and point 4 to make the curve?
You need to exploit the fact that, mathematically, a straight-line segment is just a kind of curve segment.
(It's easier than it sounds, trust me.)
Bézier path segments have something called “order” that essentially determines how many points there are in the segment, not counting the point you're coming from.
A straight-line segment is a first-order curve, meaning that it only has the destination point. These “curves” are always straight lines because there are no control points to curve toward.
Quadratic curves are second-order curves (one control point plus the destination).
Cubic curves are third-order curves (two control points).
(The math doesn't put any limit on this, but Quartz stops here. No fourth-order curves for you without rolling your own rasterizer.)
This matters because any lower-order curve—including a straight line—can be expressed as a higher-order curve.
So, the secret?
For even a straight tail, use a curve.
(Namely, a cubic curve, since you want the curve going in two different directions: One, more or less into the tail, and the other, more or less along the edge of the balloon.)
From each of the two points at the base of the tail, you want one of the control points to be about halfway to the destination. This much is unconditional.
The direction of each of the control points gives you three options:
The straight-out tail
Notice the two control points along the blue line at the vertical center of the image.
Notice the direction of these two control points, relative to the base point it's connected to. They are angled inward, toward the tip—indeed, exactly on the straight line to the tip.
The oblique tail
Here, the tip point is no longer horizontally between the two base points. The control points have moved, but only to follow: each one is still halfway along the straight line between the corresponding base point and the tip.
The curved tail
For a curved tail, you move the tip, but you keep the control points at the same position as for a straight tail. Thus, the tail starts out straight out (following the control points), but as it gets farther from the base points, their influence wanes, and the tail begins curving toward the tip.
This is a lot easier to describe visually than to put into code, so you may want to consider using something like PaintCode or Opacity to draw each kind of tail using a pen tool and then see what the code they generate for it looks like.
You can use the CGContextAddCurveToPoint() functions:
CGContextMoveToPoint(ctx, x, y);
CGContextAddCurveToPoint(ctx, outTangentX, outTangentY, inTangentX, inTangentY, newX, newY);
... // more points or whatever you need here
CGContextFillPath(ctx); // Fill with white
CGContextStrokePath(ctx); // stroke the edges with black
The in/out tangents can be hardcoded to be something that looks good based on the point on the mouth of the picture and the point where it meets the balloon bubble. You might try something like making their angles half-way between perpendicular and the slope of the straight line between the 2 points or something like that as a starting place.

Fast way to convert array of points into triangle strip?

I have an array of CGPoints (basic struct with two floats: x and y). I want to use OpenGL ES to draw a textured curve using these points. I can do this fine with just two points, but it gets harder when I need to make a line from several points.
Currently I draw a line horizontally, calculate its angle from the points given, and then rotate it. I don't think doing this for all lines in a curve is a good idea. There's probably a faster way.
I'm thinking that I can "enlarge" or "constrict" all the points at once to make a curve with some sort of width.
I'm not positive what you want to accomplish, but consider this:
Based on a ordered list of points, you can draw a polyline using those points. If you want to have a polyline with a 2D texture on it, you can draw a series of quadrilaterals (using two triangles each, of course). You can generate these quadrilaterals using an idea similar to catmul-rom spline generation.
Consider a series of points p[i-1], p[i], p[i+1]. Now, for each i, you can find two points each an epsilon distance away from p[i] along the line perpendicular to the line connecting p[i-1] and p[i+1]. You can determine the two points generated for the endpoints in various ways, like using the perpendicular to the line from p[0] to p[1].
I'm not sure if this will be faster than your method, but you should be caching the results. If you are planning on doing this every frame, another type of solution to your problem may be needed.

how can i trace the finger movement on touch for drawing smooth curves?

like what i want is if i move my finger fast on the iphone screen , then i want like something that it make a proper curve using quartz 2d or opengl es whatever.
i want to draw a path in curve style......
i had seen that GLPaint(OpenglES) example ,but it will not help me alot , considering if your finger movement is fast.....
something like making a smooth curve.....
any one have some kind of example please tell me
thanks
Edit: Moved from answer below:
thanks to all.......
but i had tried the bezier curve algo with two control points but problem is first how to calculate the control points whether there is no predefined points....
as i mentioned my movement of finger is fast...... so most of the time i got straight line instead of curve, due to getting less number of touch points.......
now as mark said piecewise fashion, ihad tried it like considering first four touch points and render them on screen , then remove the first point then again go for next four points ex. step 1: 1,2,3,4 step 2: 2,3,4,5 like that where as in that approach i got an overlap , which is not the issue actually , but didn't get smooth curve........
but for fast movement of finger i have to find something else?????
Depending on the number of sample points you are looking at, there are two approaches that I would recommend:
Simple Interpolation
You can simply sample the finger location at set intervals and then interpolate the sample points using something like a Catmull-Rom spline. This is easier than it sounds since you can easily convert a Catmull-Rom spline into a series of cubic Bezier curves.
Here's how. Say you have four consecutive sample points P0, P1, P2 and P3, the cubic Bezier curve that connects P1 to P2 is defined by the following control points:
B0 = P1
B1 = P1 + (P2 - P0)/6
B3 = P2 + (P1 - P3)/6
B4 = P2
This should work well as long as your sample points aren't too dense and it's super easy. The only problem might be at the beginning and end of your samples since the first and last sample point aren't interpolated in an open curve. One common work-around is to double-up your first and last sample point so that you have enough points for the curve to pass through each of the original samples.
To get an idea of how Catmull-Rom curves look, you can try out this Java applet demonstrating Catmull-Rom splines.
Fit a curve to your samples
A more advance (and more difficult) approach would be to do a Least Squares approximation to your sample points. If you want try this, the procedure looks something like the following:
Collect sample points
Define a NURBS curve (including its knot vector)
Set up a system of linear equations for the samples & curve
Solve the system in the Least Squares sense
Assuming you can pick a reasonable NURBS knot vector, this will give you a NURBS curve that closely approximates your sample points, minimizing the squared distance between the samples and your curve. The NURBS curve can even be decomposed into a series of Bezier curves if needed.
If you decide to explore this approach, then the book "Curves and Surfaces for CAGD" by Gerald Farin, or a similar reference, would be very helpful. In the 5th edition of Farin's book, section 9.2 deals specifically with this problem. Section 7.8 shows how to do this with a Bezier curve, but you'd probably need a high-degree curve to get a good fit.
Naaff gives a great overview of the NURBS technique. Unfortunately, I think generating a smooth bezier on-the-fly might be too much for the iPhone. I write drawing apps, and getting a large number of touchesMoved events per second is quite a challenge to begin with. You really need to optimize your drawing code just to get good performance while recording individual points - much less constructing a bezier path.
If you end up going with a bezier or NURBS curve representation - you'll probably have to wait until the user has finished touching the screen to compute the smoothed path. Doing the math continuously as the user moves their finger (and then redrawing the entire recomputed path using Quartz) is not going to give you a high enough data collection rate to do anything useful...
Good luck!
Do something like Shadow suggested. Get the position of the touch with some frequency and then make a Bézier curve out of it. This is how paths are drawn with a mouse (or tablet) in programs like Illustrator.