web-dev-qa-db-ja.com

addArcWithCenterに0度のstartAngleを指定すると、90度で開始するのはなぜですか?

CAShapeLayerのレイヤーのマスクとして使用するUIViewを作成しています。 UIBezierPathを使用してシェイプレイヤーを描画しています。描画したときに奇妙な結果が得られることを除いて、正常に機能しています。ジオメトリが期待どおりに動作していません。右上隅に単純な「パイスライス」を描画しようとしています。

#define degreesToRadians(x) ((x) * M_PI / 180.0)

...

// "layer" refer's to the UIView's root layer

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame =
    layer.presentationLayer ? 
    ((CAGradientLayer *)layer.presentationLayer).bounds : layer.bounds;
maskLayer.fillRule = kCAFillRuleEvenOdd;
maskLayer.needsDisplayOnBoundsChange = YES;

CGFloat maskLayerWidth = maskLayer.bounds.size.width;
CGFloat maskLayerHeight = maskLayer.bounds.size.height;
CGPoint maskLayerCenter = 
    CGPointMake(maskLayerWidth/2,maskLayerHeight/2);

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:maskLayerCenter];

[path addArcWithCenter:maskLayerCenter radius:(maskLayerWidth/2)
startAngle:degreesToRadians(0) endAngle:degreesToRadians(90) clockwise:YES];

[path closePath];


maskLayer.path = path.CGPath;

layer.mask = maskLayer;

最終結果は、パイスライスが右下隅に描画されることです。円弧の最初の点は90度で描画され、次に180度まで描画されます。0度と90度の角度を使用しているのに、なぜこれを行うのですか?

22
zakdances

この画像は ドキュメント から直接来ています。

image

そして、それがどのように機能するかについての議論があります(デフォルトの座標系が与えられた場合)

ディスカッション
このメソッドは、現在のポイントから始まる指定された円弧を追加します。作成された円弧は、指定された円の周囲にあります。デフォルトの座標系で描画された場合、開始角度と終了角度は、図1に示されている単位円に基づいています。たとえば、開始角度を0ラジアン、終了角度をπラジアンに指定し、時計回りのパラメーターをYESに設定すると、円の下半分が描画されます。ただし、同じ開始角度と終了角度を指定し、clockwiseパラメータをNOに設定すると、円の上半分が描画されます。

これがaddArcWithCenter:radius:startAngle:endAngle:clockwise:の角度の仕組みです。それがあなたが見ているものではない場合、あなたはあなたの角度を間違って計算しています。

73

bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise: ドキュメントの図1をご覧ください:「パイスライスの場合"右上隅でパラメータを使用する必要があります

startAngle:degreesToRadians(-90) endAngle:0 clockwise:YES

(その理由は、iOSのデフォルトの座標系では、x軸が右向きで、y軸が下向きであるためです。)

9
Martin R