2009-06-02 68 views
2

特別是,我需要一種方法來表示通過一組已知3D點的曲線/樣條曲線,以及通過細分/內插找到曲線/樣條曲線上其他點的方法。是否有一個帶有3D樣條函數的Java庫?

例如,如果我有一組點P0到PN,我想找到P0和P1之間的100個點,這些點位於通過P0和P1的樣條上。

我看到Java3D的KBRotPosScaleSplinePathInterpolator執行了這樣的計算,但它與該API的場景圖模型綁定在一起,我看不到如何返回我需要的值。

回答

1

沒有我知道的內置庫。 Source

+0

事情已經改變,因爲:http://code.google.com/p/toxiclibs提供了一個涼爽Spline3d。 – Martin 2012-02-24 15:12:19

4

您正在尋找類似的產品Catmull Rom spline。事實是,數學並不是all that hard to deal with(一些向量 - 矩陣乘法)。我的建議是,你只需要在代碼中實現你真正需要的樣條線。

Quoting from that article

限定了花鍵的點 稱爲 「控制點」。 Catmull-Rom樣條的 特徵之一是 ,指定曲線將通過所有控制點 - 這不適用於所有類型的 樣條。

An illustration of the Catmull-Rom spline passing through all control points.

爲了計算曲線上的點,需要所期望的 點的任一側上的兩個點 ,在 如左圖所示。該點由 值t指定,該值表示最接近的兩個控制點之間的距離的部分 。

但是,您應該意識到,如果Catmull-Rom樣條曲線在需要緊急轉彎時彼此靠得太近,可能會在控制點導致小回路。

看一下上面的圖片,想象一下p1和p3彼此相鄰,在p2下面(基本上壓縮圖片的右側)。 Catmull-Rom樣條可能會從p0中下來,像現在一樣通過p1,在p2的右側向上並從右向左穿過,從左側穿過並從左向右穿過P3。

這是樣條線構造的結果。

這就像是用相當堅硬的軟管(就像我在水槽下)一樣工作。爲了獲得連接點相近的長條件,我必須添加一個循環。

3

對於任何與曲線背後的數學拼搏的人,您可能會發現this有用,特別是下面的圖片。這個想法很簡單:

t循環從0.0到1.0。

對於灰色集合中的每一對點,計算一個點之間的方式的一小部分(使用t)。這些點顯示在綠色

對於綠色集合中的每一對點,計算它們之間的一部分路徑(使用t)。這一點顯示在黑色

對於t的不同值,黑點將是沿曲線的不同線。

第二張圖片顯示了用一個額外點和一個額外級別的插值重複的相同過程。

我發現這比我找到的任何其他選項更容易理解,實現和擴展到3個維度。

approximating a curve using linear interpolation http://bimixual.org/AnimationLibrary/Bezier_2_big.gif approximating a curve using linear interpolation http://bimixual.org/AnimationLibrary/Bezier_3_big.gif

+0

是的,這被稱爲貝塞爾樣條。如果/當您需要一條從P0通過P1,P2,然後也碰到P3的曲線,則此樣條的問題就會出現。正如你所看到的,P1和P2是Bezier樣條曲線的控制點,但曲線從未觸及它們。 Catmull-Rom樣條曲線與此類似,不同之處在於*將*通過以前的控制點。 – 2009-08-06 00:45:54

+0

截至今日,鏈接被破壞,圖像也消失。 – Chris 2014-07-24 16:21:53

2

我對線性插值有很好的理解,但是我發現很難掌握樣條數學的複雜性。這就是爲什麼我正在尋找一種能夠提供隱藏困難數學的抽象圖書館。以下功能足以滿足我的需求。這是基於在http://www.mvps.org/directx/articles/catmull/找到的公式,但幸運的是,你不需要了解它是如何工作的。只要記住,不像線性插值,你只需要兩點就可以開始,Catmull-Rom樣條插值在兩端使用一個額外的點。所以如果你想要一個通過10個點的樣條曲線,你需要12個。

這個函數演示一維中的Catmull-Rom樣條插值。 (對於2或3維,只需使用Y或Z值重複)。此函數將給出p1和p2之間的樣條曲線上的一個點,其中t是兩者之間距離的比例。

public class SplineTest { 

    // Catmull-Rom spline interpolation function 
    public static double q(double t, double p0, double p1, double p2, double p3) { 

     return 0.5 * ((2 * p1) + (-p0 + p2) * t 
       + (2 * p0 - 5 * p1 + 4 * p2 - p3) * (t * t) + (-p0 + 3 * p1 - 3 
       * p2 + p3) 
       * (t * t * t)); 
    } 

    public static void main(String[] args) { 
     double t = 0.0; 
     while (t <= 1.0) { 
      System.out.println(q(t, 5, 10, 20, 10)); 
      t += 0.1; 
     } 
    } 
} 

該程序的輸出:

10.0 
10.887500000000001 
12.0 
13.2625 
14.6 
15.9375 
17.2 
18.3125 
19.2 
19.7875 
20.000000000000004 
相關問題