2013-04-07 7 views
8

Szukam sposobu, aby utworzyć krzywą liniową przez wiele punktów. Byłoby lepiej użyć 3 punktów, chociaż uważałem, że w celu podania kontekstu do kąta linii wchodzącej do punktu może być potrzebne więcej, aby nadać kontekst krzywej, by tak rzec.Jak utworzyć krzywą liniową przez punkty

Ogólnie P1 punktu początkowego punktu kontroli i P2 P3 punktu końcowego linii powinien krzywa z P2-P1, a krzywa z P2-P3.

W rzeczywistości tutaj jest doskonałym przykładem efektu chciałbym osiągnąć:

Irwin Hall Spline

Gdybym mógł to zrobić naprawdę byłaby wdzięczna!

W Javie tak daleko, próbowałem zabawy z rzeczy, takich jak QuadCurve2D.Double, Cub icCurve2D.Double a także Path2D.Double (stosując curveTo z Path2D.Double), ale bezskutecznie - krzywe, które są malowane nie są nawet blisko przejazdem określony punkt kontrolny.

Oto obraz metod próbowałem dotąd:

enter image description here

A oto kod I używany do generowania punktów i krzywych na obrazku:

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

Moje powody, dla których chciałbym, aby zakrzywiona linia przechodziła przez punkty, polega na tym, że chcę "wygładzić" przejście między wierzchołkami na wykresie liniowym, który napisałem. Zanim ktokolwiek o tym wspomina, Wykres JFree nie jest opcją. Rozumiem, że są różne typy krzywych i splajnów, które są używane, ale nie miałem szczęścia w zrozumieniu, jak one działają i jak zaimplementować coś, co odpowiada moim potrzebom.

Byłbym bardzo wdzięczny za każdą oferowaną pomoc - Z góry dziękuję.

+0

Pozwól mi wyjaśnić, czy pytasz o możliwość narysowania krzywej przez szereg punktów? –

+0

Tak, więc należy wziąć pod uwagę, że każdy punkt splajnu Irwin-Hall jest elementem w tablicy. –

Odpowiedz

9

Myślę, że brakuje ci pojęcia, co to jest punkt kontrolny . Punkty kontrolne zwykle nie znajdują się na samej ścieżce. Zamiast tego kontrolują, w jaki sposób krzywa ścieżki jest kształtowana między punktami. Zobacz spline tutorial, aby uzyskać szczegółowe informacje.

Teraz do problemu pod ręką, trzeba punktów na krzywej, ale bez rzeczywistych punktów kontrolnych. Istnieją pewne techniki, takie jak Cardinal Spline, do wyprowadzania punktów kontrolnych, które następnie przechodzą do jednego z interfejsów API rysowania krzywych, o których wspomniałeś. Prawdopodobnie potrzebujesz opcji Path2D.Double, aby móc płynnie łączyć poszczególne krzywe.

Więc do rysowania od P1 do P2 do P3, zamiast

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

Chcesz

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

gdzie cx i cy współrzędne są twoi uzyskane punkty kontrolne, dwa punkty kontrolne za sześcienny splajnu człon. Ewentualnie

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; 

Wzór jest to, że na wewnętrznych punktów (tylko P2 w tym przypadku) punktów kontrolnych przed i po nim (C1b i C2A) są kompensowane przez nachylenie linii między punktami przed i po nim (P1 i P3). W przypadku punktów brzegowych punkty kontrolne opierają się na nachyleniu między tym punktem a najbliższym najbliższym punktem.

Jeśli posiadasz informacje specyficzne dla domeny, możesz wybrać różne punkty kontrolne. Na przykład, możesz chcieć wymusić nachylenie w punktach końcowych 0.

+0

Czy na pewno cx1b i cy1b nie powinny być duplikowane? Czy nie powinny to być cx1a cy1a cx1b cy1b? –

+0

Dzięki @JamesC. Naprawiono teraz. – xan

+0

Jeśli to nie będzie za duży problem, czy możesz rzucić nieco światła na to, dlaczego wybierasz takie wartości x i y, aby zbudować punkty kontrolne? Dlaczego wszystkie oprócz ostatniej pary punktów kontrolnych używają x1, y1? Również w drugiej parze cx1b i cy1b wydają się zależeć od pozycji punktu za punktem, w którym krzywa się zbliża, ale w ostatniej parze najwyraźniej nie można zrobić tego dodatkowego kroku, ponieważ zbliżasz się do tego ostatniego punktu. Zakładam więc, że prawdopodobnie wykorzystasz przyszły punkt x3, y3, aby uzasadnić kąt krzywej zbliżającej się do drugiego punktu widzenia, ponieważ będzie on wtedy płynnie musiał przejść do przyszłego punktu? –

2

dobrze może to może pomóc: P

Catmull-Rom krzywe przykładem tych samych zasadach innym lang ... http://schepers.cc/svg/path/dotty.svg

+0

Krzywe Catmull-rom różnią się od splajnów w kanale Irwina w sposobie rysowania krzywej. Sprawdź ten zasób i narysuj kilka punktów, http://blog.ivank.net/interpolation-with-cubic-splines.html –

+0

Dzięki za link Joban jednak, jeśli rozważasz [ten przykład] (http://postimg.org/ image/izjajqfw7 /), który utworzyłem pod podanym linkiem, widzisz krzywą (przynajmniej w moim przypadku) niesłusznie sprawiał wrażenie, że pomiędzy ostatnimi punktami istniały znacznie większe wartości. Przykład Catmull-Rom, który jest połączony z pływaniem jest akceptowalny, jednak implementacja nie jest jasna - czy pomysły pływają? –

+0

Ok, więc chcesz splajnu cat-cammana, hmm, to prawdopodobnie powinno być trochę łatwiejsze. –

2

Zasadniczo co prosisz jest to Cubic interpolacji spline, byłem w stanie znaleźć ten program online Interp2.java. W rzeczywistości zawiera splajn wielomianu i splajn sześcienny.

Niestety jego aplet a nie rzeczywiste klasy, ale nadal można szukać poprzez kod jest dowiedzieć się, jak oni to zrobili. Co zawsze jest dobre.

Powiązane problemy