2013-04-07 6 views
8

Ich suche nach einer Möglichkeit, eine Linie Kurve durch eine Reihe von Punkten zu machen. Es wäre vorzuziehen, 3 Punkte zu verwenden, obwohl ich berücksichtigt habe, dass, um dem Winkel der Linie, die in einen Punkt eintritt, Kontext zu geben, mehr benötigt werden kann, um der Kurve sozusagen einen Kontext zu geben.Wie mache ich eine Linie Kurve durch Punkte

Im Allgemeinen sollte ein Startpunkt P1, ein Steuerpunkt P2 und ein Endpunkt P3 sein, die Linie sollte von P1 zu P2 und dann von P2 zu P3 gekrümmt sein.

In der Tat hier ist ein perfektes Beispiel für die Wirkung würde Ich mag erreichen:

Irwin Hall Spline

Wenn ich dies tun könnte, würde ich wirklich ewig dankbar sein!

In Java bisher habe ich versucht, mit Dingen wie QuadCurve2D.Double, Cub icCurve2D.Double und auch Path2D.Double (mit curveTo mit Path2D.Double) herumspielen, aber ohne Erfolg - die Kurven, die lackiert werden, sind nicht einmal in der Nähe, die durch der Kontrollpunkt angegeben. Hier

ist ein Bild von den Methoden, die ich versucht habe bisher:

enter image description here

Und hier ist der Code, den ich verwenden, um die Punkte und Kurven im Bild zu erzeugen:

Graphics2D g = (Graphics2D) window.getGraphics(); 
    g.setColor(Color.blue); 
    int d = 4; 

    // P0 
    int x0 = window.getWidth()/8; 
    int y0 = 250; 
    g.drawString("P0", x0, y0 + 4*d); 
    g.fillRect(x0, y0, d, d); 

    // P1 
    int x1 = (window.getWidth()/7)*2; 
    int y1 = 235; 
    g.drawString("P1", x1, y1 + 4*d); 
    g.fillRect(x1, y1, d, d); 

    // P2 
    int x2 = (window.getWidth()/2); 
    int y2 = 200; 
    g.drawString("P2", x2, y2 - 2*d); 
    g.fillRect(x2, y2, d, d); 

    // P3 
    int x3 = (window.getWidth()/7)*5; 
    int y3 = 235; 
    g.drawString("P3", x3, y3 + 4*d); 
    g.fillRect(x3, y3, d, d); 

      // P4 
    int x4 = (window.getWidth()/8)*7; 
    int y4 = 250; 
    g.drawString("P4", x4, y4 + 4*d); 
    g.fillRect(x4, y4, d, d); 

    g.setColor(Color.cyan); 
    QuadCurve2D quadCurve = new QuadCurve2D.Double(x0, y0, x2, y2, x4, y4); 
    g.draw(quadCurve); 


    g.setColor(Color.YELLOW); 
    CubicCurve2D.Double cubicCurve = new CubicCurve2D.Double((double)x0, (double)y0, 
                  (double)x1, (double)y1, 
                  (double)x2, (double)y2, 
                  (double)x4, (double)y4); 
    g.draw(cubicCurve); 


    g.setColor(Color.red);  
    Path2D.Double path1 = new Path2D.Double(); 
    path1.moveTo(x1, y1); 
    path1.curveTo(x0, y0, x2, y2, x4, y4); 
    g.draw(path1); 

Ich möchte, dass eine gekrümmte Linie durch Punkte verläuft, dass ich den Übergang zwischen den Scheitelpunkten in einem Liniendiagramm, das ich geschrieben habe, "glätten" möchte. Bevor es jemand erwähnt JFree Chart ist keine Option. Ich verstehe, dass es verschiedene Arten von Kurven und Splines gibt, die verwendet werden, aber ich hatte nicht viel Glück darin, genau zu verstehen, wie sie funktionieren oder etwas umzusetzen, das meinen Bedürfnissen entspricht.

Ich wäre wirklich dankbar für jede Hilfe angeboten - Vielen Dank im Voraus.

+0

Lassen Sie mich klarstellen, ob Sie eine Kurve durch eine Reihe von Punkten zeichnen möchten? –

+0

Ja, beachten Sie, dass jeder Punkt auf dem Irwin-Hall-Spline ein Element im Array ist. –

Antwort

9

Ich denke, Sie vermissen die Idee, was ein Kontrollpunkt ist. Kontrollpunkte befinden sich in der Regel nicht auf dem Pfad selbst. Stattdessen steuern sie, wie die Kurve des Pfades zwischen Punkten geformt wird. Eine vollständige Beschreibung finden Sie unter spline tutorial.

Jetzt zum Problem, Sie haben Punkte auf der Kurve, aber keine tatsächlichen Kontrollpunkte. Es gibt einige Techniken, wie zum Beispiel Cardinal Spline, um Kontrollpunkte abzuleiten, die dann an eine der von Ihnen erwähnten Kurvenzeichnungs-APIs übergeben werden. Sie möchten wahrscheinlich die Path2D.Double Option, so dass Sie einzelne Kurven problemlos aneinanderreihen können.

Also für von P1 bis P2 bis P3 zeichnen, statt

Path2D.Double path1 = new Path2D.Double(); 
path1.moveTo(x1, y1); 
path1.curveTo(x0, y0, x2, y2, x4, y4); 
g.draw(path1); 

Sie wollen

Path2D.Double path1 = new Path2D.Double(); 
path1.moveTo(x1, y1); 
path1.curveTo(cx1a, cy1a, cx1b, cy1b, x2, y2); 
path1.curveTo(cx2a, cy2a, cx2b, cy2b, x3, y3); 
g.draw(path1); 

wo die cx und cy Koordinaten der abgeleiteten Kontrollpunkte sind, zwei Kontrollpunkte pro Cubic Spline Segment. Möglicherweise

cx1a = x1 + (x2 - x1)/3; 
cy1a = y1 + (y2 - y1)/3; 
cx1b = x2 - (x3 - x1)/3; 
cy1b = y2 - (y3 - y1)/3; 
cx2a = x2 + (x3 - x1)/3; 
cy2a = y2 + (y3 - y1)/3; 
cx2b = x3 - (x3 - x2)/3; 
cy2b = y3 - (y3 - y2)/3; 

Das Muster ist hier, dass für die inneren Punkte (nur P2 in diesem Fall), die Kontrollpunkte vor und nach (C1b und C2A) durch die Steigung der Linie zwischen den Punkten versetzt sind vor und danach (P1 und P3). Für die Kantenpunkte basieren die Kontrollpunkte auf der Neigung zwischen diesem Punkt und dem nächstliegenden Punkt.

Wenn Sie domänenspezifische Informationen haben, können Sie verschiedene Kontrollpunkte auswählen. Zum Beispiel könnten Sie die Steigung an den Endpunkten auf 0 setzen wollen.

+0

Ziemlich sicher cx1b und cy1b sollen nicht dupliziert werden? Sollten sie nicht cx1a cy1a cx1b cy1b sein? –

+0

Danke @JamesC. Jetzt behoben. – xan

+0

Wenn es nicht zu viel Mühe gibt, könnten Sie etwas Licht in die Frage bringen, warum Sie solche x- und y-Werte wählen, um die Kontrollpunkte zu konstruieren? Warum verwenden alle außer dem letzten Kontrollpunktpaar x1, y1? Auch im zweiten Paar cx1b und cy1b scheinen sie von der Position des Punktes nach dem Punkt, an dem sich die Kurve nähert, abhängig zu sein, aber im letzten Paar können Sie diesen zusätzlichen Schritt offensichtlich nicht mehr machen, da Sie sich dem letzten Punkt nähern. Also nehme ich an, dass Sie vielleicht den zukünftigen Punkt x3, y3 verwenden, um den Winkel der Kurve zu rechtfertigen, die sich dem zweiten Punkt nähert, da er dann glatt zum nächsten Punkt weitergehen muss? –

2

gut, vielleicht könnte dies helfen: P

Catmull-Rom-Kurven mit gutem Beispiel die gleichen Prinzipien unterschiedlich lang ... http://schepers.cc/svg/path/dotty.svg

+0

Catmull-Rom-Splines unterscheiden sich von Irwin-Hall-Splines in der Art, wie die Kurve gezeichnet wird. Überprüfen Sie diese Ressource und zeichnen Sie einige Punkte, http://blog.ivank.net/interpolation-with-cubic-splines.html –

+0

Danke für den Link Joban aber, wenn Sie [dieses Beispiel] betrachten (http://postimg.org/ image/izjajqfw7 /), die ich an dem Link erstellt habe, den Sie zur Verfügung gestellt haben, können Sie die Kurve sehen (zumindest in meinem Fall) würde fälschlicherweise den Eindruck vermitteln, dass viel größere Werte zwischen den letzten Punkten existierten. Das Catmull-Rom-Beispiel, mit dem man schwimmen kann, ist akzeptabel, aber die Umsetzung ist nicht klar - irgendwelche Ideen schwimmen? –

+0

Ok, du willst also einen Catmull-Rom-Spline, hmm, das dürfte wohl etwas einfacher sein. –

2

Im Grunde, was Sie für die Nachfrage ist Cubic Spline-Interpolation, war ich in der Lage, dieses Programm online zu finden Interp2.java. Es enthält tatsächlich einen Polynom-Spline und einen kubischen Spline.

Leider ist es ein Applet und nicht eine tatsächliche Klasse, aber Sie können immer noch durch den Code schauen sind lernen, wie sie es gemacht haben. Was immer gut ist.

Verwandte Themen