how to draw polygon using string array of latlng in google map

那年仲夏 提交于 2020-05-13 15:26:18

问题


In my app, i have recyclerview which contain imagview and this imageview contain static map image by using coordinates which i store in sqlite. and when i click on that image i am passing that coordinates in string array format to other map activity and then using this string array coordinates again draw the same polygon which static map hold into google map. but i don't understand how to do this.

I tried following code but not working:

this is code of my adapter class where i display static map on image view and then using intent pass the coordinates to map activity

   String url ="https://maps.googleapis.com/maps/api/staticmap?";
    url+="&zoom=18";
    url+="&size=300x300";
    url+="&maptype=satellite";
    url+="&path=color:green|fillcolor:0xFFFF0033|"+ Coordinates;
    url+="&key=" + "AIzaSyCj80x6E****Lx_KFsHKlogV0";
    Picasso.get().load(url).into(holder.poly_image);

    holder.poly_image.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {


            Intent i = new Intent(mCtx, EditMapsActivity.class);
            i.putExtra("img", Poly_Coords);
            mCtx.startActivity(i);
        }
    });

this is my map activity where i want to draw polygon using coordinates:

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

    // Obtain the SupportMapFragment and get notified when the map is ready 
   to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) 
    getSupportFragmentManager().findFragmentById(R.id.mapView);
    mapFragment.getMapAsync(EditMapsActivity.this);
    Intent intent = getIntent();
    String staticPolyCoords = intent.getStringExtra("img");
    Log.d("Log", "Polygon Coords" + staticPolyCoords);

    String answer = staticPolyCoords;
    ArrayList<Location> arrayListLatLng = new ArrayList<>();
    answer = answer.replace("lat/lng: (" , "");
    answer = answer.replace(")" , "");
    answer = answer.replace("]","");
    answer = answer.replace("[","");
    String[] arrayLatLng = answer.split(",");
    Log.d("LOG_TAG", "Polygon Coordinates" +  arrayLatLng);

    for(int i = 0 ; i < arrayLatLng.length ; i++ ){

       LatLng Cooordinate_Point = new 
       LatLng((Double.parseDouble(arrayLatLng[i])), 
       Double.parseDouble(arrayLatLng[i+1]));
        Log.d("LOG_TAG", "Polygon Coordinates" +  Cooordinate_Point);
        latLngList.add(Cooordinate_Point);
    }

then in map ready method()

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

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        DrawPolygon(latLngList);

    }


  private void DrawPolygon(List<LatLng> latLngList) {

  /*  myMap.addPolygon(new PolygonOptions().strokeColor(Color.GREEN).fillColor(0x7F228B22).add(latLngList));*/

    Polygon polygon = myMap.addPolygon(new PolygonOptions()
            .clickable(true)
            .add(latLngList));
    // Store a data object with the polygon, used here to indicate an arbitrary type.
    polygon.setTag("alpha");
    polygon.setStrokeWidth(3);
    polygon.setStrokeColor(Color.GREEN);
    polygon.setFillColor(0x7F228B22);

}

回答1:


Use this code for conversion:

    String answer = staticPolyCoords;
    answer = answer.replace("lat/lng:" , "");
    answer = answer.replace(")" , "]");
    answer = answer.replace("(" , "[");

    try {
        JSONArray jsonArray = new JSONArray(answer);
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONArray latLong = jsonArray.getJSONArray(i);
            double lat = latLong.getDouble(0);
            double lon = latLong.getDouble(1);
            coordinates.add(new LatLng(lat, lon));
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }

And then in your drawPolygon method try this for each loop :

 PolygonOptions poly = new PolygonOptions();
    for (LatLng latLng : coordinates) {
        //use the coordinates.
        poly.addAll(Collections.singleton(latLng));
    }


    Polygon polygon = myMap.addPolygon(poly);
   //add here your set methods

    myMap.moveCamera(CameraUpdateFactory.newLatLng(coordinates.get(3)));
    CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
    myMap.animateCamera(zoom);
 }



回答2:


If you want to load your map in google map's application then you can go with the below approch:

String geoUri = "http://maps.google.com/maps?q=loc:" + latitude + "," + longitude + " (" + mTitle + ")";
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(geoUri));
context.startActivity(intent);

Or If you want to load it inside your app try with MapActivity where you need to first enable google map API and then your applied coordinates will be displayed on the map

Please check below link this will be useful to integrate this

https://developers.google.com/maps/documentation/android-sdk/start




回答3:


Call this from your button click listener:

Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://www.google.com/maps/@?api=1&map_action=map&center=" + Coordinates));
mCtx.startActivity(i);

Source: Maps URLs




回答4:


If I understand your question correctly, you need to: first show a static map, then, after clicking, show the same static map, but with several polygons on it. As in the case of the quiz, when the first (question) Activity of the user is asked for the right place of an object, and the second (answer) Activity displays the correct place of the object.

For this you need:

1) bind the image of static map to geodetic coordinates;

2) implement GoogleMap.addPolygon() method for draw polygone on it.

Both of that task is not trivial in general, so easiest ways is:

1) If you want quick right answer shown in second activity, request and get from Static Map API in yours first Activity two maps: first - just with map image, and second - same map, but already with polygons. First image you show in that activity, and to second Activity (which you show after click) you show second image already with polygons. Or request second image in second Activity if you want to show answer only for clicked maps. In Official Documentation you can find how to get static map image with polygone on it (take a look at the path parameter):

https://maps.googleapis.com/maps/api/staticmap ?size=400x400&center=40.653279,-73.959816&zoom=11 &path=fillcolor:0xAA000033%7Ccolor:0xFFFFFF00%7Cenc:}zswFtikbMjJzZ%7CRdPfZ}DxWvBjWpF~IvJnEvBrMvIvUpGtQpFhOQdKpz@bIx{A%7CPfYlvApz@bl@tcAdTpGpVwQtX}i@%7CGen@lCeAda@bjA%60q@v}@rfAbjA%7CEwBpbAd_@he@hDbu@uIzWcWtZoTdImTdIwu@tDaOXw_@fc@st@~VgQ%7C[uPzNtA%60LlEvHiYyLs^nPhCpG}SzCNwHpz@cEvXg@bWdG%60]lL~MdTmEnCwJ[iJhOae@nCm[%60Aq]qE_pAaNiyBuDurAuB}}Ay%60@%7CEKv_@?%7C[qGji@lAhYyH%60@Xiw@tBerAs@q]jHohAYkSmW?aNoaAbR}LnPqNtMtIbRyRuDef@eT_z@mW_Nm%7CB~j@zC~hAyUyJ_U{Z??cPvg@}s@sHsc@_z@cj@kp@YePoNyYyb@_iAyb@gBw^bOokArcA}GwJuzBre@i\tf@sZnd@oElb@hStW{]vv@??kz@~vAcj@zKa%60Atf@uQj_Aee@pU_UrcA &key=YOUR_API_KEY

Now maps Static API URLs are restricted to 8192 characters in size. So if your polygon has a lot of points you should use encoded polyline format for polygon points. You can encode your polygon with PolyUtil.encode() method of Maps SDK for Android Utility Library.

2) (IMHO better) use MapView/MapFragment Lite Mode of Maps SDK for Android that can serve a bitmap image of a map, offering limited interactivity to the user. Polylines are supported in this mode and you can save some traffic. In that case you should place MapView' or 'MapFragment in first activity and MapView/MapFragment with same settings (size, camera position etc.) in second activity and when user click on map of first activity just draw polygon of the map of the second and show it. The lite mode functionality for shapes matches the full API:

GoogleMap map;
// ... get a map.
// Add a triangle in the Gulf of Guinea
Polygon polygon = map.addPolygon(new PolygonOptions()
     .add(new LatLng(0, 0), new LatLng(0, 5), new LatLng(3, 5), new LatLng(0, 0))
     .strokeColor(Color.RED)
 .fillColor(Color.BLUE));



回答5:


To draw polygons rectangle correctly try this sort function:

fun sortConvexs(coordinates: MutableList<LatLng>): MutableList<LatLng> {

        val input = coordinates

        // Returns a positive value, if OAB makes a counter clockwise turn,negative for clockwise turn, and zero if the points are collinear.

        fun cross(P: LatLng, _A: LatLng, _B: LatLng): Double {
            val part1 = (_A.longitude - P.longitude) * (_B.latitude - P.latitude)
            val part2 = (_A.latitude - P.latitude) * (_B.longitude - P.longitude)
            return part1 - part2
        }

        // Sort points

        var points = input.sortedWith(
            Comparator<LatLng> { coordinate0, coordinate1 ->
                when {
                    (coordinate0.longitude == coordinate1.longitude) && (coordinate0.latitude < coordinate1.latitude) -> 1
                    (coordinate0.longitude < coordinate1.longitude) -> -1
                    else -> 0
                }
            }
        )

        // Build the lower hull

        var lower: MutableList<LatLng> = ArrayList<LatLng>()

        points.forEach { p ->

            while (lower.size >= 2 && cross(lower[lower.size - 2], lower[lower.size - 1], p) <= 0) {
                lower.removeAt(lower.size - 1)
            }

            lower.add(p)

        }

        // Build upper hull

        var upper: MutableList<LatLng> = ArrayList<LatLng>()

        points = points.asReversed()

        points.forEach { p ->
            while (upper.size >= 2 && cross(upper[upper.size - 2], upper[upper.size - 1], p) <= 0) {
                upper.removeAt(upper.size - 1)
            }

            upper.add(p)
        }

        // Last point of upper list is omitted because it is repeated at the beginning of the lower list.

        upper.removeAt(upper.size - 1)


        // Concatenation of the lower and upper hulls gives the total points.

        return (upper + lower).toMutableList()
    }


    fun getApproximateCenter(points: MutableList<LatLng>): LatLng {
        // Calc bounds first
        val boundsBuilder = LatLngBounds.builder()
        points.forEach {
            boundsBuilder.include(it)
        }
        val polygonBounds = boundsBuilder.build()

        val centerPoint = polygonBounds.center

        // Center point is inside the polygon, return it
        if (PolyUtil.containsLocation(centerPoint, points, true)) {
            return centerPoint
        }

        // Center point is out of bounds
        // Sample points at fixed percentages of the bounding box’s width East and West of the center point.
        val maxSearchSteps = 10
        var testPos: LatLng = centerPoint

        // Calculate NorthWest point so we can work out height of polygon NW->SE
        val northWest = LatLng(polygonBounds.northeast.latitude, polygonBounds.southwest.longitude)

        // Work out how tall and wide the bounds are and what our search
        // increment will be
        val boundsHeight = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.southwest)
        val heightIncr = boundsHeight / maxSearchSteps

        val boundsWidth = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.northeast)
        val widthIncr = boundsWidth / maxSearchSteps

        // Expand out from Centroid and find a point within polygon at
        // 0, 90, 180, 270 degrees
        for (n in 1..maxSearchSteps) {
            // Test point North of Centroid
            testPos = SphericalUtil.computeOffset(
                centerPoint,
                (heightIncr * n),
                0.0
            )
            if (PolyUtil.containsLocation(testPos, points, true)) {
                break
            }

            // Test point East of Centroid
            testPos = SphericalUtil.computeOffset(
                centerPoint,
                (widthIncr * n),
                90.0
            )
            if (PolyUtil.containsLocation(testPos, points, true)) {
                break
            }

            // Test point South of Centroid
            testPos = SphericalUtil.computeOffset(
                centerPoint,
                (heightIncr * n),
                180.0
            )
            if (PolyUtil.containsLocation(testPos, points, true)) {
                break
            }

            // Test point West of Centroid
            testPos = SphericalUtil.computeOffset(
                centerPoint,
                (widthIncr * n),
                270.0
            )
            if (PolyUtil.containsLocation(testPos, points, true)) {
                break
            }
        }

        return testPos
    }

This works for me, based in this swift answer



来源:https://stackoverflow.com/questions/61206574/how-to-draw-polygon-using-string-array-of-latlng-in-google-map

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!