6

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

Soldeplata Saketos
  • 3,212
  • 1
  • 25
  • 38

2 Answers2

10

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

Soldeplata Saketos
  • 3,212
  • 1
  • 25
  • 38
1

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

  • This worked great for me, thanks! One thing I struggled with: the *order* of coordinates is very important. The order of inner cutouts must be opposite direction of the outer boundary coordinates. I had to reverse one set of boundaries to get my own install working. After that, it's great! – aaronbauman Jun 07 '21 at 13:37