1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
#
# Copyright 2020 Google Inc. All rights reserved.
#
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
"""Performs requests to the Google Maps Static API."""
from googlemaps import convert
MAPS_IMAGE_FORMATS = {'png8', 'png', 'png32', 'gif', 'jpg', 'jpg-baseline'}
MAPS_MAP_TYPES = {'roadmap', 'satellite', 'terrain', 'hybrid'}
class StaticMapParam:
"""Base class to handle parameters for Maps Static API."""
def __init__(self):
self.params = []
def __str__(self):
"""Converts a list of parameters to the format expected by
the Google Maps server.
:rtype: str
"""
return convert.join_list('|', self.params)
class StaticMapMarker(StaticMapParam):
"""Handles marker parameters for Maps Static API."""
def __init__(self, locations,
size=None, color=None, label=None):
"""
:param locations: Specifies the locations of the markers on
the map.
:type locations: list
:param size: Specifies the size of the marker.
:type size: str
:param color: Specifies a color of the marker.
:type color: str
:param label: Specifies a single uppercase alphanumeric
character to be displaied on marker.
:type label: str
"""
super(StaticMapMarker, self).__init__()
if size:
self.params.append("size:%s" % size)
if color:
self.params.append("color:%s" % color)
if label:
if len(label) != 1 or (label.isalpha() and not label.isupper()) or not label.isalnum():
raise ValueError("Marker label must be alphanumeric and uppercase.")
self.params.append("label:%s" % label)
self.params.append(convert.location_list(locations))
class StaticMapPath(StaticMapParam):
"""Handles path parameters for Maps Static API."""
def __init__(self, points,
weight=None, color=None,
fillcolor=None, geodesic=None):
"""
:param points: Specifies the point through which the path
will be built.
:type points: list
:param weight: Specifies the thickness of the path in pixels.
:type weight: int
:param color: Specifies a color of the path.
:type color: str
:param fillcolor: Indicates both that the path marks off a
polygonal area and specifies the fill color to use as an
overlay within that area.
:type fillcolor: str
:param geodesic: Indicates that the requested path should be
interpreted as a geodesic line that follows the curvature
of the earth.
:type geodesic: bool
"""
super(StaticMapPath, self).__init__()
if weight:
self.params.append("weight:%s" % weight)
if color:
self.params.append("color:%s" % color)
if fillcolor:
self.params.append("fillcolor:%s" % fillcolor)
if geodesic:
self.params.append("geodesic:%s" % geodesic)
self.params.append(convert.location_list(points))
def static_map(client, size,
center=None, zoom=None, scale=None,
format=None, maptype=None, language=None, region=None,
markers=None, path=None, visible=None, style=None):
"""
Downloads a map image from the Maps Static API.
See https://developers.google.com/maps/documentation/maps-static/intro
for more info, including more detail for each parameter below.
:param size: Defines the rectangular dimensions of the map image.
:type param: int or list
:param center: Defines the center of the map, equidistant from all edges
of the map.
:type center: dict or list or string
:param zoom: Defines the zoom level of the map, which determines the
magnification level of the map.
:type zoom: int
:param scale: Affects the number of pixels that are returned.
:type scale: int
:param format: Defines the format of the resulting image.
:type format: string
:param maptype: defines the type of map to construct. There are several
possible maptype values, including roadmap, satellite, hybrid,
and terrain.
:type maptype: string
:param language: defines the language to use for display of labels on
map tiles.
:type language: string
:param region: defines the appropriate borders to display, based on
geo-political sensitivities.
:type region: string
:param markers: define one or more markers to attach to the image at
specified locations.
:type markers: StaticMapMarker
:param path: defines a single path of two or more connected points to
overlay on the image at specified locations.
:type path: StaticMapPath
:param visible: specifies one or more locations that should remain visible
on the map, though no markers or other indicators will be displayed.
:type visible: list of dict
:param style: defines a custom style to alter the presentation of
a specific feature (roads, parks, and other features) of the map.
:type style: list of dict
:rtype: iterator containing the raw image data, which typically can be
used to save an image file locally. For example:
```
f = open(local_filename, 'wb')
for chunk in client.static_map(size=(400, 400),
center=(52.520103, 13.404871),
zoom=15):
if chunk:
f.write(chunk)
f.close()
```
"""
params = {"size": convert.size(size)}
if not markers:
if not (center or zoom is not None):
raise ValueError(
"both center and zoom are required"
"when markers is not specifed"
)
if center:
params["center"] = convert.latlng(center)
if zoom is not None:
params["zoom"] = zoom
if scale is not None:
params["scale"] = scale
if format:
if format not in MAPS_IMAGE_FORMATS:
raise ValueError("Invalid image format")
params['format'] = format
if maptype:
if maptype not in MAPS_MAP_TYPES:
raise ValueError("Invalid maptype")
params["maptype"] = maptype
if language:
params["language"] = language
if region:
params["region"] = region
if markers:
params["markers"] = markers
if path:
params["path"] = path
if visible:
params["visible"] = convert.location_list(visible)
if style:
params["style"] = convert.components(style)
response = client._request(
"/maps/api/staticmap",
params,
extract_body=lambda response: response,
requests_kwargs={"stream": True},
)
return response.iter_content()
|