添加一个QuadCurve到UIBezierPath

我正在做一个绘图应用程序,我试图平滑我用手指画的线。为此,我正在使用“quadCurveToPoint”function。 但是,我没有得到正确的答案。

以下是我的代码:

- (void) drawRect:(CGRect)rect { [path stroke]; } - (id) initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) self.multipleTouchEnabled = NO; path = [UIBezierPath bezierPath]; path.lineWidth = IS_IPAD? 2.0f : 1.0f; return self; } - (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event { UITouch *touch = [touches anyObject]; m_previousPoint1 = [touch locationInView:self]; m_previousPoint2 = [touch locationInView:self]; m_currentPoint = [touch locationInView:self]; } //Find the midpoint CGPoint midPoint(CGPoint p1, CGPoint p2) { return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); } - (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event { UITouch *touch = [touches anyObject]; m_previousPoint2 = m_previousPoint1; m_previousPoint1 = m_currentPoint; m_currentPoint = [touch locationInView:self]; CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1); [path setFlatness:1.0f]; [path setLineCapStyle:kCGLineCapRound]; [path setLineJoinStyle:kCGLineJoinRound]; [path moveToPoint:m_previousPoint1]; [path addLineToPoint:mid1]; [path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint]; [self setNeedsDisplay]; } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { } 

当我用手指画画时,我正在像下面这样画一条路:

在这里输入图像说明

我不明白我在想什么。 所以我需要这方面的帮助。

编辑:图像张贴到下面的答案。

在这里输入图像说明

感谢Ranjit

你的代码看起来不错。 但要解决您提到的问题,请将当前代码更改为以下内容:

更改:

 [path moveToPoint:m_previousPoint1]; [path addLineToPoint:mid1]; 

至:

 [path moveToPoint:mid1]; [path addLineToPoint:m_previousPoint1]; 

并改变这一点:

 [path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint]; 

至:

 [path addQuadCurveToPoint:m_currentPoint controlPoint:mid2]; 

testing。


附录(WWDCalgorithm):

背景

根据WWDC的想法是这样的:

1.)而不是使用当前点,我们使用中点作为起点和终点。

2.)因此,我们使用实际的触点作为控制点。

分析/更正您的代码

所以这里是我使用WWDC中引入的想法的简化版本。

你有这个想法。 几乎。 鉴于上述情况,我们需要对touchesMoved中的代码进行更改如下:

1.)

如果我们使用中点作为ToPoint值,那么当只有一个当前点时,我们需要关注第一种情况,因为只有一个当前点,我们不能从中点得出 – 我们需要2点

所以,我们需要先“读”一下当前点的一点来计算中点。 以下是:

 UITouch *touch = [touches anyObject]; m_previousPoint1 = m_currentPoint; m_currentPoint = [touch locationInView:self]; mid1 = midPoint(m_currentPoint, m_previousPoint1); if(counter == 1) { [path moveToPoint:m_currentPoint]; [path addLineToPoint:mid1]; [self setNeedsDisplay]; } 

variables计数器初始设置为0.所以,直到第二次计数器为1时才会绘制任何东西。如果是这样,我们将有2个点来计算中间点。

接下来是其余的触动:

2.)

一旦第一个案例得到处理,我们向前走到曲线的其余部分,并适当地得出我们连接段的点:

 else if(counter > 1) { [path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1]; [self setNeedsDisplay]; } counter++; 

else if在上面的第一个之后else if 。 我们只在第一个案件被处理时进入这里,因为我使用了一个简单的计数器,每当touchesMoved被调用时就增加它。

这里发生的是,我们正在使用前一个点作为控制点,从前一个中点连接到mid1 。 那么,现在呢? 我们正在使用它,直到下一个通行证。

3.)最后,我们在touchesEndedtouchesEnded曲线的最后一段:

 - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [path addLineToPoint:[[touches anyObject] locationInView:self]]; [self setNeedsDisplay]; } 

这只是从你的中点画到最后一点。

最后在touchesBegan ,我设置counter = 0; ,所以下一个曲线将再次开始上述过程。

我使用模拟器和设备testing了上面的,这里是一个屏幕截图:

截图

这里是完整的来源:

 - (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event { UITouch *touch = [touches anyObject]; counter = 0; m_previousPoint1 = [touch locationInView:self]; m_currentPoint = [touch locationInView:self]; } //Find the midpoint CGPoint midPoint(CGPoint p1, CGPoint p2) { return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); } - (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event { UITouch *touch = [touches anyObject]; m_previousPoint1 = m_currentPoint; m_currentPoint = [touch locationInView:self]; mid1 = midPoint(m_currentPoint, m_previousPoint1); [path setFlatness:1.0f]; [path setLineCapStyle:kCGLineCapRound]; [path setLineJoinStyle:kCGLineJoinRound]; if(counter == 1) { [path moveToPoint:m_currentPoint]; [path addLineToPoint:mid1]; [self setNeedsDisplay]; } else if(counter > 1) { [path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1]; [self setNeedsDisplay]; } counter++; } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [path addLineToPoint:[[touches anyObject] locationInView:self]]; [self setNeedsDisplay]; }