首页 文章

Google Maps API Snap Marker To Polyline

提问于
浏览
-1

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

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

  • 从折线列表中,我选择路径A和B的两个 endpoints .

  • 找出从A到B的方位 .

  • 创建A和B之间相距1米的 LatLng 点列表 .

  • 迭代列表以检查最近的 LatLng 的GPS坐标 .

  • 将我的标记位置设置为最近的 LatLng .

上面的工作在某些情况下,但主要是标记显示平行于折线而不是它 .

有没有其他方法可以让我的标记 snap to the polyline

1 回答

  • 0

    这是我自己实现的捕捉标记到折线(基于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 是我 class 中的私有字段,初始值设置为零 .

    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;
    }
    

相关问题