我用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;
}
}
您可以将FastMath
视为Math
但速度更快。但是,这个代码与每次计算精确值相比并没有太大的速度提升。您对如何加快速度有任何想法吗?
答案 0 :(得分: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
}