我们目前正在尝试为osmdroid开发一种航路点系统。用户可以放置依赖于用户当前正在进行的建筑物的航路点
建筑物数据包括一个角度,因此航路点之间的所有线路都是相对于原始角度的90°的倍数。例如,如果建筑角度(与水平线相比测量)为20.5°,则所有航点连接应为20.5°,110.5°,200.5°或290.5°。拖动航点时,航点位置应按照触点与任意有效角度之间的最短角度捕捉到方向。
我们制定了一个算法,该算法采用触摸坐标和最后一个航点,比较坐标并计算它们之间的角度,将它们转换为原点,围绕获得90°倍数所需的最小角度旋转并向后平移。算法本身似乎是有效的,但有时候,线条变得“曲线”,而osmdroid似乎会让路点在拖动时获得跳跃。这些飞跃非常小,但在查看整个地图时非常明显。
这是捕捉航点坐标的代码:
public static GeoPoint getSnappedCoordinates(Waypoint w, double[] touchCoordinatesUTM, double mapRotation) {
double[] parentWaypoint = w.getUTMCoordinatesAsDoubleArray();
// Angle to x-axis
double touchAngle = getAngleBetweenTwoPointsWithFixedPoint(touchCoordinatesUTM, new double[]{parentWaypoint[0], parentWaypoint[1]+1}, parentWaypoint);
// set up valid degrees
ArrayList<Double> validDegrees = new ArrayList<>();
if (mapRotation < 0)
mapRotation = 360 + mapRotation;
double curDeg = mapRotation;
while (!validDegrees.contains(curDeg)) {
validDegrees.add(curDeg);
curDeg += deg;
curDeg %= 360;
}
// get closest valid angle
double minAngleDist = Double.POSITIVE_INFINITY;
for (Double d : validDegrees) {
double curDist = Math.abs(d - touchAngle);
if (curDist < Math.abs(minAngleDist)) {
minAngleDist = d - touchAngle;
}
}
minAngleDist = GeoTransform.deg2rad(minAngleDist);
// translate to origin
double translatedX = touchCoordinatesUTM[0] - parentWaypoint[0];
double translatedY = touchCoordinatesUTM[1] - parentWaypoint[1];
// rotate
double[] pointR = {parentWaypoint[0] + translatedX * Math.cos(minAngleDist) - translatedY*Math.sin(minAngleDist),
parentBeacon[1] + translatedX*Math.sin(minAngleDist) + translatedY*Math.cos(minAngleDist)};
double[] res = GeoTransform.UTMXYToLatLon(pointR[1], pointR[0], 32, false);
// return rotated GeoPoint
GeoPoint p = new GeoPoint(GeoTransform.rad2deg(res[0]), GeoTransform.rad2deg(res[1]));
return p;
}
GeoTransform级是第三方,不是我们编写的。
This is a picture of the error.
很容易看出,所有航点产生的直线都不是直的,建筑角度应该在3°左右。问题是,航点连接角度远不一致。以下是我们已经尝试消除错误的一些事项:
1.产生一条斜率等于建筑物角度的直线并计算y位置而不是旋转坐标
2.旋转屏幕像素而不是UTM坐标,让地图投影在像素和LatLon之间转换(以查看错误是否来自GeoTransform)
根本没有任何帮助甚至改变错误。无论我们做了什么,航点都会在拖动它们时采取这些小跳跃,并且它们产生的线不会是直的。 我们使用XML序列化这些航路点,并且LatLon坐标在大多数情况下都是这样的:
<GeoPoint>
<Lat>X.489174999999996</Lat>
<Lon>X.404693999999999</Lon>
</GeoPoint>
(用x替换实际的latlon值) 这看起来像一个双十进制错误。大多数这些航路点的小数点都有“99999”。上述解决方案没有改变任何有关该方面的内容。如所预期的那样,打印所得到的角度导致不同的角度,从90°到最大0.02。我们的航点扩展了Marker类,我们在OnMarkerDragListener中设置了位置,实现如下:
double[] eventPosUTM = GeoTransform.ell2utm(eventPos.getLatitude(), eventPos.getLongitude());
marker.setPosition(getSnappedCoordinates(marker.getConnectedEdges().get(0).getOtherWaypoint(marker), eventPosUTM, marker.getLevel().getRotationDeg()));
我们现在处理边缘的方式或多或少是典型的,应用程序应该只是后端,由知道如何实现的用户处理。 当用户可以拖动这些航点并且应用程序应该捕捉它们时,有关如何使用osmdroid使用多个latlon航点生成直线的任何想法?