【问题标题】:Repair Fragments in CGPathes of Cocoa Touch / Core Graphics修复Cocoa Touch / Core Graphics的CGPathes中的片段
【发布时间】:2011-09-11 14:44:22
【问题描述】:

我有一个不寻常的问题导致我的思绪卡住了。我创建了一个绘图应用程序,该应用程序使用 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 会产生类似picture here 中的片段。我已经仔细检查了控制点,但我无法弄清楚为什么会发生这种情况。

出于调试原因,我在下面打印了 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 

更新:我使用了this link中描述的算法,翻译成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;
 }

然而,交换两个控制点并不能带来令人满意的结果,反而会大大增加碎片的数量。如果有任何进一步的帮助,我将不胜感激。

【问题讨论】:

    标签: objective-c cocoa-touch drawing core-animation core-graphics


    【解决方案1】:

    很遗憾,您的代码没有显示如何计算平滑路径的控制点。但他们是问题所在。它们中的大多数位于曲线段起点或终点的错误一侧。因此,您的路径会在许多主要点形成非常紧凑的环路或 S 曲线。

    这方面的另一个迹象是,虽然路径通常向左转,但许多路径段都向右。

    我不太明白你为什么有这些白色的半圈。似乎使用奇偶规则来绘制路径而不是非零缠绕规则,这可能无法更改。无论如何,如果您解决了上述问题,问题就会消失。

    【讨论】:

    • 我已经更新了上面的帖子来描述控制点是如何计算的。
    • 你的算法部分很难理解。您必须再次检查是否将正确的坐标传递给方法的正确参数。在大多数情况下,控制点应该或多或少位于两个连续的主要点之间。您的代码中奇怪的是该算法似乎需要主要点来计算控制点,但您的代码一次只处理三个。
    • 我真正不明白的是,每个控制点看起来都很合理,总是介于两个主要点之间。左控制点 (ControlPoint1) 始终位于该点和之前的点之间。右控制点 (ControlPoint2) 始终位于该点和之后的点之间。那么,神器出现的原因是什么?如果有人能帮助我理解这一点,我将不胜感激。
    • 您所描述的正是您所犯的错误。控制点 1 不应位于该点和之前的点之间。控制点 2 也不是。您应该或多或少有序列的升序(或降序)坐标:主点、控制点 1、控制点 2、主点、控制点 1 等。
    猜你喜欢
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多