Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a Polygon with a hole inside in Google Static Maps API?

When I try to create an outer polygon with a hole inside with Static Maps API, the fill color fills the inner polygon, and I see no parameters to draw this. This is how it looks: Fail of polygon with hole

this is the request: https://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&zoom=16&path=color:0xFF0000AA|weight:3|fillcolor:0xFFB6C1BB|enc:csr{FcgiLuSm[rYua@zIvHvCdNcAzKmRhX&path=color:0xFF0000AA|weight:3|enc:mjr{FsjjL{A}D}E|DxAvD~EwD

like image 227
Soldeplata Saketos Avatar asked Nov 01 '16 14:11

Soldeplata Saketos


2 Answers

As this is currently a feature that is not possible with Static Maps API, I've come with a workaround that achieves the "hole effect":

1) Define the outer and inner lines of the polygon without any 'fillcolor', like this example: https://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&zoom=16&path=color:0xFF0000AA|weight:3|enc:csr{FcgiLuSm[rYua@zIvHvCdNcAzKmRhX&path=color:0xFF0000AA|weight:3|enc:mjr{FsjjL{A}D}E|DxAvD~EwD enter image description here

2) Create a polygon that removes a portion of the outer polygon and of the inner polygon, creating like a packman. Set the weight to zero 'weight=0' and choose a color to fill, like in this example: https://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&zoom=16&&path=color:0x0ea001AA|weight:0|fillcolor:0xFFB6C1BB|enc:csr{FcgiLuSm[rYua@zIvHvCdNcAzKwIeI{A}D}E|DxAvDu@v\ Big portion of filling 3) Analogously to step 2, create the portion that we lack of the filled polygon, like in this example: https://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&zoom=16&path=color:0x0ea001AA|weight:0|fillcolor:0xFFB6C1BB|enc:csr{FcgiLlRiXwIeI_FvDu@v\ Last portion of filling 4) Finally stitch all the paths together to simulate the desired hole: https://maps.googleapis.com/maps/api/staticmap?size=640x640&maptype=roadmap&zoom=16&path=color:0xFF0000AA|weight:3|enc:csr{FcgiLuSm[rYua@zIvHvCdNcAzKmRhX&path=color:0xFF0000AA|weight:3|enc:mjr{FsjjL{A}D}E|DxAvD~EwD&path=color:0x0ea001AA|weight:0|fillcolor:0xFFB6C1BB|enc:csr{FcgiLuSm[rYua@zIvHvCdNcAzKwIeI{A}D}E|DxAvDu@v%5C&path=color:0x0ea001AA|weight:0|fillcolor:0xFFB6C1BB|enc:csr{FcgiLlRiXwIeI_FvDu@v%5C Polygon with hole effect

There is a Polyline encoder-decoder utility that can help you to see all the process at https://developers.google.com/maps/documentation/utilities/polylineutility

like image 71
Soldeplata Saketos Avatar answered Sep 17 '22 23:09

Soldeplata Saketos


To build on the answer from Soldeplata Saketos, for the fill part it is possible to use a single path for the contour + the holes, without the need to split it. It seems the Maps Static API uses some kind of stencil test where if an area is drawn a pair (0, 2...) number of times, it is actually not filled and when drawn an impair (1 or more) number of times, its gets filled with the fillcolor.

Based on this principle, here is some Python code based on the Shapely library (but hopefully portable to other languages or libraries):

fill_coords = list(poly.exterior.coords)
outline_coords = [poly.exterior.coords]
for hole in poly.interiors:
  fill_coords.extend(hole.coords)
  # always close by adding the first point on the exterior
  fill_coords.append(fill_coords[0])
  outline_coords.append(hole.coords)

Note that the exterior and all holes/interiors must be defined as rings i.e. a closed sequence of points.

Then, like Soldeplata Saketos suggests, draw the fill and the outline separately:

  • one path= for the fill (fill_coords), with a fillcolor and weight=0
  • a separate path= for each of the members of outline_coords, with no fillcolor. This will draw the border of the polygon

Here is a result image:

polygon with 2 holes

(the scalebar is added by additional code but the image above it is the one coming from the Maps Static API)

Here is the query (replace the API_KEY parameter with your own):

https://maps.googleapis.com/maps/api/staticmap?maptype=hybrid&key=_API_KEY_&size=640x593&scale=2&center=50.95141146936693,2.0425128936767543&zoom=16&path=fillcolor%3A0x0000ff66%7Cweight%3A0%7Cenc%3Ao%7D%7DuHqenKaZ~X_AcEqAiJvEuE_%40%7DArFgFdC%60Kd%40a%40%60A%7B%40zAqCtAmAjBHz%40zDiYzLz%40%7C%40hAaEyBaCw%40vCj%40lBhY%7BLkECx%40%7CAb%40u%40MsBuAGDrAjEB&path=color%3A0x0000ffff%7Cweight%3A2%7Cenc%3Ao%7D%7DuHqenKaZ~X_AcEqAiJvEuE_%40%7DArFgFdC%60Kd%40a%40%60A%7B%40zAqCtAmAjBHz%40zD&path=color%3A0x0000ffff%7Cweight%3A2%7Cenc%3Ayw~uHuwmKz%40%7C%40hAaEyBaCw%40vCj%40lB&path=color%3A0x0000ffff%7Cweight%3A2%7Cenc%3A%7Bc~uHuenKx%40%7CAb%40u%40MsBuAGDrA

like image 37
asdfghjk420 Avatar answered Sep 19 '22 23:09

asdfghjk420