2014-04-30 51 views
0

我已經構建了Java中的太陽系模型。爲了確定一個行星的位置,它確實做了很多計算,這些計算給出了一個非常精確的值。不過,我常常對大概的位置感到滿意,如果這可能會讓它更快。因爲我在模擬中使用它非常重要,因爲這個星球的位置將被要求數百萬次。一組點之間的快速插值

目前我嘗試緩存行星在整個軌道上的位置,然後反覆使用這些座標。如果請求兩個值之間的位置,則執行線性插值。這就是我如何存儲值:

for(int t=0; t<tp; t++) { 
    listCoordinates[t]=super.coordinates(ti+t); 
} 

interpolator = new PlanetOrbit(listCoordinates,tp); 

PlanetOrbit有插值代碼:

package cometsim; 

import org.apache.commons.math3.util.FastMath; 

public class PlanetOrbit { 

    final double[][] coordinates; 
    double tp; 

    public PlanetOrbit(double[][] coordinates, double tp) { 
     this.coordinates = coordinates; 
     this.tp = tp; 
    } 

    public double[] coordinates(double julian) { 
     double T = julian % FastMath.floor(tp); 

     if(coordinates.length == 1 || coordinates.length == 0) return coordinates[0]; 

     if(FastMath.round(T) == T) return coordinates[(int) T]; 

     int floor = (int) FastMath.floor(T); 

     if(floor>=coordinates.length) floor=coordinates.length-5; 

     double[] f = coordinates[floor]; 
     double[] c = coordinates[floor+1]; 

     double[] retval = f; 
     retval[0] += (T-FastMath.floor(T))*(c[0]-f[0]); 
     retval[1] += (T-FastMath.floor(T))*(c[1]-f[1]); 
     retval[2] += (T-FastMath.floor(T))*(c[2]-f[2]); 

     return retval; 
    } 
} 

你能想到的FastMathMath但速度更快。然而,這個代碼在每次計算精確值方面速度並沒有太大提高。你對如何加快速度有什麼想法嗎?

+0

是我讀這正確的方法'座標'實際上改變字段內的值' coordinates'? –

+0

@RichardTingle在代碼'coordinates'的第一個片段中,爲每個't'返回一個三個值的數組,這些數組存儲在'listCoordinates'中。 'listCoordinates'被賦予'PlanetOrbit'來存儲它。從此以後從未改變,但我使用該列表來獲取該位置。 'PlanetOrbit.coordinates'是我在模擬過程中要調用的方法來找出行星的位置。 –

+0

好吧,我強烈建議不要調用所有的「座標」。我的意思是PlanetOrbit#協調的方法。在該方法中,f =座標[floor];'然後'double [] retval = f;'然後'retval'被修改 –

回答

1

有幾個問題,我所看到的,是主要的,我可以看到如下

  • PlanetOrbit#coordinates似乎在變量coordinates真正改變的值。由於這種方法只能插入,我認爲你的軌道實際上每次運行時都會略微損壞(因爲它是線性插值,軌道實際上會降低到它的中心)。
  • 你多次做同樣的事情,最清楚的是T-FastMath.floor(T)在代碼中發生3次單獨的時間。
  • 不是一個效率或準確性的問題,但變量和方法名稱是非常不透明的,使用真正的單詞作爲變量名稱。

我所提出的方法是如下

public double[] getInterpolatedCoordinates(double julian){ //julian calendar? This variable name needs to be something else, like day, or time, or whatever it actually means 
    int startIndex=(int)julian; 
    int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around 

    double nonIntegerPortion=julian-startIndex; 


    double[] start = coordinates[startIndex]; 
    double[] end = coordinates[endIndex]; 

    double[] returnPosition= new double[3]; 

    for(int i=0;i< start.length;i++){ 
     returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion; 
    } 
    return returnPosition; 
} 

這避免了破壞座標陣列和避免重複同一樓層數次(1-nonIntegerPortion還是做幾次,如果需要的話,但我可以去掉期望分析將顯示它不重要)。但是,它每次都會創建一個新的double [],如果您只需要臨時存儲陣列,效率可能會很低。這可以糾正使用商店對象(您先前使用但不再需要的對象,通常從前一個循環)

public double[] getInterpolatedCoordinates(double julian, double[] store){ 
    int startIndex=(int)julian; 
    int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around 

    double nonIntegerPortion=julian-startIndex; 


    double[] start = coordinates[startIndex]; 
    double[] end = coordinates[endIndex]; 

    double[] returnPosition= store; 

    for(int i=0;i< start.length;i++){ 
     returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion; 
    } 
    return returnPosition; //store is returned 
} 
+0

謝謝,這個答案是偉大的,非常有幫助。我喜歡'store'的訣竅,我以前從未見過。 –