0

我们目前正在尝试为 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 类是第三方的,不是我们编写的。 这是错误的图片。 很容易看出,所有航路点产生的线都不是直的,建筑角度应该在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 使用多个纬度航点生成直线的任何想法?

4

0 回答 0