如何获得CGPath曲线或四边形曲线中的所有点

时间:2009-05-08 18:14:55

标签: iphone cocoa core-animation core-graphics bezier

我使用方法CGPathAddQuadCurveToPoint制作了四条曲线路径。我完美地完成了这条道路。但是,我想知道参与路径的所有坐标点。

有没有办法检索路径中的所有坐标点?

如果没有,你有任何其他方法可以用数学方法检索曲线中的所有点。

提前致谢, Vamshi

6 个答案:

答案 0 :(得分:14)

您可以使用wykobi C ++库例程来实现三次贝塞尔曲线。 Wykobi的库也支持二次贝塞尔曲线。

当然有人指出你不想要所有的要点(虽然不是不可能的,但它只需要无限的时间:)。 Wykobi可以轻松获得一定数量的积分 - 如果你的开始,c1,c2和终点(其中c1,c2是控制点)与给予CGContextAddCurveToPoint的那些点完全相同那么这些积分将完美无缺在核心图形绘制的线上 - 所以你可以做一些事情,比如在路径上的几个点画一个图案。

请参阅:http://www.codeproject.com/Articles/22568/Computational-Geometry-C-and-Wykobi

此外,在我开始使用wykobi之后,我听说有一个类似的,甚至更好的库是Boost的一部分,但还没有检查过它。

我创建了一个C ++类WPoint作为wykobi点和CGPoints之间的桥梁(C ++有趣!)。这里有一些代码(没有WPoint,但你可以想象它与CGPoint的布局完全相同,所以如果你做了正确的演员,你可以轻松转换。

        NSMutableArray* result = [[NSMutableArray alloc] init];
        wykobi::cubic_bezier<CGFloat,2> bezier;
        bezier[0] = (WPoint)p1;  // start point, in CG we did a CGMoveToPoint
        bezier[1] = (WPoint)b1i; // control 1
        bezier[2] = (WPoint)b2i; // control 2
        bezier[3] = (WPoint)p2;  // end point

        std::vector<WPoint> point_list;
        int numPoints = p2.dist(p3) * pointDensity;
        // *** here's the magic ***
        wykobi::generate_bezier(bezier,std::back_inserter(point_list), numPoints);

        for (int i=0; i<numPoints; i++) {
            CGPoint p = (CGPoint)(point_list[i]);
            [result addObject:[NSValue valueWithCGPoint:p]];
        }

// result has your points!

这是Boost几何库的链接: http://www.boost.org/doc/libs/1_47_0/libs/geometry/doc/html/geometry/introduction.html

答案 1 :(得分:2)

使用CGContextSetLineDash

此功能的目的是创建一条虚线,但您可以使用它来获取较小的线段。 每个段的起点可以视为点。

CGSize bbSize = CGPathGetBoundingBox(path).size;
UIGraphicsBeginImageContext(bbSize);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, 1.0);
CGContextAddPath(ctx, path);
CGContextSetLineDash(ctx, phase, lengths, count);
CGContextReplacePathWithStrokedPath(ctx);
result = CGContextCopyPath(ctx);
UIGraphicsEndImageContext();

答案 2 :(得分:1)

如果您想处理路径的moveto,lineto和curveto元素,请使用CGPathApply。您将此指针传递给程序中的函数,并且每个元素都会调用该函数一次。

不幸的是,没有办法像AppKit的NSBezierPath那样只询问每个元素。功能是唯一的方法。

如果你想确定路径相交的每个像素,那太糟糕了 - 这是不切实际的,我甚至无法想到你为什么要这些信息。某些上下文(例如PDF contexts)甚至没有像素;在这些情况下,任何涉及像素的问题都是不合理的。

答案 3 :(得分:0)

二次曲线就是 - 曲线。它不可能得到所有点的列表,因为它有无限多的点,而且它不是一个简单的线段。

有关可用于查询CGPath对象的函数列表,请参阅Getting Information about Quartz Paths。不幸的是,看起来您将获得的最有用的信息是CGPathContainsPoint(),它只会告诉您某个点是否包含在路径区域内。

答案 4 :(得分:0)

如果没有,你还有其他解决办法以数学方式检索曲线中的所有点。

你需要什么,比如你想解决什么问题?如果要交叉两条曲线,可以用数学方法完成。只需将两个曲线方程设置为彼此相等并求解未知数。

答案 5 :(得分:0)

我猜你是在追求与Java2D FlatteningPathIterator类相同的东西。例如,Java2D的path.getPathIterator(null, 1.0)只返回'lineTo'段的迭代器,即使原始路径有curveTo和quadTo,double参数控制'flatness',这使您可以轻松计算曲线上的任何点。 我在Cocoa中寻找相同的东西,但一无所获。如果您找到解决方案,请告诉我。 可以移植(例如http://sourceforge.net/projects/curves/)周围的曲线实现,但是如果你不使用与Cocoa相同的算法,那么你的插值和描边的NSBezierPath / CGPath之间可能存在错误。