2011-11-06 34 views
14

我正在使用UIBezierPath,但这个问题涉及到路径的控制点,而不是绘图。给定一组点,我可以渲染一条路径。但是,我一直无法弄清楚如何计算控制点,以便在照片曲线编辑器(How to implement a Photoshop Curves editor in UIKit)中拥有平滑的线条。如何计算给定一组点的平滑路径的控制点?

最接近的答案,我所看到的是在这里:how can i trace the finger movement on touch for drawing smooth curves?

不过,我还不能掌握正确的计算。概括起来代码:

for (int i = 0; i< points; i++) 
{ 
    ... 

    [path addQuadCurveToPoint:nextPoint controlPoint:WTF]; 
} 
+5

沉默是如此之大,它伤害。 – akaru

+0

你想让曲线精确地穿过你的每个给定点吗?或者你想要一条更平滑的曲线可以通过一些给定的点? –

+0

@robmayoff如果这是一个简单得多的操作,我认为close是够好的。 – akaru

回答

12

您链接到的图像是不使用二次曲线的例子,所以我要运行 与图像,而不是代码。

下面的ios(和os x)上的bezier路径基本上是一个绘图命令和点的列表。例如:在

[path moveTo:CGMakePoint(1,1)]; 
[path curveToPoint:(10,10) controPoint1:(3,7) controlPoint2:(4,1)]; 
[path curveToPoint:(10,10) controPoint1:(15,17) controlPoint2:(21,11)]; 
[path closePath]; 

结果:一个贝塞尔路径上

moveto (1,1)  
curveto (10,10) (3,7) (4,1) 
curveto (20,0) (15,17) (21,11)  
closepath 

控制点控制方向和曲线的速率出的点的。第一个控制点(cp)控制退出前一点的曲线的方向和速率,第二个cp控制曲线点的方向和速率。对于二次曲线(使用addQuadCurveToPoint:controlPoint:得到的结果),这两个点都是相同的,正如您可以在方法here的文档中看到的那样。

沿着一系列点获得平滑曲线涉及使cp1和cp2彼此共线,并且该线与该段两端的点平行。

Annotated curve

这看起来是这样的:

[path moveTo:2]; 
[path curveTo:3 controlPoint1:cp1 controlPoint2:cp2]; 

CP1和CP2可以通过选择一些固定的线路长度,并做一些几何计算(我忘了我所有的线方程,但现在他们”

要使用# - >#来指定段和# - >#(cp#)来指定该段曲线调用的控制点。

下一个问题是使曲线从2-> 3段进入3-> 4段平滑。在你的代码的这一点上,你应该有一个控制点计算2-> 3(cp2)。给定你以前的恒定线长度(这将控制你得到的曲线的尖锐程度),你可以通过在图中得到2-> 3(cp2)和点3的共线点来计算cp1为3> 4。然后计算3-> 4(cp2),它与3-> 4(cp1)共线并平行于点3和点4形成的线。冲洗并重复您的点数组。

+1

感谢您的回复。不幸的是,通过链接阅读后,我仍然无法确定正确的方法。我责怪我的大脑。 – akaru

+0

您无法编写用于计算控制点的代码。 –

4

我不知道这会有多大的帮助,但我必须做类似的工作来实现这个应用程序中遵循的笔记曲线路径(www.app.net/hereboy)。实质上,它是一条有三条曲线的路径。

为此,我创建了每条曲线4点,起点,终点和两个控制点,分别为25%和75%。

下面是我写这样做代码:

//create points along the keypath for curve. 
CGMutablePathRef curvedPath = CGPathCreateMutable(); 
const int TOTAL_POINTS = 3; 
int horizontalWiggle = 15; 

int stepChangeX = (endPoint.x - viewOrigin.x)/TOTAL_POINTS; 
int stepChangeY = (endPoint.y - viewOrigin.y)/TOTAL_POINTS; 

for(int i = 0; i < TOTAL_POINTS; i++) { 
    int startX = (int)(viewOrigin.x + i * stepChangeX); 
    int startY = (int)(viewOrigin.y + i * stepChangeY); 

    int endX = (int)(viewOrigin.x + (i+1) * stepChangeX); 
    int endY = (int)(viewOrigin.y + (i+1) * stepChangeY); 

    int cpX1 = (int)(viewOrigin.x + (i+0.25) * stepChangeX); 
    if((i+1)%2) { 
     cpX1 -= horizontalWiggle; 
    } else { 
     cpX1 += horizontalWiggle; 
    } 
    int cpY1 = (int)(viewOrigin.y + (i+0.25) * stepChangeY); 

    int cpX2 = (int)(viewOrigin.x + (i+0.75) * stepChangeX); 
    if((i+1)%2) { 
     cpX2 -= horizontalWiggle; 
    } else { 
     cpX2 += horizontalWiggle; 
    } 
    int cpY2 = (int)(viewOrigin.y + (i+0.75) * stepChangeY); 

    CGPathMoveToPoint(curvedPath, NULL, startX, startY); 
    CGPathAddCurveToPoint(curvedPath, NULL, cpX1, cpY1, cpX2, cpY2, endX, endY); 
} 

祝你好运!

相关问题