Erica Sadun は、UIBezierPath と CGPathRef を処理するための一連の便利な関数を提供しています。
このコードは本書で使用されています。
彼女は 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 アルゴリズムを適用して不要な点を削除することもできます。
次を直接使用することもできます。- (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;
}
コードはエリカ・サドゥンのものです。完全な実装については、https ://github.com/erica/iOS-Drawing を参照してください。
Rob Napier は、 iOS 6 Pushing the limitsの Chapter 26 Fancy Text Layoutでベジエ曲線についても書いています。彼は完全な UIBezierPath を平坦化しようとしているのではなく、4 つのポイントで定義された 1 つのキュービック ベジェ パスのみをフラット化しようとしていましたが、実際にはまったく同じことです (ベジェ パスの離散化) 。高速ベジェ