Android 地图bezier曲线点的计算
我正在计算一条bezier曲线到地理位置点之间的必要点数,以便在Google Maps V2上绘制这条线。我的问题是,如果必须在“太平洋上空”划一条线,例如,起点在东京,终点在温哥华,那么这条线就不能正常工作。这些点的计算方向是错误的(绕地球向东),而不是向西。跨大西洋或亚洲的位置点计算和绘制正确 我的代码或思维中的错误在哪里 以下是用于计算的代码:Android 地图bezier曲线点的计算,android,google-maps,google-maps-android-api-2,bezier,android-maps-v2,Android,Google Maps,Google Maps Android Api 2,Bezier,Android Maps V2,我正在计算一条bezier曲线到地理位置点之间的必要点数,以便在Google Maps V2上绘制这条线。我的问题是,如果必须在“太平洋上空”划一条线,例如,起点在东京,终点在温哥华,那么这条线就不能正常工作。这些点的计算方向是错误的(绕地球向东),而不是向西。跨大西洋或亚洲的位置点计算和绘制正确 我的代码或思维中的错误在哪里 以下是用于计算的代码: public static ArrayList<LatLng> bezier(LatLng p1, LatLng p2, double
public static ArrayList<LatLng> bezier(LatLng p1, LatLng p2, double arcHeight, double skew, boolean up){
ArrayList<LatLng> list = new ArrayList<LatLng>();
try {
if(p1.longitude > p2.longitude){
LatLng tmp = p1;
p1 = p2;
p2 = tmp;
}
LatLng c = midPoint(p1, p2, 0);
Log.v(TAG, "P1: " + p1.toString());
Log.v(TAG, "P2: " + p2.toString());
Log.v(TAG, "C: " + c.toString());
double cLat = c.latitude;
double cLon = c.longitude;
//add skew and arcHeight to move the midPoint
if(Math.abs(p1.longitude - p2.longitude) < 0.0001){
if(up){
cLon -= arcHeight;
}else{
cLon += arcHeight;
cLat += skew;
}
}else{
if(up){
cLat += arcHeight;
}else{
cLat -= arcHeight;
cLon += skew;
}
}
list.add(p1);
//calculating points for bezier
double tDelta = 1.0/10;
for (double t = 0; t <= 1.0; t+=tDelta) {
double oneMinusT = (1.0-t);
double t2 = Math.pow(t, 2);
double lon = oneMinusT * oneMinusT * p1.longitude
+ 2 * oneMinusT * t * cLon
+ t2 * p2.longitude;
double lat = oneMinusT * oneMinusT * p1.latitude
+ 2 * oneMinusT * t * cLat
+ t2 * p2.latitude;
Log.v(TAG, "t: " + t + "[" + lat +"|" + lon + "]");
list.add(new LatLng(lat, lon));
}
list.add(p2);
} catch (Exception e) {
Log.e(TAG, "bezier", e);
}
return list;
}
这是地图的截图:
我决定将地理位置转换为a,然后进行计算。这起作用了 以下是变化:
//inside bezier(...)
CartesianCoordinates cart1 = new CartesianCoordinates(p1);
CartesianCoordinates cart2 = new CartesianCoordinates(p2);
CartesianCoordinates cart3 = new CartesianCoordinates(cLat, cLon);
for (double t = 0; t <= 1.0; t += tDelta) {
double oneMinusT = (1.0 - t);
double t2 = Math.pow(t, 2);
double y = oneMinusT * oneMinusT * cart1.y + 2 * t * oneMinusT * cart3.y + t2 * cart2.y;
double x = oneMinusT * oneMinusT * cart1.x + 2 * t * oneMinusT * cart3.x + t2 * cart2.x;
double z = oneMinusT * oneMinusT * cart1.z + 2 * t * oneMinusT * cart3.z + t2 * cart2.z;
LatLng control = CartesianCoordinates.toLatLng(x, y, z);
if (Config.DEBUG)
Log.v(TAG, "t: " + t + control.toString());
list.add(control);
}
计算两个坐标中点的方法(可能不是100%完全数学正确):
我决定将地理位置转换为a,然后进行计算。这起作用了 以下是变化:
//inside bezier(...)
CartesianCoordinates cart1 = new CartesianCoordinates(p1);
CartesianCoordinates cart2 = new CartesianCoordinates(p2);
CartesianCoordinates cart3 = new CartesianCoordinates(cLat, cLon);
for (double t = 0; t <= 1.0; t += tDelta) {
double oneMinusT = (1.0 - t);
double t2 = Math.pow(t, 2);
double y = oneMinusT * oneMinusT * cart1.y + 2 * t * oneMinusT * cart3.y + t2 * cart2.y;
double x = oneMinusT * oneMinusT * cart1.x + 2 * t * oneMinusT * cart3.x + t2 * cart2.x;
double z = oneMinusT * oneMinusT * cart1.z + 2 * t * oneMinusT * cart3.z + t2 * cart2.z;
LatLng control = CartesianCoordinates.toLatLng(x, y, z);
if (Config.DEBUG)
Log.v(TAG, "t: " + t + control.toString());
list.add(control);
}
计算两个坐标中点的方法(可能不是100%完全数学正确):
您可能希望将此设置为正确答案,以便其他人不会在尝试回答时查看它。您介意给出您的中点方法吗?我正在尝试实现一个非常接近于此的目标:)您可能希望将此设置为正确答案,这样其他人就不会通过查看来尝试回答。您介意给出您的中点方法吗?我正在努力实现与此非常接近的目标:)
private static class CartesianCoordinates {
private static final int R = 6371; // approximate radius of earth
double x;
double y;
double z;
public CartesianCoordinates(LatLng p) {
this(p.latitude, p.longitude);
}
public CartesianCoordinates(double lat, double lon) {
double _lat = Math.toRadians(lat);
double _lon = Math.toRadians(lon);
x = R * Math.cos(_lat) * Math.cos(_lon);
y = R * Math.cos(_lat) * Math.sin(_lon);
z = R * Math.sin(_lat);
}
public static LatLng toLatLng(double x, double y, double z){
return new LatLng(Math.toDegrees(Math.asin(z / R)), Math.toDegrees(Math.atan2(y, x)));
}
}
private static LatLng midPoint(LatLng p1, LatLng p2) throws IllegalArgumentException{
if(p1 == null || p2 == null)
throw new IllegalArgumentException("two points are needed for calculation");
double lat1;
double lon1;
double lat2;
double lon2;
//convert to radians
lat1 = Math.toRadians(p1.latitude);
lon1 = Math.toRadians(p1.longitude);
lat2 = Math.toRadians(p2.latitude);
lon2 = Math.toRadians(p2.longitude);
double x1 = Math.cos(lat1) * Math.cos(lon1);
double y1 = Math.cos(lat1) * Math.sin(lon1);
double z1 = Math.sin(lat1);
double x2 = Math.cos(lat2) * Math.cos(lon2);
double y2 = Math.cos(lat2) * Math.sin(lon2);
double z2 = Math.sin(lat2);
double x = (x1 + x2)/2;
double y = (y1 + y2)/2;
double z = (z1 + z2)/2;
double lon = Math.atan2(y, x);
double hyp = Math.sqrt(x*x + y*y);
// HACK: 0.9 and 1.1 was found by trial and error; this is probably *not* the right place to apply mid point shifting
double lat = Math.atan2(.9*z, hyp);
if(lat>0) lat = Math.atan2(1.1*z, hyp);
if(Config.DEBUG)
Log.v(TAG, Math.toDegrees(lat) + " " + Math.toDegrees(lon));
return new LatLng(Math.toDegrees(lat), Math.toDegrees(lon));
}