2013-04-07 19 views
8

Sto cercando un modo per tracciare una curva di linea attraverso un numero di punti. Sarebbe preferibile utilizzare 3 punti, anche se ho considerato che, per dare un contesto all'angolo della linea che entra in un punto, potrebbe essere necessario più per dare un contesto alla curva, per così dire.Come eseguire una curva di linea attraverso i punti

In generale un punto iniziale P1, un punto di controllo P2 e un punto finale P3, la linea deve curvare verso P2 da P1 e quindi curvare da P2 a P3.

Infatti ecco un perfetto esempio dell'effetto vorrei realizzare:

Irwin Hall Spline

Se potessi fare questo ho davvero sarei eternamente grato!

In Java finora, ho provato a giocare con cose come QuadCurve2D.Double, Cub icCurve2D.Double e anche Path2D.Double (utilizzando curveTo con Path2D.Double), ma senza alcun risultato - le curve che sono dipinte non sono nemmeno vicino a passando per il punto di controllo specificato.

Ecco un'immagine dei metodi che ho provato finora:

enter image description here

E qui è il codice che ho usato per generare i punti e curve nell'immagine:

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); 

Le mie ragioni per cui voglio che una linea curva passi attraverso i punti è che voglio "ammorbidire" la transizione tra i vertici su un grafico a linee che ho scritto. Prima che qualcuno lo menzioni, JFree Chart non è un'opzione. Capisco che ci sono diversi tipi di curve e spline che vengono utilizzati, ma non ho avuto molta fortuna nel capire esattamente come funzionano o come implementare qualcosa che si adatta alle mie esigenze.

Sarei davvero grato per qualsiasi aiuto offerto - Grazie in anticipo.

+0

Mi permetta di chiarire che stai chiedendo di essere in grado di disegnare una curva attraverso una serie di punti? –

+0

Sì, quindi considera che ogni punto della spline di Irwin-Hall è un elemento dell'array. –

risposta

9

Penso che manchi l'idea di cosa sia un punto di controllo . I punti di controllo non sono generalmente sul percorso stesso. Invece controllano come la curva del percorso è modellata tra i punti. Vedere uno spline tutorial per i dettagli completi.

Ora, per il problema in questione, sono presenti punti sulla curva ma non punti di controllo effettivi. Ci sono alcune tecniche, come Cardinal Spline, per derivare i punti di controllo per poi passare ad una delle API di disegno della curva che menzioni. Probabilmente vuoi l'opzione Path2D.Double in modo da poter incolonnare uniformemente le singole curve.

Così per il disegno da P1 a P2 alla P3, invece di

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

Volete

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); 

dove i cx e cy coordinate sono i tuoi punti di controllo derivate, due punti di controllo per spline cubica segmento. Eventualmente,

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; 

Il modello qui è che per i punti interni (solo P2 in questo caso) i punti di controllo prima e dopo (C1B e C2A) sono compensati dalla pendenza della retta tra i punti prima e dopo di esso (P1 e P3). Per i punti di bordo, i punti di controllo si basano sulla pendenza tra quel punto e il prossimo punto più vicino.

Se si dispone di informazioni specifiche del dominio, è possibile scegliere diversi punti di controllo. Ad esempio, potresti voler forzare le pendenze dei punti finali a 0.

+0

Piuttosto sicuro che cx1b e cy1b non dovrebbero essere duplicati? Non dovrebbero essere cx1a cy1a cx1b cy1b? –

+0

Grazie a @JamesC. Risolto ora. – xan

+0

Se non è troppo disturbo potresti far luce sul motivo per cui scegli tali valori xey per costruire i punti di controllo? Perché tutti tranne l'ultima coppia di punti di controllo usano x1, y1? Anche nella seconda coppia cx1b e cy1b sembrano dipendere dalla posizione del punto dopo il punto in cui la curva si sta avvicinando, ma nell'ultima coppia ovviamente non puoi fare quel passo in più da quando ti stai avvicinando all'ultimo punto. Quindi presumo che tu forse usi il futuro punto x3, y3 per giustificare l'angolo della curva che si avvicina al secondo punto, visto che sarà quindi necessario passare al punto futuro? –

2

bene forse questo potrebbe aiutare: P

curve Catmull-Rom per esempio gli stessi principi diversi lang ... http://schepers.cc/svg/path/dotty.svg

+0

Le spline di Catmull-rom differiscono dalle spline di Irwin-hall nel modo in cui viene disegnata la curva. Controlla questa risorsa e disegna alcuni punti, http://blog.ivank.net/interpolation-with-cubic-splines.html –

+0

Grazie per il link Joban tuttavia se consideri [questo esempio] (http://postimg.org/ image/izjajqfw7 /) che ho creato al link che hai fornito puoi vedere la curva (almeno nel mio caso) darebbe erroneamente l'impressione che esistessero valori molto più grandi tra l'ultimo e i punti. L'esempio Catmull-Rom con cui nuotare è accettabile, tuttavia l'implementazione non è chiara: nessuna idea nuota? –

+0

Ok, quindi vuoi una spline rom di catmull allora, hmm che probabilmente dovrebbe essere un po 'più facile. –

2

Fondamentalmente quello che stai chiedendo è per è Cubic Spline di interpolazione, ero in grado di trovare questo programma online Interp2.java. In realtà include una spline polinomiale e una spline cubica.

Sfortunatamente è un'applet e non una classe reale, ma è comunque possibile esaminare il codice e imparare come lo hanno fatto. Che è sempre una buona cosa

Problemi correlati