2

I've got a Google Map with Polygons, I've got everything to work except this last part which is detect if a Marker is already inside a Polygon.The current situation is when I touch a Polygon it will add the Marker"which is correct" but if I touch the Polygon in a different spot it will remove the Marker and add a new one. What I want to happen is if a Marker is already within those points don't add a new one. My code is below any help would be appreciate.

public void onMapClick(LatLng point) {


    for (int j = 0; j < arrPolygons.size(); j++) {

        if (isPointInPolygon(point, arrPolygons.get(j).getPoints())) {

        if (marker != null) {
                marker.remove();
                marker = null;
                Log.v("Marker", "Removing Marker");
            }else{
                marker = googleMap.addMarker(new MarkerOptions()
                        .position(point)
                        .title("test")
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
                Log.v("Marker", "ADDing Marker");
            }
        }
    }

Any help would be appreciated.

Dwill
  • 506
  • 1
  • 5
  • 22
  • look at this question, it can be easily converted to use google maps http://stackoverflow.com/questions/217578/point-in-polygon-aka-hit-test – tyczj Jul 14 '15 at 16:25

1 Answers1

2

The easiest way to do this would be using the Google Maps Android API Utility Library, which contains the PolyUtil class.

First import the library by adding the current version to your build.gradle, currently 0.3.4 for example:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.1'
    compile 'com.google.android.gms:play-services-maps:7.3.0'
    compile 'com.google.maps.android:android-maps-utils:0.3.4'
}

For this simple example we'll assume the Map Activity class definition and member variables look like this, and only one Polygon defined in polygonList:

import com.google.maps.android.PolyUtil;
//other imports.....

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;
    List<LatLng> polygonList = new ArrayList<LatLng>();
    //.............

You would then set up your GoogleMap.OnMapClickListener like this in order to only add one Marker inside the Polygon.:

  mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

        @Override
        public void onMapClick(LatLng point) {

            if (PolyUtil.containsLocation(point, polygonList, false)) {

                if (marker == null) {
                    //only add Marker if there is not one already inside the Polygon
                    marker = mMap.addMarker(new MarkerOptions()
                            .position(point)
                            .title("test")
                            .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
                    Log.v("Marker", "ADDing Marker");

                }

            }
        }
    });

Multiple Polygons, Multiple Markers Solution:

In order to make it work with multiple Ploygons, you could use a POJO to store Polygon/Marker pairs:

public class PolyMarkerObject{
    Polygon polygon;
    Marker marker;
}

Then define a new member variable polyMarkerList:

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    List<PolyMarkerObject> polyMarkerList = new ArrayList<>();
    //.............

Add each Polygon to the list when drawing it:

    List<LatLng> newPolygon = new ArrayList<>();
    //set up the points in the Polygon.......

    Polygon p = mMap.addPolygon(new PolygonOptions()
            .addAll(newPolygon)
            .strokeColor(Color.RED)
            .fillColor(Color.BLUE));

    PolyMarkerObject newPolyMarkerObj = new PolyMarkerObject();
    newPolyMarkerObj.polygon = p;
    polyMarkerList.add(newPolyMarkerObj);

Then cycle through the list on each Map click to see whether the current Ploygon already has a Marker. If it does not have a Marker already, then remove any Marker already placed in a different Polygon, and create one in the current Polygon:

 mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

        @Override
        public void onMapClick(LatLng point) {

            for (PolyMarkerObject pmObj : polyMarkerList) {
                //only add Marker if there is not one already inside the Polygon
                if (PolyUtil.containsLocation(point, pmObj.polygon.getPoints(), false)) {
                    if (pmObj.marker == null) {

                        //Add Marker to current Polygon
                        Marker newMarker = mMap.addMarker(new MarkerOptions()
                                .position(point)
                                .title("test")
                                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));

                        pmObj.marker = newMarker;
                        Log.v("Marker", "ADDing Marker");
                        break;
                    }

                }
            }
        }
    });

Multiple Polygons, One Marker Solution:

In this case, you just need one Marker reference, and a list of Polygons:

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    Marker marker;
    List<Polygon> polyList = new ArrayList<>();
    //................

Add the Polygon to the list when it's added to the Map:

    List<LatLng> newPolygon = new ArrayList<>();
    //set up the points in the Polygon.......

    Polygon p = mMap.addPolygon(new PolygonOptions()
            .addAll(newPolygon)
            .strokeColor(Color.RED)
            .fillColor(Color.BLUE));

    polyList.add(p);

Then, in the Map click listener, you have two cases, one for if the Marker reference is null (no Marker added yet), and one for if the Marker is in a different Polygon. If the Marker is in the current Polygon already, it will not be moved.

 mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

        @Override
        public void onMapClick(LatLng point) {

            for (Polygon pObj : polyList) {
                //find Polygon user tapped inside of
                if (PolyUtil.containsLocation(point, pObj.getPoints(), false)) {
                    //first case, no Marker
                    if (marker == null) {

                        //Add Marker to current Polygon
                        marker = mMap.addMarker(new MarkerOptions()
                                .position(point)
                                .title("test")
                                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));

                        Log.v("Marker", "ADDing first Marker");
                        break;
                    }
                    else if (!PolyUtil.containsLocation(marker.getPosition(), pObj.getPoints(), false)) {
                        //Marker exists already in a different Polygon
                        //remove Marker from previous Polygon
                        marker.remove();
                        //Add Marker to current Polygon
                        marker = mMap.addMarker(new MarkerOptions()
                                .position(point)
                                .title("test")
                                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));

                        Log.v("Marker", "Moving Marker to new Polygon");
                        break;
                    }

                }
            }
        }
    });
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • that works with one polygon but what if I have multiple ? – Dwill Jul 14 '15 at 17:52
  • where is polygonList defined? – Dwill Jul 14 '15 at 18:47
  • Thanks man! One more thing. I had code to remove the previous marker. Do I need to wrap that in an if statement to look markers that are not null? – Dwill Jul 14 '15 at 19:09
  • yes, when I click on a new polygon it should remove the marker from the previous one. – Dwill Jul 14 '15 at 19:17
  • @Dwill Ok, I see. You will need an inner loop then, in order to remove the previous Marker. I just updated the answer! – Daniel Nugent Jul 14 '15 at 19:20
  • @Dwill I just realized that if you only want one Marker on the entire Map at any given time, there is no need for a POJO. You can just keep a list of Polygons, and one Marker reference. – Daniel Nugent Jul 14 '15 at 19:26
  • @Dwill Ok, just updated the answer with a solution for Multiple Polygons and one Marker, which is what you're going for! Basically you need an extra case to make sure that if the Marker is not null, that it is in a different Polygon. If it's in a different Polygon, remove it and place it in the current one. If it's not null and already exists in the current Polygon, do nothing. – Daniel Nugent Jul 14 '15 at 19:48