Pergunta

eu tenho um CGPath Em algum sistema de coordenadas que eu gostaria de desenhar. Isso envolve escalar o antigo sistema de coordenadas para o contexto. Para esse fim, eu uso CGContextConcatCTM() que transforma todos os pontos como deveria. Mas, como é uma operação de escala, as larguras da linha horizontal/vertical são alteradas para. Por exemplo, uma escala de 10 na direção x, mas de 1 na direção y levaria a linhas verticais 10 vezes mais espessa que as horizontais. Existe uma maneira de manter a facilidade de uso de matrizes de tradução (por exemplo CGAffineTransform), mas não as larguras da linha de escala ao mesmo tempo, por exemplo, uma função como CGPathApplyAffineTransformToPoints?

Felicidades

Mrmage

Foi útil?

Solução

Você pode usar CGPathApply para iterar através dos elementos em um caminho. É um pouco mais complexo do que apenas uma linha, mas se você o empacotar em uma função auxiliar simples, poderá ser útil para você. Aqui está uma versão que cria um novo caminho e o transforma:

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;
    }
}

Para usá -lo, você faria (esta é a parte que eu colocaria dentro de uma função ajudante):

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

    CGPathApply(originalPath, &info,  PathTransformer);

O caminho transformado está em info.path neste ponto.

Outras dicas

Faça a transformação quando adicionar o caminho, mas remova a transformação antes de acariciar o caminho. Em vez disso:

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

Fazem isto:

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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top