当我的用户在屏幕上滑动时,我的目标是实现类似Adobe Illustrator的行。目前情况非常不稳定 - 这是当前情况的屏幕截图:
我认为这显然是我想要的。我希望平滑这些直线。这叫做抗锯齿吗?
- (void)touchesBegan: (CGPoint)point
{
currentStroke = [[Stroke alloc] initWithStartPoint:point];
[strokes addObject:currentStroke];
}
- (void)touchesMoved: (CGPoint)point
{
if (!currentStroke) {
[self touchesBegan:point];
}
[currentStroke.points addObject:[NSValue valueWithCGPoint:point]]
pathTwo = [self createPath];
[self scaleToFit];
[self setNeedsDisplay];
}
- (UIBezierPath *)createPath {
UIBezierPath * bezierPath = [UIBezierPath bezierPath];
for (Stroke * stroke in strokes) {
[bezierPath moveToPoint:stroke.startPoint];
for (NSValue * value in stroke.points) {
[bezierPath addLineToPoint:[value CGPointValue]];
}
}
return bezierPath;
}
- (void)touchesEnded: (CGPoint)point
{
[points removeAllObjects];
[self setNeedsDisplay];
}
drawRect
有这个:
[[UIColor whiteColor] setStroke];
[pathTwo setLineWidth: _strokeWidth];
[pathTwo stroke];
修改的
我想我找到了答案...... https://github.com/jnfisher/ios-curve-interpolation
我根本不知道如何使用createPath
公式。
也许有人可以帮我插上我的阵列?
答案 0 :(得分:5)
问题是你在一个手势中捕获的一系列点之间的路径,并且这些点不是全部在同一条线上,因为它们包括当用户手指在屏幕上拖动时发生的自然偏差
这与“抗锯齿”完全无关,“抗锯齿”是一种使直线看起来更平滑,不会在视觉上分散“锯齿”的技术。但问题不在于你是在尝试改善单条直线的渲染,而是你首先不是绘制直线,而是绘制一堆不具有直线的直线。碰巧排队。
我的目标是在用户在屏幕上滑动时实现类似Adobe Illustrator的
在这种情况下,您不需要“抗锯齿”。您所需要的只是createPath
moveToPoint
到第一点;和addLineToPoint
到最后一点。不要担心其中的任何一点。这个简单的解决方案将产生一条直线,它将从您触摸开始的任何地方开始,并延伸到您的触摸结束的位置,并将继续这样做,直到您举起手指。
我认为这会转化为:
- (UIBezierPath *)createPath {
UIBezierPath * bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:stroke.startPoint];
[bezierPath addLineToPoint:[[stroke.points lastObject] CGPointValue]];
return bezierPath;
}
如果你不想要一条实际的线,而只想平滑这一点,我建议(a)做滚动平均线以消除你的弹性数据点中的峰值和谷值; (b)使用Hermite或Catmull-Rom样条(如https://spin.atomicobject.com/2014/05/28/ios-interpolating-points/中所述),因此得到的路径是平滑的而不是一系列线段。
因此
- (UIBezierPath * _Nullable)createActualPathFor:(Stroke *)stroke {
if (stroke.points.count < 2) return nil;
UIBezierPath * path = [UIBezierPath bezierPath];
[path moveToPoint:[stroke.points.firstObject CGPointValue]];
for (NSInteger i = 1; i < stroke.points.count; i++) {
[path addLineToPoint:[stroke.points[i] CGPointValue]];
}
return path;
}
- (UIBezierPath * _Nullable)createSmoothedPathFor:(Stroke *)stroke interval:(NSInteger)interval {
if (stroke.points.count < 2) return nil;
NSMutableArray <NSValue *> *averagedPoints = [NSMutableArray arrayWithObject:stroke.points[0]];
NSInteger current = 1;
NSInteger count = 0;
do {
CGFloat sumX = 0;
CGFloat sumY = 0;
do {
CGPoint point = [stroke.points[current] CGPointValue];
sumX += point.x;
sumY += point.y;
current++;
count++;
} while (count < interval && current < stroke.points.count);
if (count >= interval) {
CGPoint average = CGPointMake(sumX / count, sumY / count);
[averagedPoints addObject:[NSValue valueWithCGPoint:average]];
count = 0;
}
} while (current < stroke.points.count);
if (count != 0) {
[averagedPoints addObject:stroke.points.lastObject];
}
return [UIBezierPath interpolateCGPointsWithHermite:averagedPoints closed:false];
}
将产生以下结果(实际数据点为蓝色,平滑的再现为红色):
注意,我假设您的points
Stroke
数组包含起点,因此您可能需要相应地调整它。
答案 1 :(得分:0)
谢谢大家的支持。我离开了一会儿。但我找到了解决我的情况的现象。这是一个插值的类。
https://github.com/jnfisher/ios-curve-interpolation
我所要做的就是通过我的点数组,然后将它们平滑出来!