Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective C Bezier Curve ReShaping

I want to be able to reposition and reshape a cubic bezier curve drawn in Core Graphics by touching it and dragging it. I can draw the basic shape and I can use touch and drag to move the WHOLE of the shape but this isnt what I want to be able to do.

What I want is to be able to move and reshape the bezier curve it as if it were a piece of string lying on a table being pulled around by my finger. Ie touching on part of the bezier curve and pulling it in a direction to change the shape of the curve overall.

Does anyone know how to do this? Any help would be very welcome.

Thanks in advance

like image 417
MiltsInit Avatar asked Feb 13 '12 15:02

MiltsInit


Video Answer


1 Answers

It is fairly easy to draw the control points and allow the user to drag them around. Unfortunately, the curve does not pass through all the control points, so the experience does not quite match what you're suggesting.

To do what you're suggesting, you first need to answer the question "is the user touching the curve?" This is the same as the question "is a given point within a certain distance of the curve." That is not a trivial question, but it can be calculated. Probably the simplest approach is to just calculate X points along the curve (where X is sufficiently high to give you reasonable precision), and check the distance for each. In principle, you could also take the derivative of the distance equation and solve it for its zeros, but this requires iteration. In my experience you can calculate the needed 1000 or so distances quickly enough (even on an iPad 1) that it may not be worth the extra complexity.

Once you find that the user is in fact touching the curve, it's easy to figure out which control point is closest. The hard thing at this point is deciding what to do about it. Some options:

  • Move the closest control point in the direction that the user is moving. You may need to do multiple calculations until you find a new curve that passes through the touch point. This is the simplest approach and probably where I'd start.
  • You could subdivide the curve at the touched point and move the newly created endpoints. (See De Casteljau's algorithm for this.)This will tend to create sharp corners unless you adjust the other control points to create matched slopes. This allows for more arbitrary curves, but it could become very hard to know what the user really wanted. You'd also almost certainly need to apply Ramer-Douglas-Peucker to keep your number of curves from exploding.

I'm currently quite interested in Bézier curve problems in Objective-C. You may be interested in my first post on the subject. My initial work in this area is available on GitHub in the iOS:PTL sample code. Hopefully I'll have another post up this week. Your particular problem is interesting, so I may see what I can build around that.

like image 108
Rob Napier Avatar answered Oct 19 '22 20:10

Rob Napier