gpt4 book ai didi

ios - 展平 CGPath

转载 作者:可可西里 更新时间:2023-11-01 05:13:06 30 4
gpt4 key购买 nike

简单地说,我正在寻找可在 iOS 上使用的与 NSBezierPath 的 -bezierPathByFlatteningPath 等效的方法。这对我来说是直接处理 CGPath 的函数还是 UIBezierPath 上的方法并不重要,因为两者可以轻松地来回转换。 CGPath Reference 都不是也不是 UIBezierPath Class Reference指示任何此类功能或方法的存在。

此外:我知道 CGPath 的 CGPathApply 函数,但我缺乏时间和技能来通过遍历 CGPathApplierFunction 中的路径元素来实现我自己的展平算法。我正在寻找对此的现有解决方案 - 应用程序函数、UIBezierPath 上的类别等。肯定存在一个。

最佳答案

Erica Sadun 提供了一组有用的函数来处理 UIBezierPath 和 CGPathRef。

此代码用于 this book .

她没有提供 CGPathRef 扁平化的实现,但可以使用可在此处找到的函数轻松完成: https://github.com/erica/iOS-Drawing/blob/master/C05/Quartz%20Book%20Pack/Bezier/BezierFunctions.m

特别是,这些函数将有助于离散化非线性贝塞尔曲线段:

float CubicBezier(float t, float start, float c1, float c2, float end)
float QuadBezier(float t, float start, float c1, float end)
CGPoint CubicBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint c2, CGPoint end);
CGPoint QuadBezierPoint(CGFloat t, CGPoint start, CGPoint c1, CGPoint end);

所以基本上,初始化一个空的 CGMutablePathRef,并且对于原始路径中的每个 CGPath 元素,如果它是线性的则复制它,或者根据贝塞尔曲线段的程度将其离散化。

您可能还想应用 Ramer–Douglas–Peucker algorithm删除不必要的点。

您也可以直接使用:- (NSArray *) interpolatedPathPoints 它返回一个 NSArray 点,可用于构建路径的近似值。该算法是幼稚的,因此您必须在这种情况下简化结果,例如,三次贝塞尔曲线路径是线性的(如果控制点对齐);和以前一样,Ramer-Douglas-Peucker 算法完成了这项工作。

这是实际离散化的样子。代码不是自包含的,您必须使用所有依赖项。

- (NSArray *) interpolatedPathPoints
{
NSMutableArray *points = [NSMutableArray array];
BezierElement *current = nil;
int overkill = 3;
for (BezierElement *element in self.elements)
{
switch (element.elementType)
{
case kCGPathElementMoveToPoint:
case kCGPathElementAddLineToPoint:
[points addObject:[NSValue valueWithCGPoint:element.point]];
current = element;
break;
case kCGPathElementCloseSubpath:
current = nil;
break;
case kCGPathElementAddCurveToPoint:
{
for (int i = 1; i < NUMBER_OF_BEZIER_SAMPLES * overkill; i++)
{
CGFloat percent = (CGFloat) i / (CGFloat) (NUMBER_OF_BEZIER_SAMPLES * overkill);
CGPoint p = CubicBezierPoint(percent, current.point, element.controlPoint1, element.controlPoint2, element.point);
[points addObject:[NSValue valueWithCGPoint:p]];
}
[points addObject:[NSValue valueWithCGPoint:element.point]];
current = element;
break;
}
case kCGPathElementAddQuadCurveToPoint:
{
for (int i = 1; i < NUMBER_OF_BEZIER_SAMPLES * overkill; i++)
{
CGFloat percent = (CGFloat) i / (CGFloat) (NUMBER_OF_BEZIER_SAMPLES * overkill);
CGPoint p = QuadBezierPoint(percent, current.point, element.controlPoint1, element.point);
[points addObject:[NSValue valueWithCGPoint:p]];
}
[points addObject:[NSValue valueWithCGPoint:element.point]];
current = element;
break;
}
}
}
return points;
}

代码属于 Erica Sadun。有关完整的实现,请参见此处:https://github.com/erica/iOS-Drawing

Rob Napier 还在 iOS 6 Pushing the limits 中写了关于贝塞尔曲线的文章, 第 26 章花哨的文本布局。他并没有试图展平一个完整的 UIBezierPath,只有一个用四个点定义的立方贝塞尔路径,但实际上这完全是一回事(离散化贝塞尔路径)此外,您可能会发现这篇文章很有趣:http://robnapier.net/faster-bezier

关于ios - 展平 CGPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18858011/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com