Сохраняйте ширину линии при масштабировании всех точек в контексте с помощью CGAffineTransform.

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

Вопрос

у меня есть CGPath в некоторой системе координат, которую я хотел бы нарисовать.Для этого необходимо масштабировать старую систему координат на систему контекста.Для этой цели я использую CGContextConcatCTM() который преобразует все точки должным образом.Но, поскольку это операция масштабирования, ширина горизонтальной/вертикальной линии изменяется на.Например.масштаб 10 по оси x и 1 по оси y приведет к тому, что вертикальные линии будут в 10 раз толще горизонтальных.Есть ли способ сохранить простоту использования матриц перевода (например, CGAffineTransform), но не масштабируя при этом ширину линий, например.функция типа CGPathApplyAffineTransformToPoints?

Ваше здоровье

Мистер Маг

Это было полезно?

Решение

Вы можете использовать CGPathApply для перебора элементов пути.Это немного сложнее, чем просто однострочный код, но если вы упаковаете его в простую вспомогательную функцию, это может оказаться для вас полезным.Вот одна из версий, которая создает новый путь и преобразует его:

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