地图上的规则形状多边形 Android 地图 单击

Regular Shape polygon Android map on Map Click

无论点击地图的顺序如何,我都想创建一个正多边形。目前我遇到一个问题,如果在地图上单击以下列方式绘制多边形,那么它可以正常工作顺序如下 左上右上右下左下。如果保持此顺序,则绘制的多边形非常好,如果我单击右上角,左上角,右下角,它也可以很好地绘制。如果当我更改单个 pint 时它不会绘制正确形状的多边形 图片1

图 2

代码 2 绘制多边形如下

     gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                llClearSelection.setVisibility(View.VISIBLE);
                gMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)).position(latLng));
                if (markerClicked) {
//                    latLngArrayListPolygon.clear();
                    if (polygon != null) {
                        polygon.remove();
                        polygon = null;
                    }

                    polygonOptions.add(latLng);
                    latLngArrayListPolygon.add(latLng);
                    polygonOptions.strokeColor(Color.RED);
                    polygonOptions.fillColor(shadeColor);
                    polygon = gMap.addPolygon(polygonOptions);
                    if (latLngArrayListPolygon.size() > 1)
                        ivSaveMap.setVisibility(View.VISIBLE);
                    else
                        ivSaveMap.setVisibility(View.GONE);
                } else {
                    if (polygon != null) {
                        polygon.remove();
                        polygon = null;
                    }
                    polygonOptions = new PolygonOptions().add(latLng);
                    latLngArrayListPolygon.add(latLng);
                    markerClicked = true;
                }
            }
        });

我担心的是我想绘制一个规则的形状,而不考虑在地图上的点击顺序

看看How can I determine whether a 2D Point is within a Polygon?

当您的用户在地图上单击时,您必须确定新顶点是在多边形内还是在多边形外。如果在里面,请忽略。否则,添加多边形和 运行 多边形中每个点的算法。

希望对您有所帮助。

最后我得出了创建规则形状多边形的解决方案。这与凸包无关。 以下是创建规则形状多边形的步骤,无论您是在地图上顺时针单击还是在地图上逆时针单击。

  1. Find the mid points of the edges of polygon
  2. Calculate the nearest coordinate by finding distance between mid point of each edge and the coordinate to be drawn
  3. The nearest coordinate = the edge with minimum distance from mid point to the coordinate to be drawn
  4. move the nearest coordinate at the end by shifting array right Following is the code :
 ArrayList<LatLng> latLngArrayListPolygon = new ArrayList<>();
ArrayList<Double> distancesFromMidPointsOfPolygonEdges = new ArrayList<>();
    private void adjustPolygonWithRespectTo(LatLng point) {
        double minDistance = 0;

        if (latLngArrayListPolygon.size() > 2) {
            distancesFromMidPointsOfPolygonEdges.clear();
            //midPointsOfPolygonEdges?.removeAll()

            for (int i = 0; i < latLngArrayListPolygon.size(); i++) {
                // 1. Find the mid points of the edges of polygon
                ArrayList<LatLng> list = new ArrayList<>();

                if (i == (latLngArrayListPolygon.size() - 1)) {
                    list.add(latLngArrayListPolygon.get(latLngArrayListPolygon.size() - 1));
                    list.add(latLngArrayListPolygon.get(0));
                } else {
                    list.add((latLngArrayListPolygon.get(i)));
                    list.add((latLngArrayListPolygon.get(i + 1)));
                }


                LatLng midPoint = computeCentroid(list);

                // 2. Calculate the nearest coordinate by finding distance between mid point of each edge and the coordinate to be drawn
                Location startPoint = new Location("");
                startPoint.setLatitude(point.latitude);
                startPoint.setLongitude(point.longitude);
                Location endPoint = new Location("");
                endPoint.setLatitude(midPoint.latitude);
                endPoint.setLongitude(midPoint.longitude);
                double distance = startPoint.distanceTo(endPoint);

                distancesFromMidPointsOfPolygonEdges.add(distance);
                if (i == 0) {
                    minDistance = distance;
                } else {

                    if (distance < minDistance) {
                        minDistance = distance;
                    }
                }
                //midPointsOfPolygonEdges?.append(midPoint)
            }

            // 3. The nearest coordinate = the edge with minimum distance from mid point to the coordinate to be drawn
            int position = minIndex(distancesFromMidPointsOfPolygonEdges);


            // 4. move the nearest coordinate at the end by shifting array right
            int shiftByNumber = (latLngArrayListPolygon.size() - position - 1);

            if (shiftByNumber != latLngArrayListPolygon.size()) {
                latLngArrayListPolygon = rotate(latLngArrayListPolygon, shiftByNumber);
            }
        }

        // 5. Now add coordinated to be drawn
        latLngArrayListPolygon.add(point);
    }

    public static int minIndex(ArrayList<Double> list) {
        return list.indexOf(Collections.min(list));
    }

    public static <T> ArrayList<T> rotate(ArrayList<T> aL, int shift) {
        if (aL.size() == 0)
            return aL;

        T element = null;
        for (int i = 0; i < shift; i++) {
            // remove last element, add it to front of the ArrayList
            element = aL.remove(aL.size() - 1);
            aL.add(0, element);
        }

        return aL;
    }

    private LatLng computeCentroid(List<LatLng> points) {
        double latitude = 0;
        double longitude = 0;
        int n = points.size();

        for (LatLng point : points) {
            latitude += point.latitude;
            longitude += point.longitude;
        }

        return new LatLng(latitude / n, longitude / n);
    }

点击地图绘制多边形如下

 gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            gMap.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker)).position(latLng));
            if (markerClicked) {
                if (polygon != null) {
                    polygon.remove();
                    polygon = null;
                }
                adjustPolygonWithRespectTo(latLng);
                PolygonOptions polygonOptions = null;
                for (int i = 0; i < latLngArrayListPolygon.size(); i++)
                    if (i == 0)
                        polygonOptions = new PolygonOptions().add(latLngArrayListPolygon.get(0));
                    else
                        polygonOptions.add(latLngArrayListPolygon.get(i));
                polygonOptions.strokeColor(Color.BLACK);
                polygonOptions.strokeWidth(5f);
                polygonOptions.fillColor(shadeColor);
                polygon = gMap.addPolygon(polygonOptions);
            } else {
                if (polygon != null) {
                    polygon.remove();
                    polygon = null;
                }
                polygonOptions = new PolygonOptions().add(latLng);
                latLngArrayListPolygon.add(latLng);
                markerClicked = true;
            }
        }

    });