【问题标题】:Google Maps API Snap Marker To PolylineGoogle Maps API 捕捉标记到折线
【发布时间】:2018-12-01 16:28:11
【问题描述】:

我有一个在 Google 地图上绘制的折线列表(来自 Google Directions API)。接下来,我希望我的标记在不使用 Google Maps Roads API 的情况下沿着这条线移动。

为了解决这个问题,这是我目前正在做的事情:

  1. 从折线列表中,我选择了路径 A 和 B 的两个端点。
  2. 找出从 A 到 B 的方位。
  3. 创建 A 和 B 之间相距 1 米的 LatLng 点列表。
  4. 遍历列表以检查最近的LatLng 的 GPS 坐标。
  5. 将我的标记位置设置为最近的LatLng

上述方法在某些情况下有效,但大多数情况下,标记平行于不在其上的折线显示。

有没有其他方法可以让我的标记捕捉到折线

【问题讨论】:

标签: google-maps google-maps-api-3


【解决方案1】:

这是我自己的将标记捕捉到折线的实现(基于 GPS 位置):

首先,使用折线点创建距离较小的LatLng 列表(我使用的是splitPathIntoPoints 函数中指定的一米距离):

for (int i = 0; i < polylinePoints.size(); i++) {
    LatLng src = new LatLng(Double.parseDouble(polylinePoints.get(i).get("lat")), Double.parseDouble(polylinePoints.get(i).get("lng")));

    if (polylinePoints.size() > i + 1) {
        LatLng dest = new LatLng(Double.parseDouble(polylinePoints.get(i + 1).get("lat")), Double.parseDouble(polylinePoints.get(i + 1).get("lng")));
        List<LatLng> splitPoints = splitPathIntoPoints(src, dest);
        mSplitPoints.addAll(splitPoints);
    } else {
        break;
    }
}

splitPathIntoPoints 的代码:

public static List<LatLng> splitPathIntoPoints(LatLng source, LatLng destination) {
    Float distance = findDistance(source, destination);

    List<LatLng> splitPoints = new ArrayList<>();
    splitPoints.add(source);
    splitPoints.add(destination);

    while (distance > 1) {
        int polypathSize = splitPoints.size();
        List<LatLng> tempPoints = new ArrayList<>();
        tempPoints.addAll(splitPoints);

        int injectionIndex = 1;

        for (int i = 0; i < (polypathSize - 1); i++) {
            LatLng a1 = tempPoints.get(i);
            LatLng a2 = tempPoints.get(i + 1);

            splitPoints.add(injectionIndex, findMidPoint(a1, a2));
            injectionIndex += 2;
        }

        distance = findDistance(splitPoints.get(0), splitPoints.get(1));
    }

    return splitPoints;
}

findDistance 的代码:

public static Float findDistance(LatLng source, LatLng destination) {
    Location srcLoc = new Location("srcLoc");
    srcLoc.setLatitude(source.latitude);
    srcLoc.setLongitude(source.longitude);

    Location destLoc = new Location("destLoc");
    destLoc.setLatitude(destination.latitude);
    destLoc.setLongitude(destination.longitude);

    return srcLoc.distanceTo(destLoc);
}

findMidPoint 的代码:

public static LatLng findMidPoint(LatLng source, LatLng destination) {
    double x1 = toRad(source.latitude);
    double y1 = toRad(source.longitude);

    double x2 = toRad(destination.latitude);
    double y2 = toRad(destination.longitude);

    double Bx = Math.cos(x2) * Math.cos(y2 - y1);
    double By = Math.cos(x2) * Math.sin(y2 - y1);
    double x3 = toDeg(Math.atan2(Math.sin(x1) + Math.sin(x2), Math.sqrt((Math.cos(x1) + Bx) * (Math.cos(x1) + Bx) + By * By)));
    double y3 = y1 + Math.atan2(By, Math.cos(x1) + Bx);
    y3 = toDeg((y3 + 540) % 360 - 180);

    return new LatLng(x3, y3);
}

一旦mSplitPoints 填充了彼此相距 1 米的较小折线点,下面的函数会根据我当前的 GPS 位置在折线上找到捕捉的位置。请注意,mMinorIndexTravelled 是我班级中的一个私有字段,初始值设置为零。

public static LatLng snapToPolyline(LatLng currentLocation) {
    LatLng snappedLatLng = null;

    Location current = new Location("current");
    current.setLatitude(currentLocation.latitude);
    current.setLongitude(currentLocation.longitude);

    Integer minConfirmCount = 0;
    float currentMinDistance = 0, previousMinDistance = 0;
    List<Float> distances = new ArrayList<>();

    for (LatLng point: mSplitPoints.subList(mMinorIndexTravelled, mSplitPoints.size() - 1)) {
        Location pointLoc = new Location("pointLoc");
        pointLoc.setLatitude(point.latitude);
        pointLoc.setLongitude(point.longitude);

        distances.add(current.distanceTo(pointLoc));
        previousMinDistance = currentMinDistance;
        currentMinDistance = Collections.min(distances);

        if (currentMinDistance == previousMinDistance) {
            minConfirmCount++;
            if (minConfirmCount > 10) {
                mMinorIndexTravelled = distances.indexOf(currentMinDistance) + mMinorIndexTravelled;
                snappedLatLng = mSplitPoints.get(mMinorIndexTravelled);

                break;
            }
        }
    }

    return snappedLatLng;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 2014-11-05
    • 2014-02-14
    相关资源
    最近更新 更多