Ремонт фрагментов в CGPathes Cocoa Touch / Core Graphics - PullRequest
0 голосов
/ 11 сентября 2011

У меня необычная проблема, из-за которой мой разум застрял. Я создал приложение для рисования, использующее CGPathes, которое создается инструментом «на лету» с помощью следующего кода контроллера вида.

@implementation WWLGrabManager
- (void) touchesBegan:(NSSet*)touchesIgnore withEvent:(UIEvent*)event {
     currentPath = CGPathCreateMutable();
     CGPathMoveToPoint(currentPath, NULL, pt.x, pt.y); 
}

- (void) touchesMoved:(NSSet*)touchesIgnore withEvent:(UIEvent*)event {
     CGPathAddLineToPoint(currentPath, NULL, pt.x, pt.y);
}

- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
    currentPath = [self newSmoothedPathWithPath:currentPath];
}
@end

После рисования я повторяю еще раз по CGPath, чтобы сгладить нарисованные края пути. Это должно сделать путь не таким уродливым, построив середину каждой из трех точек и применив кривую к каждой точке. Код для сглаживания ребер в основном состоит из следующего псевдокода:

-(CGMutablePathRef)newSmoothedPathWithPath:(CGPathRef)path {
      // This is pseudo code
      CGMutablePathRef newPath = CGPathCreateMutable();
      foreach (CGPoint point in path)
            CGPathAddCurveToPoint(newPath, NULL, 
                    ctrlPt1.x,ctrlPt1.y,ctrlPt2.x,ctrlPt2.y,
                    ((*preLastPoint).x + (*lastPoint).x + (point).x)/3, 
                    ((*preLastPoint).y + (*lastPoint).y + (point).y)/3); 
      }
      return newPath;
 }

Теперь, после применения функции сглаживания, новый CGPath вызывает фрагменты, как на рисунке здесь . Я дважды проверил контрольные точки, но не могу понять, почему это происходит.

По причинам отладки я распечатал журнал точек CGPathes и контрольных точек ниже.

 MainPoint //      ControlPoint1 //  ControlPoint2

 66.00, 91.00 //   67.00,87.00 //    64.25,95.75 
 59.00,110.00 //   60.75,105.25 //   58.00,113.75 
 55.00,125.00 //   56.00,121.25 //   54.00,128.75 
 51.00,140.00 //   52.00,136.25 //   50.25,144.25 
 48.00,157.00 //   48.75,152.75 //   47.25,161.00 
 45.00,173.00 //   45.75,169.00 //   44.75,176.75 
 44.00,188.00 //   44.25,184.25 //   43.75,191.75 
 43.00,203.00 //   43.25,199.25 //   43.00,207.00 
 43.00,219.00 //   43.00,215.00 //   43.00,223.00 
 43.00,235.00 //   43.00,231.00 //   43.00,239.25 
 43.00,252.00 //   43.00,247.75 //   43.00,256.00 
 43.00,268.00 //   43.00,264.00 //   44.25,272.00 
 48.00,284.00 //   46.75,280.00 //   49.50,287.50 
 54.00,298.00 //   52.50,294.50 //   56.75,300.75 
 65.00,309.00 //   62.25,306.25 //   68.75,310.75 
 80.00,316.00 //   76.25,314.25 //   84.00,316.50 
 96.00,318.00 //   92.00,317.50 //   101.50,318.25 
 118.00,319.00 //  112.50,318.75 //  124.75,319.00 
 145.00,319.00 //  138.25,319.00 //  151.25,319.00 
 170.00,319.00 //  163.75,319.00 //  175.50,318.25 
 192.00,316.00 //  186.50,316.75 //  199.50,314.00 
 222.00,308.00 //  214.50,310.00 //  226.75,306.75 
 241.00,303.00 //  236.25,304.25 //  245.00,301.75 
 257.00,298.00 //  253.00,299.25 //  260.50,295.75 
 271.00,289.00 //  267.50,291.25 //  273.25,285.25 
 280.00,274.00 //  277.75,277.75 //  280.50,270.25 
 282.00,259.00 //  281.50,262.75 //  282.00,254.50 
 282.00,241.00 //  282.00,245.50 //  280.50,237.25 
 276.00,226.00 //  277.50,229.75 //  273.50,222.75 
 266.00,213.00 //  268.50,216.25 //  263.00,208.75 
 254.00,196.00 //  257.00,200.25 //  249.75,192.50 
 237.00,182.00 //  241.25,185.50 //  234.00,179.75 
 225.00,173.00 //  228.00,175.25 //  221.75,170.50 
 212.00,163.00 //  215.25,165.50 //  208.50,160.25 
 198.00,152.00 //  201.50,154.75 //  194.00,148.75 
 182.00,139.00 //  186.00,142.25 //  178.00,136.75 
 166.00,130.00 //  170.00,132.25 //  162.25,128.50 

Обновление: Я использовал алгоритм, описанный в по этой ссылке , который был переведен в Objective-C следующим образом:

 CGPoint ctrl2 = controlPointForPoints(*lastPoint,*preLastPoint,currentPoint);
 CGPoint ctrl1 = controlPointForPoints(*lastPoint,currentPoint,*preLastPoint);

 static CGPoint controlPointForPoints(CGPoint pt, CGPoint pre, CGPoint post) {
     CGPoint ctrlPt = CGPointMake(
         middleOfPoints(middleOfPoints(pt.x, pre.x), middleOfPoints(symmetryOfPoints(pt.x, post.x), pt.x)),
         middleOfPoints(middleOfPoints(pt.y, pre.y), middleOfPoints(symmetryOfPoints(pt.y, post.y), pt.y))
     );

     return ctrlPt;
 }

 static float symmetryOfPoints(float a,float b) {
     return a - ((b-a)*smoothingFactor) / 100.0;
 }

 static float middleOfPoints(float a, float b) {
     return (a+b) / 2.0;
 }

Однако обмен двумя контрольными точками не приводит к удовлетворительным результатам, а увеличивает количество фрагментов до огромных размеров. Буду признателен за любую дополнительную помощь.

1 Ответ

0 голосов
/ 11 сентября 2011

К сожалению, ваш код не показывает, как рассчитываются контрольные точки сглаженного пути. Но они проблема. Большинство из них находятся на неправильной стороне начальной или конечной точки сегмента кривой. Как следствие, ваш путь делает очень узкую петлю или кривую S во многих основных точках.

Еще одним свидетельством этого является то, что, хотя путь обычно поворачивается влево, многие сегменты пути находятся справа.

Я не совсем понимаю, почему у вас эти белые полукруги. Кажется, что четное-нечетное правило используется для рисования пути вместо ненулевого правила намотки, которое, вероятно, не может быть изменено. В любом случае, проблема исчезнет, ​​если вы исправите вышеуказанную проблему.

...