Das Problem ist, dass Sie einen Pfad zwischen einer Reihe von Punkten in einer Geste streichen, und diese Punkte sind nicht alle auf der gleichen Linie, weil sie natürliche Abweichungen enthalten, die stattfinden, wenn der Benutzer den Finger über die zieht Bildschirm.
Dies steht in keinem Zusammenhang mit "Anti-Aliasing", einer Technik, die eine gerade Linie glatter erscheinen lässt, ohne visuell "jaggies" zu stören. Aber das Problem hier ist nicht, dass Sie versuchen, das Rendern einer einzelnen geraden Linie zu verbessern, sondern dass Sie nicht gerade eine gerade Linie zeichnen, sondern stattdessen eine Reihe von Liniensegmenten zeichnen, die das nicht tun passieren zu richten.
Mein Ziel ist es Adobe Illustrator wie Linien zu erreichen, wenn mein Benutzer über den Bildschirm streicht
In diesem Fall Sie nicht wollen, „Anti-Aliasing“. Alles, was Sie brauchen, ist ein createPath
, dass
moveToPoint
zum ersten Punkt; und
addLineToPoint
bis zum letzten Punkt.
Machen Sie sich keine Sorgen über irgendwelche Punkte dazwischen. Diese einfache Lösung ergibt eine einzelne gerade Linie, die überall dort beginnt, wo Ihre Berührungen begonnen haben und sich dorthin erstrecken, wo Ihre Berührungen enden, und wird dies weiterhin tun, bis Sie Ihren Finger heben.
denke ich, dass etwas übersetzen wird wie:
- (UIBezierPath *)createPath {
UIBezierPath * bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:stroke.startPoint];
[bezierPath addLineToPoint:[[stroke.points lastObject] CGPointValue]];
return bezierPath;
}
Wenn Sie nicht über eine tatsächliche Linie wollen, sondern wollen nur diese glätten, ich würde vorschlagen, (a) Sie rollen Durchschnitt, um Spitzen und Täler in Ihren hüpfenden Datenpunkten zu eliminieren; und (b) Hermite- oder Catmull-Rom-Spline verwenden (wie in https://spin.atomicobject.com/2014/05/28/ios-interpolating-points/ umrissen), so dass der resultierende Pfad eher glatt ist als eine Reihe von Liniensegmenten.
So
- (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];
}
Werden ergeben die folgende (wobei die tatsächlichen Datenpunkte in blau sind und die geglättete Wiedergabe ist in rot):
Hinweis, ich gehe davon aus, dass Ihr Array von points
von Stroke
enthält den Startpunkt, also müssen Sie das entsprechend anpassen.
Nein, dies ist kein Antialiasing-Problem. Sie müssen Zugriff auf die einzelnen Punkte haben, die die gesamte Linie bilden, und eine Glättungsoperation anwenden, die etwa so aussieht: 1) Startpunkt und Endpunkt nehmen und nur durch die gerade Linie dazwischen ersetzen oder 2) Mittelung des Neigung mehrerer Segmente usw. Viele Möglichkeiten, Kurven zu glätten. –
Kannst du mir Code für Option # 2 zeigen? – noodlez
Wie werden Ihre Daten gespeichert? Haben Sie Zugang zu einem Array von Punkten (x, y)? Ich kann helfen, aber es ist wichtig, mit was Sie arbeiten, um anzufangen. Mit anderen Worten, hat jeder Punkt auch die "Zeit" oder eine Angabe, die ihn in die richtige Reihenfolge relativ zur Linie bringt? UND wie planen Sie, es neu zu zeichnen? Sie müssen sicher sein, dass das zuerst funktioniert. –