Ваша проблема может быть решена с помощью следующих шагов:
Рассчитайте расстояние от точек A и B (используйте формулу Haversine , которая достаточно хорошаздесь, или более сложная формула Винсенти ).Чтобы правильно использовать формулу, микродегиды Android, которые возвращают getLatitude и getLongitude, необходимо преобразовать в радианы, используя следующую формулу:
double radians = Math.toRadians((double)microdegrees/1000000);
Рассчитать направление (направление)из точек А и В (используйте формулу на той же странице).Это будет отличаться от формулы Пифагора, потому что земля круглая, а не плоская.
- Затем вы можете выбрать новое расстояние и рассчитать точку X для данной точки A и опоры, найденной на предыдущем шаге (см.либо «Точка назначения с указанным расстоянием и азимутом от начальной точки» на той же странице, либо прямая формула Винсенти ).
Преобразуйте радианы из сгенерированной точки в микродепуты, используя эту формулу:
int microdegrees = (int)(Math.toDegrees(radians)*1000000);
Собрав все это вместе, мы имеем следующую функцию, которую я помещаю в общественное достояние:
public static int[] getIntermediatePoint(
int startLatMicroDeg,
int startLonMicroDeg,
int endLatMicroDeg,
int endLonMicroDeg,
double t // How much of the distance to use, from 0 through 1
){
// Convert microdegrees to radians
double alatRad=Math.toRadians((double)startLatMicroDeg/1000000);
double alonRad=Math.toRadians((double)startLonMicroDeg/1000000);
double blatRad=Math.toRadians((double)endLatMicroDeg/1000000);
double blonRad=Math.toRadians((double)endLonMicroDeg/1000000);
// Calculate distance in longitude
double dlon=blonRad-alonRad;
// Calculate common variables
double alatRadSin=Math.sin(alatRad);
double blatRadSin=Math.sin(blatRad);
double alatRadCos=Math.cos(alatRad);
double blatRadCos=Math.cos(blatRad);
double dlonCos=Math.cos(dlon);
// Find distance from A to B
double distance=Math.acos(alatRadSin*blatRadSin +
alatRadCos*blatRadCos *
dlonCos);
// Find bearing from A to B
double bearing=Math.atan2(
Math.sin(dlon) * blatRadCos,
alatRadCos*blatRadSin -
alatRadSin*blatRadCos*dlonCos);
// Find new point
double angularDistance=distance*t;
double angDistSin=Math.sin(angularDistance);
double angDistCos=Math.cos(angularDistance);
double xlatRad = Math.asin( alatRadSin*angDistCos +
alatRadCos*angDistSin*Math.cos(bearing) );
double xlonRad = alonRad + Math.atan2(
Math.sin(bearing)*angDistSin*alatRadCos,
angDistCos-alatRadSin*Math.sin(xlatRad));
// Convert radians to microdegrees
int xlat=(int)Math.round(Math.toDegrees(xlatRad)*1000000);
int xlon=(int)Math.round(Math.toDegrees(xlonRad)*1000000);
if(xlat>90000000)xlat=90000000;
if(xlat<-90000000)xlat=-90000000;
while(xlon>180000000)xlon-=360000000;
while(xlon<=-180000000)xlon+=360000000;
return new int[]{xlat,xlon};
}
И вот как она используется:
int ax = oldPoint.getLatitude();
int ay = oldPoint.getLongitude();
int bx = currentPoint.getLatitude();
int by = currentPoint.getLongitude();
long at = oldPoint.getDataRilevamento(); //get time first point
long bt = currentPoint.getDataRilevamento(); // get time second point
long xt = x.getDate(); // time of point to find
// Find relative time from point A to point B
double t=(bt==at) ? 0 : ((double)(xt-at))/((double)(bt-at));
// Find new point given the start and end points and the relative time
int[] xpos=getIntermediatePoint(ax,ay,bx,by,t);
x.setLatitude(xpos[0]); //set the latitude of X
x.setLongitude(xpos[1]); // set the longitude of X