CGAffineTransform を使用してコンテキスト内のすべてのポイントをスケーリングしながら線幅を維持します

StackOverflow https://stackoverflow.com/questions/1798441

質問

私は持っています CGPath 描画したい座標系で。これには、古い座標系をコンテキストの座標系にスケール変更することが含まれます。その目的のために、私が使用するのは、 CGContextConcatCTM() これにより、すべてのポイントが適切に変換されます。ただし、拡大縮小操作なので、水平/垂直の線幅が変更されます。例えば。x 方向のスケールが 10 ですが、y 方向のスケールが 1 の場合、垂直線の太さは水平線の 10 倍になります。翻訳行列の使いやすさを維持する方法はありますか (例: CGAffineTransform)ただし、同時に線幅をスケーリングすることはありません。のような関数 CGPathApplyAffineTransformToPoints?

乾杯

ミスターメイジ

役に立ちましたか?

解決

あなたは、パス内の要素を反復処理するCGPathApplyを使用することができます。これは、もう少し複雑なだけでワンライナーよりますが、あなたは、単純なヘルパー関数でそれをパッケージ化した場合、それはあなたのために役に立つかもしれません。

:ここに新しいパスを作成し、それを変換バージョンは1つです
typedef struct {
    CGMutablePathRef path;
    CGAffineTransform transform;
} PathTransformInfo;

static void
PathTransformer(void *info, const CGPathElement *element)
{
    PathTransformInfo *transformerInfo = info;

    switch (element->type) {
        case kCGPathElementMoveToPoint:
            CGPathMoveToPoint(transformerInfo->path, &transformerInfo->transform,
                              element->points[0].x, element->points[0].y);
            break;

        case kCGPathElementAddLineToPoint:
            CGPathAddLineToPoint(transformerInfo->path, &transformerInfo->transform,
                                 element->points[0].x, element->points[0].y);
            break;

        case kCGPathElementAddQuadCurveToPoint:
            CGPathAddQuadCurveToPoint(transformerInfo->path, &transformerInfo->transform,
                                      element->points[0].x, element->points[0].y,
                                      element->points[1].x, element->points[1].y);
            break;

        case kCGPathElementAddCurveToPoint:
            CGPathAddCurveToPoint(transformerInfo->path, &transformerInfo->transform,
                                  element->points[0].x, element->points[0].y,
                                  element->points[1].x, element->points[1].y,
                                  element->points[2].x, element->points[2].y);
            break;
        case kCGPathElementCloseSubpath:
            CGPathCloseSubpath(transformerInfo->path);
            break;
    }
}

(これは私がヘルパー関数の内部で置く部分です)、あなたはどうしたらそれを使用します:

    PathTransformInfo info;
    info.path = CGPathCreateMutable();
    info.transform = CGAffineTransformMakeScale(2, 1);

    CGPathApply(originalPath, &info,  PathTransformer);

形質転換されたパスは、この時点でinfo.pathである。

他のヒント

あなたがパスを追加するときに変換するが、その後、あなたのストロークのパスの前に変換削除してください。これに代えます:

CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 10, 10);   // scale path 10x

CGContextAddPath(ctx, somePath);

CGContextSetStrokeColorWithColor(ctx, someColor);
CGContextSetLineWidth(ctx, someWidth);   // uh-oh, line width is 10x, too
CGContextStrokePath(ctx);

CGContextRestoreGState(ctx);      // back to normal

これを行います:

CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 10, 10);   // scale path 10x

CGContextAddPath(ctx, somePath);

CGContextRestoreGState(ctx);      // back to normal

CGContextSetStrokeColorWithColor(ctx, someColor);
CGContextSetLineWidth(ctx, someWidth);
CGContextStrokePath(ctx);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top