为了账号安全,请及时绑定邮箱和手机立即绑定

iPhone平滑草图绘制算法

iPhone平滑草图绘制算法

iOS
侃侃尔雅 2019-11-21 15:08:16
我正在开发iPhone上的素描应用程序。我让它正常工作,但是看起来不像这里 我正在寻找任何使绘图平滑的建议基本上,我所做的是当用户将手指放在我叫过的屏幕上时- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 然后我用一个阵列收集一次触摸- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event当用户从屏幕上离开手指时,我打电话给- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event然后我使用绘制数组中的所有点NSMutableArray *points = [collectedArray points];   CGPoint firstPoint;[[points objectAtIndex:0] getValue:&firstPoint];CGContextMoveToPoint(context, firstPoint.x, firstPoint.y);CGContextSetLineCap(context, kCGLineCapRound);CGContextSetLineJoin(context, kCGLineJoinRound);for (int i=1; i < [points count]; i++) {    NSValue *value = [points objectAtIndex:i];    CGPoint point;    [value getValue:&point];        CGContextAddLineToPoint(context, point.x, point.y);} CGContextStrokePath(context);UIGraphicsPushContext(context);现在,我想改善绘图效果,使其更像“ Sketch Book”应用程序我认为信号处理算法可以重新排列阵列中的所有点,但我不确定。任何帮助将非常感激。预先感谢:)
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

像这样平滑曲线的最简单方法是使用贝塞尔曲线而不是直线段。有关其背后的数学信息,请参阅本文(指向此答案),该文章描述了如何计算平滑通过多个点的曲线所需的曲线。


我相信Core Plot框架现在可以平滑绘图的曲线,因此您可以查看那里用于实现这种平滑处理的代码。


这没有什么神奇的,因为这些平滑例程是快速且相对容易实现的。


查看完整回答
反对 回复 2019-11-21
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

CGPoint midPoint(CGPoint p1, CGPoint p2)

{


    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);


}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{


    UITouch *touch = [touches anyObject];


    previousPoint1 = [touch previousLocationInView:self];

    previousPoint2 = [touch previousLocationInView:self];

    currentPoint = [touch locationInView:self];


}


-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{


    UITouch *touch = [touches anyObject];


    previousPoint2 = previousPoint1;

    previousPoint1 = [touch previousLocationInView:self];

    currentPoint = [touch locationInView:self];



    // calculate mid point

    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 

    CGPoint mid2 = midPoint(currentPoint, previousPoint1);


    UIGraphicsBeginImageContext(self.imageView.frame.size);

    CGContextRef context = UIGraphicsGetCurrentContext();

    [self.imageView.image drawInRect:CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height)];


    CGContextMoveToPoint(context, mid1.x, mid1.y);

    // Use QuadCurve is the key

    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 


    CGContextSetLineCap(context, kCGLineCapRound);

    CGContextSetLineWidth(context, 2.0);

    CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);

    CGContextStrokePath(context);


    self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();


}


查看完整回答
反对 回复 2019-11-21
?
月关宝盒

TA贡献1772条经验 获得超5个赞

我真的很喜欢这个话题。感谢所有实现,尤其是KrzysztofZabłocki和Yu-Sen Han。我已经修改了Yu-Sen Han的版本,以便根据平移速度(实际上是最后一次触摸之间的距离)来更改线条的粗细。我还实现了点绘制(对于touchBegan和touchEnded位置彼此靠近),结果如下: 

//img1.sycdn.imooc.com//5dd638170001b64205800772.jpg

为了定义线宽,我选择了距离的函数:

(不要问我为什么……虽然很合适,但我敢肯定您会找到更好的一个)

//img1.sycdn.imooc.com//5dd638200001fbf205340525.jpg

CGFloat dist = distance(previousPoint1, currentPoint);

CGFloat newWidth = 4*(atan(-dist/15+1) + M_PI/2)+2;

还有一个提示。为确保厚度平滑变化,我根据上一段的厚度和自定义系数限制了边界:


self.lineWidth = MAX(MIN(newWidth,lastWidth*WIDTH_RANGE_COEF),lastWidth/WIDTH_RANGE_COEF);


查看完整回答
反对 回复 2019-11-21
  • 3 回答
  • 0 关注
  • 663 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信