2010-01-26 7 views
5

Irgendwo musste jemand dieses Problem lösen. Ich kann viele tolle Webseiten finden, die dieses Problem erklären und wie man es löst. Obwohl ich mir sicher bin, dass sie gut geschrieben sind und Sinn machen, Mathe-Whizzles, das bin ich nicht. Und während ich vielleicht auf eine vage Art verstehe, verstehe ich nicht, wie ich diese Mathematik in eine Funktion umwandeln kann, die ich benutzen kann.Funktion zum Zurückgeben einer Liste von Punkten auf einer Bezier-Kurve bei gleicher Bogenlänge

Also ich bitte Sie, wenn Sie eine Funktion haben, die dies tun kann, in jeder Sprache, (sicher sogar Fortran oder heck 6502 Assembler) - bitte helfen Sie mir aus.

  • bevorzugen eine analytische zu iterative Lösung

EDIT: seine angeben dazu geführt, dass eine kubische Bezier Ich versuche, mit zu arbeiten.

Antwort

3

Sie fragen nach der Umkehrung der Lichtbogenlängenfunktion. Bei einer Kurve B möchten Sie also eine Funktion Linv (len), die ein t zwischen 0 und 1 zurückgibt, so dass die Bogenlänge der Kurve zwischen 0 und t len ​​ist.

Wenn Sie diese Funktion hatten, ist Ihr Problem wirklich einfach zu lösen. Sei B (0) der erste Punkt. Um den nächsten Punkt zu finden, berechnen Sie einfach B (Linv (w)), wobei w die "gleiche Bogenlänge" ist, auf die Sie sich beziehen. Um den nächsten Punkt zu erhalten, evaluiere einfach B (Linv (2 * w)) und so weiter, bis Linv (n * w) größer als 1 wird.

Ich musste mich in letzter Zeit mit diesem Problem befassen. Ich habe mir ein paar Lösungen ausgedacht, von denen keine für mich zufriedenstellend sind (aber vielleicht werden sie für dich sein).

Nun, das ist ein bisschen kompliziert, also lass mich dir nur den Link zum Quellcode geben: http://icedtea.classpath.org/~dlila/webrevs/perfWebrev/webrev/raw_files/new/src/share/classes/sun/java2d/pisces/Dasher.java. Was Sie wollen, ist in der LengthIterator-Klasse. Sie sollten sich keine anderen Teile der Datei ansehen müssen. Es gibt eine Reihe von Methoden, die in einer anderen Datei definiert sind. Um zu ihnen zu gelangen, schneiden Sie einfach alles von/raw_files/bis zum Ende der URL aus. So benutzen Sie es. Initialisieren Sie das Objekt auf einer Kurve. Um dann den Parameter eines Punktes mit der Bogenlänge L vom Beginn der Kurve zu erhalten, rufen Sie einfach next (L) auf (um den tatsächlichen Punkt zu erhalten, bewerten Sie einfach Ihre Kurve bei diesem Parameter mit deCasteljaus Algorithmus oder dem Zneak-Vorschlag). Jeder nachfolgende Aufruf von next (x) bewegt Sie um einen Abstand von x entlang der Kurve im Vergleich zu Ihrer letzten Position. next gibt eine negative Zahl zurück, wenn Sie keine Kurve mehr haben.

Erläuterung des Codes: Also, ich brauchte einen t-Wert, so dass B (0) bis B (t) die Länge LEN haben würde (wobei LEN bekannt ist). Ich habe die Kurve einfach abgeflacht. Unterteilen Sie die Kurve also nur rekursiv, bis jede Kurve nahe genug an einer Linie ist (Sie können dies testen, indem Sie die Länge des Kontrollpolygons mit der Länge der Linie vergleichen, die die Endpunkte verbindet). Sie können die Länge dieser Unterkurve als (controlPolyLength + endPointsSegmentLen)/2 berechnen. Addiere alle diese Längen zu einem Akkumulator und stoppe die Rekursion, wenn der Akkumulatorwert> = LEN ist. Nennen Sie nun die letzte Unterkurve C und [t0, t1] sei ihre Domäne. Sie wissen, dass das gewünschte t0 < = t < t1 ist, und Sie die Länge von B (0) zu B (t0) kennen - nennen Sie diesen Wert L0t0. Also müssen Sie jetzt ein t finden, so dass C (0) bis C (t) die Länge LEN-L0t0 hat. Dies ist genau das Problem, mit dem wir begonnen haben, aber in einem kleineren Maßstab. Wir könnten Rekursion verwenden, aber das wäre schrecklich langsam, also verwenden wir einfach die Tatsache, dass C eine sehr flache Kurve ist. Wir geben vor, dass C eine Linie ist, und berechnen den Punkt bei t unter Verwendung von P = C (0) + ((LEN-L0t0)/Länge (C)) * (C (1) -C (0)). Dieser Punkt liegt nicht wirklich auf der Kurve, weil er auf der Linie C (0) -> C (1) liegt, aber es ist sehr nahe an dem Punkt, den wir wollen. Also lösen wir einfach Bx (t) = Px und By (t) = Py. Dies ist nur das Finden kubischer Wurzeln, die eine geschlossene Quellenlösung haben, aber ich habe nur Newtons Methode benutzt. Jetzt haben wir das t, das wir wollen, und wir können einfach C (t) berechnen, was der tatsächliche Punkt ist.

Ich sollte erwähnen, dass ich vor ein paar Monaten ein Papier durchforstete, das eine andere Lösung zu diesem hatte, die eine Annäherung an die natürliche Parametrisierung der Kurve fand. Der Autor hat einen Link dazu hier:

+0

Mann schrecklich entschuldigen Sie das nicht kommentieren vor zwei Jahren, als Sie es gepostet haben, mache ich nicht viel auf SO, weil ich keinen Ruf habe (was mich nicht rep machen. . yeah, yeah) .. aber ausgezeichnete Antwort und großes Codebeispiel, jetzt für mich, um die Antwort vollständig zu erhöhen .... – Prozacgod