2009-11-25 12 views
5

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

Приветствия

MrMage

ответ

3

Вы можете использовать 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 на этом этапе.

+0

Спасибо! Это будет делать то, о чем я просил, но, к сожалению, это не даст мне прироста производительности, чтобы не воссоздать весь путь. Если это останется единственным ответом, я помечаю его как решение. – MrMage

6

Сделайте преобразование при добавлении пути, но затем удалите преобразование перед тем, как погладить путь. Вместо этого:

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

У меня сейчас нет проблемы, но вы попробовали это? Если это сработает, как описано, это будет лучший ответ. – MrMage

+0

@MrMage Да, я нашел ваш вопрос, когда у меня была такая же проблема, а потом я придумал свое решение немного позже. – bugloaf

+0

Спасибо, это сработало для меня. Похоже, это должен быть официальный ответ. –