【问题标题】:Find out the sections where polylines overlap GoogleMap找出折线重叠的部分 GoogleMap
【发布时间】:2021-10-06 14:43:05
【问题描述】:

我想在GoogleMap 上显示几条折线,其中一些可能会重叠,如下图所示。 (它们可能不会完全重叠)。

我的目标是获得一个多段线列表,这些多段线与最初的一组多段线穿过相同的道路,但约束条件是它们不重叠。

对于前一种情况,我可以这样结束:

关于如何实现这一点的一些想法?

【问题讨论】:

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


【解决方案1】:

最简单的方法(如果你没有那么多折线)是使用Google Maps Roads API part Snap to Road which

针对给定的 GPS 坐标集返回最适合的道路几何形状。 该服务最多需要沿路线收集 100 个 GPS 点,并且 返回一组相似的数据,其中的点捕捉到最多 车辆行驶的可能道路。

点赞this example:

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mGoogleMap;
    private MapFragment mapFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mapFragment = (MapFragment) getFragmentManager()
                .findFragmentById(R.id.map_fragment);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mGoogleMap = googleMap;

        List<LatLng> sourcePoints = new ArrayList<>();
        sourcePoints.add(new LatLng(<COORDINATES_OF_POLYLINE>));
        ...
        sourcePoints.add(new LatLng(<COORDINATES_OF_POLYLINE>));

        PolylineOptions polyLineOptions = new PolylineOptions();
        polyLineOptions.addAll(sourcePoints);
        polyLineOptions.width(5);
        polyLineOptions.color(Color.BLUE);
        mGoogleMap.addPolyline(polyLineOptions);

        mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));

        List<LatLng> snappedPoints = new ArrayList<>();
        new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
    }


    private String buildRequestUrl(List<LatLng> trackPoints) {
        StringBuilder url = new StringBuilder();
        url.append("https://roads.googleapis.com/v1/snapToRoads?path=");

        for (LatLng trackPoint : trackPoints) {
            url.append(String.format("%8.5f", trackPoint.latitude));
            url.append(",");
            url.append(String.format("%8.5f", trackPoint.longitude));
            url.append("|");
        }
        url.delete(url.length() - 1, url.length());
        url.append("&interpolate=true");
        url.append(String.format("&key=%s", <your_Google_Maps_API_key>);

        return url.toString();
    }


    private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {

        protected void onPreExecute() {
            super.onPreExecute();
        }

        protected List<LatLng> doInBackground(List<LatLng>... params) {

            List<LatLng> snappedPoints = new ArrayList<>();

            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                URL url = new URL(buildRequestUrl(params[0]));
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();

                InputStream stream = connection.getInputStream();

                reader = new BufferedReader(new InputStreamReader(stream));
                StringBuilder jsonStringBuilder = new StringBuilder();

                StringBuffer buffer = new StringBuffer();
                String line = "";

                while ((line = reader.readLine()) != null) {
                    buffer.append(line+"\n");
                    jsonStringBuilder.append(line);
                    jsonStringBuilder.append("\n");
                }

                JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
                JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");

                for (int i = 0; i < snappedPointsArr.length(); i++) {
                    JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
                    double lattitude = snappedPointLocation.getDouble("latitude");
                    double longitude = snappedPointLocation.getDouble("longitude");
                    snappedPoints.add(new LatLng(lattitude, longitude));
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return snappedPoints;
        }

        @Override
        protected void onPostExecute(List<LatLng> result) {
            super.onPostExecute(result);

            PolylineOptions polyLineOptions = new PolylineOptions();
            polyLineOptions.addAll(result);
            polyLineOptions.width(5);
            polyLineOptions.color(Color.RED);
            mGoogleMap.addPolyline(polyLineOptions);

            LatLngBounds.Builder builder = new LatLngBounds.Builder();
            builder.include(result.get(0));
            builder.include(result.get(result.size()-1));
            LatLngBounds bounds = builder.build();
            mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));

        }
    }

}

(为此,您需要在 Google Cloud Console 中为您的项目添加 Google Maps Roads API 支持)

在您使用 Snap To Road 处理所有“初始”多段线后,所有这些多段线都应该完全重叠,您可以使用 Polyline 的 Z-Index 属性来管理多段线的 Z 顺序。

其他方法是“手动”检测折线的重叠。在这种情况下,您应该:

  1. 决定如何确定应在其他折线之上显示的“主”折线(最长或具有最多点数或其他东西);
  2. 对于“非主”折线的每个点,检查它是否在“主”折线上(您可以使用PolyUtil library 的isLocationOnPath() 方法)并根据检查结果选择线段的颜色:if point在“主要”路径上(以米为单位的指定公差内),您不应显示“非主要”折线段或以其他方式显示选定颜色。

【讨论】:

  • 谢谢。这真的很有帮助,最后一部分是我正在寻找的。因此,对于“非主”折线中的每一段,我使用isLocationOnPath 检查它是否位于“主”折线上。确实如此,我丢弃了那个片段。
  • 关于第一个解决方案,它并不真正适合我的需要。在这个小例子上会很棒。但我更感兴趣的是在代码中获取不重叠的折线列表,而不仅仅是在地图上,因为我需要一次又一次地重用该列表,并且我不想在内存,因为那会浪费资源。此外,我最终可以在地图上渲染 50 条折线,而不仅仅是一条(假设它们都会重叠)。
  • 所以,PolyUtil library 是您的首选。稍后您可以手动实现isLocationOnPath()。
猜你喜欢
  • 1970-01-01
  • 2019-10-29
  • 2013-02-14
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多