Bestimmung der Länge eines CGPath

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Da es weder eine entsprechende Funktion noch welche zum Bestimmen der Pfadsegmente, glaube ich nicht, dass das über das offizielle API von Apple geht. Wozu brauchst Du denn die Länge?

    EDIT: Der erste Teilsatz ist nicht ganz richtig. Es gibt zumindest CGPathApply.
    „Meine Komplikation hatte eine Komplikation.“

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von macmoonshine ()

  • Das wirst du mit dem CGPath nicht lösen können. Du müsstest den Weg des Schiebers irgendwie in einem eigenen Objekt speichern mit den Punkten des Weges. Dann addierst du die Abstände von Punkt zu Punkt. Je kürzer die Punktabstände, desto besser. Aus diesem "Punktearray" könntest du dann deinen CGPath zum Zeichnen ableiten.

    CGPath beschreibt nur die Stützpunkte des Pfades, wie die Kurve dann verläuft wird beim Rendern berechnet.

    Idee für ne Mogelpackung: Zeichne den CGPath schwarz in ein weißes Bild ohne AntiAliasing. Dann sollte die Anzahl der schwarzen Pixel etwa mit der Wegstrecke proportional sein.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • meine Idee geht in eine ähnliche Richtung:

    man nehme einen CALayer den man den Path entlang mit konstanter Geschwindigkeit positions-animiert. Während dessen fragt man die current-position des presentationsLayers über eine Timerfunktion in kurzen Abständen ab.
    die Entfernung der Positionspunkte in der Summe ergeben dann die Gesamtstrecke.
  • Oha, ich will ein Foto machen und du drehst nen Film , da dürfte meine Idee die paar Pixel zu zählen, aber schneller sein ;)

    @macmoonshine: Er hat ja nur den Pfad als Information. Deine Idee den Pfad zusammen zu stückeln geht in die Richtung die ich auch meinte mit einzelnen Punkte speichern. Aber die scheint er ja nicht zu haben.

    Davon mal abgesehen ist es gar nicht mal so schwer einen kubischen Bezierpfad selbst zu rendern. Schau dir mal die Grafik auf Wikipedia an. Dann kannst du dir die Punkte so genau wie du es brauchst berechnen und die Abstände addieren.

    EDIT: Wenn's jetzt zwischen Weihnachten und Neujahr wäre und meine Shell geflickt wäre - dann würde ich jetzt schon am Kubischen Bezierpfad coden. Schade, der quadratische fliegt hier schon irgendwo rum.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Manfred Kreß schrieb:

    @macmoonshine: Er hat ja nur den Pfad als Information. Deine Idee den Pfad zusammen zu stückeln geht in die Richtung die ich auch meinte mit einzelnen Punkte speichern. Aber die scheint er ja nicht zu haben.

    Wenn er den CGPath hat kann er die einzelnen Teilstück über die genannte Funktion ermitteln. Die höhere Genauigkeit, die sich gegenüber Deinem Interpolationsvorschlag ermitteln lässt, ist aber wahrscheinlich nicht notwendig.

    322 schrieb:

    man nehme einen CALayer den man den Path entlang mit konstanter Geschwindigkeit positions-animiert. Während dessen fragt man die current-position des presentationsLayers über eine Timerfunktion in kurzen Abständen ab.

    Timer sind im Zusammenhang mit Animationen meistens eine schlechte Idee. Im Prinzip liefert Dir doch die Animation die Punkte schon automatisch.
    „Meine Komplikation hatte eine Komplikation.“
  • Die Animation braucht ja nicht nur nicht schön aussehen, sondern gar nicht zu sehen sein. Ob der Timer die Ani negativ beeinflusst, ist vernachlässigbar. Hauptsache die Positionswerte des Presentationslayers liegen in einem Abstand, der eng genug ist.

    Frage: inwiefern kann man denn von der Animation die durchlaufenen Positionen ableiten?
  • CGPathApply ist richtig, aber ganz so simpel ist es dann doch nicht, weil sich die Länge eines kubischen Splines nicht so einfach direkt berechnen lässt. Aber er lässt sich per de Casteljau-Algorithmus rekursiv so lange teilen, bis die Teile gerade genug sind, um durch eine Linie approximiert zu werden (lässt sich über die konvexe Hülle abschätzen). Dann die Längen der Linien aufsummieren. NSBezierPath bietet das fertig an, bei CGPath muss man das von Hand machen.
    Multigrad - 360°-Produktfotografie für den Mac
  • Wenn die Forumauswahl kein Fehler ist, geht das mit NSBezierPath. Dort gibt es eine Methode bezierPathWithFlattenedPath: oder so, die nur lineare Elemente liefert. Die sind dann einfach zu berechnen (Pythagoras usw.). Das ist dann der Pfad, wie er angewendet wird. Die Qualität kannst du selbst bestimmen, ist aber augenscheinlich (hehehe, im wahrsten Sinne des Wortes) ausreichend.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Also:

    CGPathApply liefert mir die Path Elemente zurück, aus denen der Path zusammengesetzt ist:

    Quellcode

    1. void processPathElement(void* info, const CGPathElement* element);
    2. void processPathElement(void* info, const CGPathElement* element)
    3. {
    4. int nPoints;
    5. switch (element->type)
    6. {
    7. case kCGPathElementMoveToPoint:
    8. nPoints = 1;
    9. break;
    10. case kCGPathElementAddLineToPoint:
    11. nPoints = 1;
    12. break;
    13. case kCGPathElementAddQuadCurveToPoint:
    14. nPoints = 2;
    15. break;
    16. case kCGPathElementAddCurveToPoint:
    17. nPoints = 3;
    18. break;
    19. case kCGPathElementCloseSubpath:
    20. nPoints = 0;
    21. break;
    22. default:
    23. return;
    24. }
    25. NSLog(@"Type: %i", element->type);
    26. int i;
    27. for (i=0; i<nPoints; i++)
    28. {
    29. NSLog(@"Point %@", NSStringFromCGPoint(element ->points[i]));
    30. }
    31. }
    32. @implementation OCAppDelegate
    33. @synthesize window = _window;
    34. - (void)dealloc
    35. {
    36. [_window release];
    37. [super dealloc];
    38. }
    39. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    40. {
    41. UIBezierPath *p = [[UIBezierPath alloc] init];
    42. [p moveToPoint: CGPointMake(10, 10)];
    43. [p addCurveToPoint: CGPointMake( 100, 10) controlPoint1: CGPointMake(20, 100) controlPoint2: CGPointMake(90, 100)];
    44. CGPathRef path = [p CGPath];
    45. CGPathApply(path, NULL, processPathElement);
    46. ....
    Alles anzeigen


    Output:

    Quellcode

    1. 2011-11-08 09:49:39.706 Path[519:f803] Type: 0
    2. 2011-11-08 09:49:39.708 Path[519:f803] Point {10, 10}
    3. 2011-11-08 09:49:39.709 Path[519:f803] Type: 3
    4. 2011-11-08 09:49:39.709 Path[519:f803] Point {20, 100}
    5. 2011-11-08 09:49:39.710 Path[519:f803] Point {90, 100}
    6. 2011-11-08 09:49:39.711 Path[519:f803] Point {100, 10}


    osxentwicklerforum.de/index.php/Attachment/3419/

    Wir bekommen Informationen über die Konstruktionspunkte etc. des Pfades. Was ich mal mit der oberen Skizze versucht habe darzustellen. Was wir aber brauchen, zumindest wenn ich den Tonic Starter richtig verstanden habe, ist der Fortschritt auf dem gerrenderten Pfad selbst (untere Zeichnung), wozu ich dann eben die gerenderten Punkte brauche - und das liefert und CGPath nicht.

    Wenn der Pfad jetzt natürlich mit 300 lineToPoint: zusammengestückelt ist, kann man natürlich die einzelnen Punkte des Pfades verwenden. Aber das wäre ja völlig Langweilig.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Amin Negm-Awad schrieb:

    Wenn die Forumauswahl kein Fehler ist, geht das mit NSBezierPath.

    Ach ja, früher... da waren die iOS-Beiträge in ihrem Thread, alles andere war OSX. Wird, wie ich es sehe, mittlerweile micht mehr praktiziert. Hier kommt alles rein. Deshalb hatte ich vorsichtshalber sowohl das händische Vorgehen bei CGPath als auch die automatische Zerteilung bei NSBezierPath erwähnt.

    Vielleicht wäre es sinnvoll, die Forumskategorien etwas umzuordnen - ist ja mittlerweile überwiegend iOS.
    Multigrad - 360°-Produktfotografie für den Mac
  • Manfred Kreß schrieb:

    Wenn der Pfad jetzt natürlich mit 300 lineToPoint: zusammengestückelt ist, kann man natürlich die einzelnen Punkte des Pfades verwenden. Aber das wäre ja völlig Langweilig.


    Es gibt keine mathematische Methode um die Länge eines Bezier Path zu bestimmen (es gibt auch keine Möglichkeit eine Paralle zu einem Bezier Path zu ermitteln), es bleibt nur eine approximation z.B. in dem man den Pfad in Gradenteilstücke zerlegt.
    Xcode 4 sucks – „,Multiple exclamation marks‘, he went on, shaking his head, are a sure sign of a diseased mind.‘“ (Terry Pratchett 1992: Eric)

    "Wir ordnen und befehlen hiermit allen Ernstes, dass die Advocati wollene schwarze Mäntel, welche bis unter das Knie gehen, unserer Verordnung gemäß zu tragen haben, damit man die Spitzbuben schon von weitem erkennt." (Friedrich Wilhelm I., Soldatenkönig)
  • mika schrieb:

    Manfred Kreß schrieb:

    Wenn der Pfad jetzt natürlich mit 300 lineToPoint: zusammengestückelt ist, kann man natürlich die einzelnen Punkte des Pfades verwenden. Aber das wäre ja völlig Langweilig.


    Es gibt keine mathematische Methode um die Länge eines Bezier Path zu bestimmen (es gibt auch keine Möglichkeit eine Paralle zu einem Bezier Path zu ermitteln), es bleibt nur eine approximation z.B. in dem man den Pfad in Gradenteilstücke zerlegt.

    Das fürchte ich auch. Weshalb der Ansatz mit Apply jedenfalls nicht unmittelbar funktionieren dürfte (siehe mattik). Man muss immer flatten. Wenn das iOS ist (aka kein NSBezierPath) muss man das wohl selbst machen. Das hat man eben davon, wenn man alles auf die Graphikchips schiebt. :-] Ist aber schon komisch, dass keine Funktion angeboten wird.

    Ah, möglicherweise gibt es Code, der etwas ähnliches macht. Es gibt ein Sample, der entlang eines Bezierpfades Text layoutet. Und wenn ich mich recht entsinne, wird a nicht -…flattened… benutzt, sondern der Pfad analysiert. Da müsste man sehen, wie sich das approximieren lässt. Ist aber aus blasser Erinnerung.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • oder man rechnet und zeichnet den Pfad selber. Dann weiß man ja wieviele verschiedene Pixel man gesetzt hat. Ich habe sowas mal gemacht um ein Video an einem Pfad zu bewegen. Man muss die Auflösung der Berechnung halt nur groß genug machen das man auf jeden Fall >1 Punkt pro Pixel erhält und zeichnet dann nur die Pixel welche nicht gleich sind.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)
  • Thallius schrieb:

    oder man rechnet und zeichnet den Pfad selber. Dann weiß man ja wieviele verschiedene Pixel man gesetzt hat. Ich habe sowas mal gemacht um ein Video an einem Pfad zu bewegen. Man muss die Auflösung der Berechnung halt nur groß genug machen das man auf jeden Fall >1 Punkt pro Pixel erhält und zeichnet dann nur die Pixel welche nicht gleich sind.

    Gruß

    Claus

    Haben denn drei Punkte nebeneinander dieselbe Länge wie drei Punkte diagonal? ;) Ich will ab sofort Displays mit 6-eckiger Wabenstrukter der Pixel!!!!!!!!!!!

    Ernsthaft: Dann lieber Teilstücke berechnen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?