Get points from a UIBezierPath

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-30 09:31:01

It should be possible to get points along a Bezier path as addQuadCurveToPoint is to add a quadratic Bezier segment into the path. So, the three control points of your first quadratic Bezier curve are (refer to the code piece in original post)

P(0) = origin
P(1) = (midpt1.x, midpt1.y+50)
P(2) = location

You can compute as many points on this quadratic Bezier curve as you want by varying the parameter t from 0 to 1 by any small increment value as

C(t) = (1-t)^2*P(0) + 2*t*(1-t)*P(1) + t^2 *P(2)

To get the Y value from a given X value, you will have to solve for the t value from the given X value from this quadratic polynomial of t:

X = (1-t)^2*X0 + 2*t*(1-t)*X1 + t^2 *X2

where X0, X1 and X2 are the X coordinates of P(0), P(1) and P(2), which means X0=origin.x, X1=midpt1.x and X2=location.x.

From this, we can obtain a quadratic equation

(X0-2*X1+X2)t^2 + 2(X1-X0)*t + (X0-X) = 0

You can solve for t using the quadratic formula. If your X0, X1 and X2 values happens to make the coefficient of t^2 term zero, you can solve for t directly as t = (X-X0)/(2*(X1-X0)).

Once you have the t value, you can easily evaluate the corresponding Y value.

CGPath is opaque data types, ie. in this case, we can only get the points on which we define on the creation, like eg. the graph you create, there are only three points that can be obtained.

Like the sample code, you obtain those points using CGPathApply. If you append below code after your codes, it will output 3 points.

    ...
    [shapeLayer setPath:path.CGPath];
    NSMutableArray *keyPoints = [NSMutableArray array];
    CGPathApply(path.CGPath, (__bridge void *)keyPoints, getPointsFromBezier);

    NSLog(@"Points = %@", points);
}

// copied from the sample code.
void getPointsFromBezier(void *info, const CGPathElement *element)
{
    NSMutableArray *bezierPoints = (__bridge NSMutableArray *)info;
    CGPathElementType type = element->type;
    CGPoint *points = element->points;
    if (type != kCGPathElementCloseSubpath)
    {
        if ((type == kCGPathElementAddLineToPoint) ||
            (type == kCGPathElementMoveToPoint))
            [bezierPoints addObject:VALUE(0)];
        else if (type == kCGPathElementAddQuadCurveToPoint)
            [bezierPoints addObject:VALUE(1)];
        else if (type == kCGPathElementAddCurveToPoint)
            [bezierPoints addObject:VALUE(2)];
    }
}

So, in short, you cannot get every single coordinate on that graph like you required given its x/y counterpart.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!