Preservare linea larghezza durante il ridimensionamento tutti i punti nel contesto con CGAffineTransform
-
22-09-2019 - |
Domanda
Ho un CGPath
in qualche sistema di coordinate che mi piacerebbe disegnare. In questo modo comporta il ridimensionamento del vecchio sistema di coordinate su uno del contesto. A tal fine, io uso CGContextConcatCTM()
che fa trasformare tutti i punti come dovrebbe. Ma, in quanto è un operazione di dimensionamento, le larghezze di riga verticale / orizzontale vengono cambiati. Per esempio. una scala 10 in direzione x, ma di 1 in direzione y provocherebbe linee verticali essere 10 volte più spessa come quelli orizzontali. C'è un modo per mantenere la facilità di utilizzo di matrici di traduzione (ad esempio CGAffineTransform
) ma linea non regolante larghezze allo stesso tempo, ad esempio una funzione come CGPathApplyAffineTransformToPoints
?
Saluti
MrMage
Soluzione
È possibile utilizzare CGPathApply
per scorrere gli elementi in un percorso. E 'un po' più complesso di un semplice one-liner, ma se si confezionarlo in una semplice funzione di supporto, potrebbe essere utile per voi. Ecco una versione che crea un nuovo percorso e lo trasforma:
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;
}
}
Per usarlo si farebbe (questa è la parte avrei messo dentro una funzione di supporto):
PathTransformInfo info;
info.path = CGPathCreateMutable();
info.transform = CGAffineTransformMakeScale(2, 1);
CGPathApply(originalPath, &info, PathTransformer);
Il percorso è stato trasformato in in info.path
a questo punto.
Altri suggerimenti
Do la trasformazione quando si aggiunge il percorso, ma poi rimuovere la trasformazione prima di corsa il percorso. Invece di questo:
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
Fare questo:
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);