gpt4 book ai didi

ios - 将 QuadCurve 添加到 UIBezierPath

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:28:57 25 4
gpt4 key购买 nike

我正在做一个绘图应用程序,我正在尝试平滑我用手指绘制的线条。为此,我正在使用“quadCurveToPoint”函数。但是,我没有做对。

下面是我的代码:

- (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
{

}

当我用手指画画时,我得到了如下所示的路径:

enter image description here

我不明白我错过了什么。所以我需要这方面的帮助。

编辑:图片发布 w.r.t.到下面的答案。

enter image description here

谢谢兰 git

最佳答案

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

改变:

[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];

已测试。


附录(WWDC 算法):

背景:

根据 WWDC 的想法是这样的:

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

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

代码分析/修正:

下面是我使用 WWDC 中引入的想法制作的代码的简化版本。

你明白了。几乎。鉴于上述情况,我们需要将 touchesMoved 中的代码更改为以下内容:

1.)

If we are using the mid point as the ToPoint value, we need to take care the first case when there is only one current point, because with only one current point, we cannot derive a mid point from it - we need 2 points.

因此,我们需要先“读取”当前点之后的一个点来计算中点。以下是这样做的:

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];
}

The variable counter is initially set to 0. So, nothing gets drawn until the second pass when counter is 1. And when it is, we will have 2 points to calculate the mid point.

接下来就是剩下的部分了:

2.)

Once the first case is taken care of, we move forward to the rest of the curve and derive appropriately the points with which we connect the segments:

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

这是紧接在上面第一个 if 之后的 else if。我们在仅处理第一种情况时进入此处,因为我使用了一个简单的计数器并在每次调用 touchesMoved 时递增它。

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

3.) And finally, we take care the last segment of the curve in touchesEnded:

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

这只是从您的中点到最后一点画一条线。

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

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

screenshot

这是完整的来源:

- (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];
}

关于ios - 将 QuadCurve 添加到 UIBezierPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21143614/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com