4

この例のように、UIView オブジェクトで Quartz 2D を使用して複数の曲線を描画しています。

<code>CGContextStrokePath</code> で Quartz 2D を使用して描画された 2 つの曲線

これは私が今持っているコードです(制御点の計算やその他のものは省略しています):

for (int i = 1; i < points.count; ++i) {
  CGContextMoveToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );

  // CGContextFillPath(context);
  CGContextStrokePath(context);
}

ここで、曲線の下の領域を塗りつぶしたいと思いますがCGContextFillPath、結果を使用すると次のようになります。

<code>CGContextFillPath</code> で Quartz 2D を使用して塗りつぶされた 2 つの曲線

Quartz 2Dのドキュメントによると、これは理にかなっています:

現在のパスを埋めると、Quartz はパスに含まれる各サブパスが閉じられているかのように動作します。次に、これらの閉じたサブパスを使用して、塗りつぶすピクセルを計算します。

次に、パスを右下隅に移動してパスを閉じようとしましたが、fill メソッドは効果がありません。

CGContextMoveToPoint(context, rect.size.width, rect.size.height);
CGContextClosePath(context);
CGContextFillPath(context);

すべてのサブパスで閉じられたサブエリアだけでなく、曲線の下のエリア全体を埋めるにはどうすればよいですか?

編集:

私は一時的な解決策を見つけました:各サブパスに曲線と2本の垂直線を使用して形状を描画します:

for (int i = 1; i < points.count; ++i) {
  // Draw the curve
  CGContextMoveToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );
  CGContextStrokePath(context);

  // Draw a shape using curve's initial and final points
  CGContextMoveToPoint(context, previousXValue, rect.size.height);
  CGContextAddLineToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );
  CGContextAddLineToPoint(context, xValue, rect.size.height);
  CGContextFillPath(context);
}

これがやり過ぎかどうかはわかりませんので、改善も歓迎します。その上、私はこの結果を得ています:

Quartz 2D を使用して描画された 2 つの曲線で、その下の領域が塗りつぶされています

サブエリアを並べて描画すると、縦線が表示されることに注意してください。どうすればそれを回避できますか?

4

1 に答える 1

3

アイデアは正しいですが、個々の曲線を塗りつぶすのではなく、単一のパスを作成してから塗りつぶす必要があります。したがって、CGContextMoveToPoint左下隅から始めCGContextAddLineToPointて最初の点まで、CGContextAddCurveToPointすべての曲線に対して を実行し、最後にCGContextAddLineToPoint右下隅まで を実行します (適切CGContextClosePathな測定を行うこともできます)。

これは単純化された例で、ポイントの配列があるだけですが、アイデアを示しています。

- (void)drawRect:(CGRect)rect
{
    if (!self.points)
        [self configurePoints];

    DataPoint *point;

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGColorRef color = [[UIColor redColor] CGColor];
    CGContextSetStrokeColorWithColor(context, color);
    CGContextSetFillColorWithColor(context, color);

    point = self.points[0];

    CGContextMoveToPoint(context, point.x, self.bounds.size.height);
    CGContextAddLineToPoint(context, point.x, point.y);

    for (point in self.points)
    {
        // you'd do your CGContextAddCurveToPoint here; I'm just adding lines
        CGContextAddLineToPoint(context, point.x, point.y);
    }

    point = [self.points lastObject];
    CGContextAddLineToPoint(context, point.x, self.bounds.size.height);
    CGContextClosePath(context);

    CGContextDrawPath(context, kCGPathFillStroke);
}
于 2013-04-23T16:47:06.727 に答える