2009-11-25 30 views
5

J'ai un CGPath dans un système de coordonnées que j'aimerais dessiner. Cela implique de mettre l'ancien système de coordonnées à l'échelle du contexte. Pour cela, j'utilise CGContextConcatCTM() qui transforme tous les points comme il se doit. Mais, comme il s'agit d'une opération de mise à l'échelle, les largeurs de lignes horizontales/verticales sont modifiées. Par exemple. une échelle de 10 dans la direction x, mais de 1 dans la direction y, conduirait à des lignes verticales 10 fois plus épaisses que les lignes horizontales. Existe-t-il un moyen de conserver la facilité d'utilisation des matrices de traduction (par exemple CGAffineTransform) mais de ne pas mettre à l'échelle les largeurs de ligne en même temps, par ex. une fonction comme CGPathApplyAffineTransformToPoints?Conserver la largeur de ligne tout en redimensionnant tous les points dans le contexte avec CGAffineTransform

Vive

MrMage

Répondre

3

Vous pouvez utiliser CGPathApply pour parcourir les éléments dans un chemin. C'est un peu plus complexe qu'un simple interligne, mais si vous l'intégrez dans une simple fonction d'aide, cela pourrait vous être utile. Voici une version qui crée un nouveau chemin et la transforme:

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

Pour l'utiliser, vous feriez (ce qui est la partie que je mettrais dans une fonction d'aide):

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

    CGPathApply(originalPath, &info, PathTransformer); 

Le chemin transformé est dans info.path à ce stade.

+0

Merci! Cela fera ce que j'ai demandé, mais malheureusement, il ne me donnera pas le gain de performance de ne pas avoir à recréer le chemin entier. Si cela reste la seule réponse, je la marquerai comme la solution. – MrMage

6

Effectuez la transformation lorsque vous ajoutez le chemin, puis supprimez la transformation avant d'appliquer le chemin. Au lieu de cela:

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 

Pour ce faire:

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); 
+0

Je n'ai plus le problème à l'heure actuelle, mais l'avez-vous essayé? Si cela fonctionne comme décrit, ce serait la meilleure réponse. – MrMage

+0

@MrMage Oui, j'ai trouvé votre question quand j'avais le même problème, puis j'ai trouvé ma propre solution un peu plus tard. – bugloaf

+0

Merci, cela a fonctionné pour moi. On dirait que ça devrait être la réponse officielle. –