Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
453 views
in Technique[技术] by (71.8m points)

iphone - How do I detect a touch on a UIBezierPath and move a ball along that?

How do I move a ball along a specific UiBezierPath? Is that possible?

I've tried everything including doing a hit test using

-(BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath*)path inFillArea:(BOOL)inFill

How do I detect a touch along a path?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Firstly ... it is an absolute fact that:

there is, definitely, NO method, provided by Apple,
to extract points from a UIBezierPath
.

That is an absolute fact as of February 2011, in the latest OS, and everything just on the horizon. I've spoken to the relevant engineers at Apple about the issue. It's annoying in many game programming contexts, but that's the fact. So, it could be that answers your question?

Secondly: don't forget it's as easy as pie to animate something along a UIBezierPath. There are numerous answers on SO, for example How can I animate the movement of a view or image along a curved path?

Thirdly: Regarding finding out where touches happened, if that's what you're asking, as Cory said, this is a hard problem! But you can use CGContextPathContainsPoint to find out if a point (or touch) was on a path of a given thickness.

After that, assuming we are talking about cubics, you need to find points and likely velocities (a.k.a. tangents) along a bezier.

Here is the exact, total code to do that: Find the tangent of a point on a cubic bezier curve (on an iPhone). I pasted it in below, too.

You will have to implement your own MCsim or iteration to find where it hit, depending on your situation. That's not so hard.

(Fourthly -- as a footnote, there's that new thing where you can progressively draw a bezpath, probably not relevant to your question but just a note.)


For the convenience of anyone reading in the future, here is the summary from the linked question of the two "handy" routines...

Finally, here in the simplest possible fashion are the two routines to calculate equidistant points (in fact, approximately equidistant) and the tangents of those, along a bezier cubic:

CGFloat bezierPoint(CGFloat t, CGFloat a, CGFloat b, CGFloat c, CGFloat d)
    {
    CGFloat C1 = ( d - (3.0 * c) + (3.0 * b) - a );
    CGFloat C2 = ( (3.0 * c) - (6.0 * b) + (3.0 * a) );
    CGFloat C3 = ( (3.0 * b) - (3.0 * a) );
    CGFloat C4 = ( a );

    return ( C1*t*t*t + C2*t*t + C3*t + C4  );
    }

CGFloat bezierTangent(CGFloat t, CGFloat a, CGFloat b, CGFloat c, CGFloat d)
    {
    CGFloat C1 = ( d - (3.0 * c) + (3.0 * b) - a );
    CGFloat C2 = ( (3.0 * c) - (6.0 * b) + (3.0 * a) );
    CGFloat C3 = ( (3.0 * b) - (3.0 * a) );
    CGFloat C4 = ( a );

    return ( ( 3.0 * C1 * t* t ) + ( 2.0 * C2 * t ) + C3 );
    }

The four precalculated values, C1 C2 C3 C4, are sometimes called the coefficients of the bezier. (Recall that a b c d are usually called the four control points.) Of course, t runs from 0 to 1, perhaps for example every 0.05. Simply call these routines once for X and separately once for Y. Hope it helps someone!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...