Preservar el ancho de línea, mientras que todos los puntos de escala en el contexto con CGAffineTransform
-
22-09-2019 - |
Pregunta
Tengo un CGPath
en algún sistema de coordenadas que me gusta dibujar. Si lo hace, implica la ampliación del sistema de coordenadas de edad en uno del Contexto. A tal fin, yo uso CGContextConcatCTM()
la que hace transformar todos los puntos como debería. Pero, ya que es una operación de escalado, la horizontal / ancho de las líneas verticales se ve modificado a. P.ej. una escala de 10 en la dirección x, pero de 1 en la dirección y conducirían a líneas verticales que son 10 veces tan gruesa como las horizontales. ¿Hay una manera de mantener la facilidad de uso de matrices de traducción (por ejemplo, CGAffineTransform
) pero no escalar anchos de línea, al mismo tiempo, por ejemplo, una función como CGPathApplyAffineTransformToPoints
?
Saludos
MrMage
Solución
Se puede utilizar CGPathApply
para iterar a través de los elementos en un camino. Es un poco más complejo que una simple de una sola línea, pero si se empaqueta en una función auxiliar simple, que podría ser útil para usted. Aquí es una versión que crea un nuevo camino y lo 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 usarlo lo haría (esta es la parte que me gustaría poner dentro de una función de ayuda):
PathTransformInfo info;
info.path = CGPathCreateMutable();
info.transform = CGAffineTransformMakeScale(2, 1);
CGPathApply(originalPath, &info, PathTransformer);
La ruta transformada es en info.path
en este punto.
Otros consejos
Foro de la transformada cuando se agrega el camino, pero a continuación, retire la transformada antes de contornear el trazado. En lugar de esto:
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
Haga lo siguiente:
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);