simplestmaps 1.3.0__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {simplestmaps-1.3.0/simplestmaps.egg-info → simplestmaps-1.5.0}/PKG-INFO +2 -2
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/README.md +1 -1
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/setup.py +1 -1
- {simplestmaps-1.3.0 → simplestmaps-1.5.0/simplestmaps.egg-info}/PKG-INFO +2 -2
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/simplestmaps.py +180 -99
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/LICENSE +0 -0
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/setup.cfg +0 -0
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/simplestmaps.egg-info/SOURCES.txt +0 -0
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/simplestmaps.egg-info/dependency_links.txt +0 -0
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/simplestmaps.egg-info/requires.txt +0 -0
- {simplestmaps-1.3.0 → simplestmaps-1.5.0}/simplestmaps.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simplestmaps
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Super simple on-liner maps in python.
|
|
5
5
|
Home-page: http://github.com/fisadev/simplestmaps
|
|
6
6
|
Author: Juan Pedro Fisanotti
|
|
@@ -49,7 +49,7 @@ Description: # Simplest Maps
|
|
|
49
49
|
|
|
50
50
|
Here are a good set of examples that showcase (and document) all of the supported features:
|
|
51
51
|
|
|
52
|
-
[Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/
|
|
52
|
+
## [Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/59c84384463eb31eb827e2ec42cb40f2f502ff58/demo_and_docs.ipynb)
|
|
53
53
|
|
|
54
54
|
Platform: UNKNOWN
|
|
55
55
|
Classifier: Intended Audience :: Developers
|
|
@@ -41,4 +41,4 @@ And every element plotted into the map is also customizable (colors, fonts, size
|
|
|
41
41
|
|
|
42
42
|
Here are a good set of examples that showcase (and document) all of the supported features:
|
|
43
43
|
|
|
44
|
-
[Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/
|
|
44
|
+
## [Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/59c84384463eb31eb827e2ec42cb40f2f502ff58/demo_and_docs.ipynb)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: simplestmaps
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Super simple on-liner maps in python.
|
|
5
5
|
Home-page: http://github.com/fisadev/simplestmaps
|
|
6
6
|
Author: Juan Pedro Fisanotti
|
|
@@ -49,7 +49,7 @@ Description: # Simplest Maps
|
|
|
49
49
|
|
|
50
50
|
Here are a good set of examples that showcase (and document) all of the supported features:
|
|
51
51
|
|
|
52
|
-
[Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/
|
|
52
|
+
## [Take a look at everything that's possible with so little code!](https://nbviewer.org/github/fisadev/simplestmaps/blob/59c84384463eb31eb827e2ec42cb40f2f502ff58/demo_and_docs.ipynb)
|
|
53
53
|
|
|
54
54
|
Platform: UNKNOWN
|
|
55
55
|
Classifier: Intended Audience :: Developers
|
|
@@ -7,55 +7,66 @@ import json
|
|
|
7
7
|
import folium
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Point = namedtuple("Point", "lat lon")
|
|
11
11
|
|
|
12
12
|
# type -> converter function that receives instance of type and returns either a single (lat,lon)
|
|
13
13
|
# tuple, or a sequence of (lat,lon) tuples
|
|
14
|
-
|
|
14
|
+
converters = {}
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def
|
|
17
|
+
def all_numbers(sequence):
|
|
18
18
|
"""
|
|
19
|
-
|
|
19
|
+
Is a sequence composed of just numbers?
|
|
20
20
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
return all(
|
|
22
|
+
isinstance(x, (int, float)) and not isinstance(x, bool)
|
|
23
|
+
for x in sequence
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def to_points(source):
|
|
28
|
+
"""
|
|
29
|
+
Convert any possible thing to lat lon points and/or sequences of points.
|
|
30
|
+
"""
|
|
31
|
+
while source.__class__ in converters:
|
|
32
|
+
# a custom type for which we have a converter registered, use it before trying to extract
|
|
33
|
+
# points from it
|
|
34
|
+
source = converters[source.__class__](source)
|
|
35
|
+
|
|
36
|
+
if isinstance(source, GeneratorType):
|
|
37
|
+
# traverse the generator and build a tuple with its components, that we can inspect and
|
|
38
|
+
# parse (so we can do things like decide how to parse it based on its length and the types
|
|
39
|
+
# of its items)
|
|
40
|
+
return to_points(tuple(source))
|
|
41
|
+
elif hasattr(source, "lat") and hasattr(source, "lon"):
|
|
26
42
|
# a few known classes that have lat long attributes
|
|
27
|
-
lat, lon =
|
|
28
|
-
elif hasattr(
|
|
43
|
+
lat, lon = source.lat, source.lon
|
|
44
|
+
elif hasattr(source, "latitude") and hasattr(source, "longitude"):
|
|
29
45
|
# a few known classes that have latitude longitude attributes, like some common geo
|
|
30
46
|
# libs
|
|
31
|
-
lat, lon =
|
|
32
|
-
elif hasattr(
|
|
47
|
+
lat, lon = source.latitude, source.longitude
|
|
48
|
+
elif hasattr(source, "latitude_deg") and hasattr(source, "longitude_deg"):
|
|
33
49
|
# a few known classes that have latitude_deg longitude_deg attributes, like the
|
|
34
50
|
# locations from the orbit-predictor lib
|
|
35
|
-
lat, lon =
|
|
36
|
-
elif isinstance(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
lat, lon = source.latitude_deg, source.longitude_deg
|
|
52
|
+
elif isinstance(source, (tuple, list)):
|
|
53
|
+
if len(source) == 1:
|
|
54
|
+
# a sequence with a single object inside, so extract a point from it as if we just got
|
|
55
|
+
# that object alone
|
|
56
|
+
return to_points(source[0])
|
|
57
|
+
elif len(source) in (2, 3) and all_numbers(source):
|
|
58
|
+
# a sequence of 2 or 3 numbers, these must be coordinates, finally!
|
|
59
|
+
lat, lon = source[:2]
|
|
60
|
+
else:
|
|
61
|
+
# a sequence that doesn't look like coordinates but maybe a collection of points, try
|
|
62
|
+
# to extract all of them into a list
|
|
63
|
+
return [to_points(item) for item in source]
|
|
40
64
|
else:
|
|
41
65
|
raise ValueError(
|
|
42
|
-
f"Can't guess the latitude and longitude from this object: {repr(
|
|
66
|
+
f"Can't guess the latitude and longitude from this object: {repr(source)}"
|
|
43
67
|
)
|
|
44
68
|
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def extract_coords_sequence(coords_sequence):
|
|
49
|
-
"""
|
|
50
|
-
Extract a sequence of lat lon coordinates from any possible known thing.
|
|
51
|
-
"""
|
|
52
|
-
if coords_sequence.__class__ in coords_converters:
|
|
53
|
-
# a custom type from which we need to extract the coordinates sequence
|
|
54
|
-
converter = coords_converters[coords_sequence.__class__]
|
|
55
|
-
coords_sequence = converter(coords_sequence)
|
|
56
|
-
|
|
57
|
-
# a sequence from which we need to extract each coordinate
|
|
58
|
-
return [extract_coords(coords) for coords in coords_sequence]
|
|
69
|
+
return Point(lat, lon)
|
|
59
70
|
|
|
60
71
|
|
|
61
72
|
def auto_convert(custom_type, converter_function):
|
|
@@ -63,34 +74,106 @@ def auto_convert(custom_type, converter_function):
|
|
|
63
74
|
Register a custom type to be automatically converted to single coordinates or sequences of
|
|
64
75
|
coordinates, to be able to use them in the helper functions for map elements.
|
|
65
76
|
"""
|
|
66
|
-
|
|
77
|
+
converters[custom_type] = converter_function
|
|
67
78
|
|
|
68
79
|
|
|
69
80
|
# types of things we can display on a map, with their attributes
|
|
70
|
-
Marker = namedtuple("Marker", "
|
|
71
|
-
Dot = namedtuple("Dot", "
|
|
72
|
-
Label = namedtuple("Label", "
|
|
73
|
-
Html = namedtuple("Html", "
|
|
74
|
-
Line = namedtuple("Line", "
|
|
75
|
-
Area = namedtuple("Area", "
|
|
81
|
+
Marker = namedtuple("Marker", "point popup")
|
|
82
|
+
Dot = namedtuple("Dot", "point color radius opacity border_color border_width popup")
|
|
83
|
+
Label = namedtuple("Label", "point text color size font opacity popup")
|
|
84
|
+
Html = namedtuple("Html", "point code popup")
|
|
85
|
+
Line = namedtuple("Line", "points_sequence color width opacity popup")
|
|
86
|
+
Area = namedtuple("Area", "points_sequence color opacity border_color border_width popup")
|
|
76
87
|
Geojson = namedtuple("Geojson", "path points_as lines_as areas_as")
|
|
77
88
|
|
|
78
89
|
|
|
79
|
-
def
|
|
90
|
+
def extract_single_points(points_source):
|
|
91
|
+
"""
|
|
92
|
+
Extract and iterate over single points that might be part of point sequences, or even trees of
|
|
93
|
+
points.
|
|
94
|
+
|
|
95
|
+
This function assumes that points_source can contain only two types of things: Point instances,
|
|
96
|
+
or sequences (lists/tuples/generators) containing any of both.
|
|
97
|
+
|
|
98
|
+
Something like [[point_a], [point_b, point_c, point_d], [[[point_e]], point_f]]
|
|
99
|
+
Will yield all of the Point instances, one by one, in order.
|
|
100
|
+
"""
|
|
101
|
+
pending = [points_source]
|
|
102
|
+
while pending:
|
|
103
|
+
current = pending.pop(0)
|
|
104
|
+
|
|
105
|
+
if isinstance(current, Point):
|
|
106
|
+
yield current
|
|
107
|
+
elif isinstance(current, (list, tuple, GeneratorType)):
|
|
108
|
+
pending.extend(current)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def extract_points_sequences(points_source):
|
|
112
|
+
"""
|
|
113
|
+
Extract and iterate over point sequences that might be themselves part of higher order
|
|
114
|
+
sequences, or even trees of sequences.
|
|
115
|
+
|
|
116
|
+
This function assumes that points_source can contain only two types of things: Point instances,
|
|
117
|
+
or sequences (lists/tuples/generators) containing any of both.
|
|
118
|
+
|
|
119
|
+
The only condition is that any sequence (list/tuple/generator) contains either all Point
|
|
120
|
+
instances, or all sequences. No mixing of the two element types inside the same sequence.
|
|
121
|
+
|
|
122
|
+
Something like [[point_a], [point_b, point_c, point_d], [[[point_e]]]]
|
|
123
|
+
Will yield three sequences:
|
|
124
|
+
[point_a]
|
|
125
|
+
[point_b, point_c, point_d]
|
|
126
|
+
[point_e]
|
|
127
|
+
|
|
128
|
+
While something like [point_a, [point_b, point_c]]
|
|
129
|
+
Will yield an error, as there's a sequence (the top level one) mixing types inside it.
|
|
130
|
+
"""
|
|
131
|
+
pending = [points_source]
|
|
132
|
+
while pending:
|
|
133
|
+
current = pending.pop(0)
|
|
134
|
+
|
|
135
|
+
if isinstance(current, Point):
|
|
136
|
+
# we received a single point, not even in a sequence, just yield it as a sequence of
|
|
137
|
+
# one element
|
|
138
|
+
yield [current]
|
|
139
|
+
elif isinstance(current, (list, tuple, GeneratorType)):
|
|
140
|
+
# we have a sequence, but is it a sequence of points? or a sequence of other sequences?
|
|
141
|
+
if all(isinstance(item, Point) for item in current):
|
|
142
|
+
# current is a sequence of coords!
|
|
143
|
+
yield current
|
|
144
|
+
elif any(isinstance(item, Point) for item in current):
|
|
145
|
+
raise ValueError(
|
|
146
|
+
f"There's a sequence mixing points and other kinds of objects: {repr(current)}"
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
# a sequence of sequences, or a sequence of broken things. Add each item to the
|
|
150
|
+
# pending queue and deal with them when popped
|
|
151
|
+
pending.extend(current)
|
|
152
|
+
else:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"Can't guess a sequence of coordinates from this object: {repr(current)}"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def marker(*points_sources, popup=None):
|
|
80
159
|
"""
|
|
81
160
|
Helper to easily build a Marker instance.
|
|
82
161
|
"""
|
|
83
|
-
if not
|
|
162
|
+
if not points_sources:
|
|
84
163
|
return partial(marker, popup=popup)
|
|
85
164
|
|
|
86
|
-
return
|
|
165
|
+
return [
|
|
166
|
+
Marker(point, popup)
|
|
167
|
+
for point in extract_single_points(to_points(points_sources))
|
|
168
|
+
]
|
|
87
169
|
|
|
88
170
|
|
|
89
|
-
def dot(*
|
|
171
|
+
def dot(*points_sources, color="blue", radius=3, opacity=1, border_color=None, border_width=0,
|
|
172
|
+
popup=None):
|
|
90
173
|
"""
|
|
91
174
|
Helper to easily build a Dot instance.
|
|
92
175
|
"""
|
|
93
|
-
if not
|
|
176
|
+
if not points_sources:
|
|
94
177
|
return partial(dot, color=color, radius=radius, opacity=opacity, border_color=border_color,
|
|
95
178
|
border_width=border_width, popup=popup)
|
|
96
179
|
|
|
@@ -99,46 +182,58 @@ def dot(*coords, color="blue", radius=3, opacity=1, border_color=None, border_wi
|
|
|
99
182
|
elif border_width == 0:
|
|
100
183
|
border_width = 2
|
|
101
184
|
|
|
102
|
-
return
|
|
185
|
+
return [
|
|
186
|
+
Dot(point, color, radius, opacity, border_color, border_width, popup)
|
|
187
|
+
for point in extract_single_points(to_points(points_sources))
|
|
188
|
+
]
|
|
103
189
|
|
|
104
190
|
|
|
105
|
-
def label(*
|
|
191
|
+
def label(*points_sources, text, color="blue", size=12, font="arial", opacity=1, popup=None):
|
|
106
192
|
"""
|
|
107
193
|
Helper to easily build a Label instance.
|
|
108
194
|
"""
|
|
109
|
-
if not
|
|
195
|
+
if not points_sources:
|
|
110
196
|
return partial(label, text=text, color=color, size=size, font=font, opacity=opacity,
|
|
111
197
|
popup=popup)
|
|
112
198
|
|
|
113
|
-
return
|
|
199
|
+
return [
|
|
200
|
+
Label(point, text, color, size, font, opacity, popup)
|
|
201
|
+
for point in extract_single_points(to_points(points_sources))
|
|
202
|
+
]
|
|
114
203
|
|
|
115
204
|
|
|
116
|
-
def html(*
|
|
205
|
+
def html(*points_sources, code, popup=None):
|
|
117
206
|
"""
|
|
118
207
|
Helper to easily build a Html instance.
|
|
119
208
|
"""
|
|
120
|
-
if not
|
|
209
|
+
if not points_sources:
|
|
121
210
|
return partial(html, code=code, popup=popup)
|
|
122
211
|
|
|
123
|
-
return
|
|
212
|
+
return [
|
|
213
|
+
Html(point, code, popup)
|
|
214
|
+
for point in extract_single_points(to_points(points_sources))
|
|
215
|
+
]
|
|
124
216
|
|
|
125
217
|
|
|
126
|
-
def line(
|
|
218
|
+
def line(*points_sequences_sources, color="blue", width=2, opacity=1, popup=None):
|
|
127
219
|
"""
|
|
128
220
|
Helper to easily build a Line instance.
|
|
129
221
|
"""
|
|
130
|
-
if not
|
|
222
|
+
if not points_sequences_sources:
|
|
131
223
|
return partial(line, color=color, width=width, opacity=opacity, popup=popup)
|
|
132
224
|
|
|
133
|
-
return
|
|
225
|
+
return [
|
|
226
|
+
Line(points_sequence, color, width, opacity, popup)
|
|
227
|
+
for points_sequence in extract_points_sequences(to_points(points_sequences_sources))
|
|
228
|
+
]
|
|
134
229
|
|
|
135
230
|
|
|
136
|
-
def area(
|
|
231
|
+
def area(*points_sequences_sources, color="blue", opacity=0.5, border_color=None, border_width=0,
|
|
137
232
|
popup=None):
|
|
138
233
|
"""
|
|
139
234
|
Helper to easily build an Area instance.
|
|
140
235
|
"""
|
|
141
|
-
if not
|
|
236
|
+
if not points_sequences_sources:
|
|
142
237
|
return partial(area, color=color, opacity=opacity, border_color=border_color,
|
|
143
238
|
border_width=border_width, popup=popup)
|
|
144
239
|
|
|
@@ -147,8 +242,10 @@ def area(coords_sequence=None, color="blue", opacity=0.5, border_color=None, bor
|
|
|
147
242
|
elif border_width == 0:
|
|
148
243
|
border_width = 2
|
|
149
244
|
|
|
150
|
-
return
|
|
151
|
-
|
|
245
|
+
return [
|
|
246
|
+
Area(points_sequence, color, opacity, border_color, border_width, popup)
|
|
247
|
+
for points_sequence in extract_points_sequences(to_points(points_sequences_sources))
|
|
248
|
+
]
|
|
152
249
|
|
|
153
250
|
|
|
154
251
|
def geojson(path_or_data, points_as=marker, lines_as=line, areas_as=area):
|
|
@@ -204,35 +301,6 @@ def geojson(path_or_data, points_as=marker, lines_as=line, areas_as=area):
|
|
|
204
301
|
)
|
|
205
302
|
|
|
206
303
|
|
|
207
|
-
def pluralize(helper):
|
|
208
|
-
"""
|
|
209
|
-
Make a helper able to work with multiple sources instead of just one.
|
|
210
|
-
Example: use the 'label' helper to create a new 'labels' helper, that works with multiple
|
|
211
|
-
points coordinates instead of just one point.
|
|
212
|
-
"""
|
|
213
|
-
@wraps(helper)
|
|
214
|
-
def plural_helper(sources, **kwargs):
|
|
215
|
-
if sources.__class__ in coords_converters:
|
|
216
|
-
# a custom type from which we need to extract the coordinates sequence
|
|
217
|
-
converter = coords_converters[sources.__class__]
|
|
218
|
-
sources = converter(sources)
|
|
219
|
-
|
|
220
|
-
# a sequence from which we need to extract each coordinate
|
|
221
|
-
for source in sources:
|
|
222
|
-
yield helper(source, **kwargs)
|
|
223
|
-
|
|
224
|
-
return plural_helper
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
marker_set = pluralize(marker)
|
|
228
|
-
dot_set = pluralize(dot)
|
|
229
|
-
label_set = pluralize(label)
|
|
230
|
-
html_set = pluralize(html)
|
|
231
|
-
line_set = pluralize(line)
|
|
232
|
-
area_set = pluralize(area)
|
|
233
|
-
geojson_set = pluralize(geojson)
|
|
234
|
-
|
|
235
|
-
|
|
236
304
|
def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
237
305
|
"""
|
|
238
306
|
Draw a simple map with elements on it. Good known working tiles with folium 0.14:
|
|
@@ -242,7 +310,7 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
242
310
|
More info on tiles:
|
|
243
311
|
https://python-visualization.github.io/folium/latest/user_guide/raster_layers/tiles.html
|
|
244
312
|
"""
|
|
245
|
-
center =
|
|
313
|
+
center = to_points(center)
|
|
246
314
|
|
|
247
315
|
map_ = folium.Map(location=(center.lat, center.lon), zoom_start=zoom, attr=".", tiles=tiles)
|
|
248
316
|
|
|
@@ -260,13 +328,13 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
260
328
|
|
|
261
329
|
if isinstance(thing, Marker):
|
|
262
330
|
folium.Marker(
|
|
263
|
-
location=[thing.
|
|
331
|
+
location=[thing.point.lat, thing.point.lon],
|
|
264
332
|
popup=thing.popup,
|
|
265
333
|
).add_to(map_)
|
|
266
334
|
|
|
267
335
|
elif isinstance(thing, Dot):
|
|
268
336
|
folium.CircleMarker(
|
|
269
|
-
location=[thing.
|
|
337
|
+
location=[thing.point.lat, thing.point.lon],
|
|
270
338
|
radius=thing.radius,
|
|
271
339
|
color=thing.border_color,
|
|
272
340
|
weight=thing.border_width,
|
|
@@ -277,7 +345,7 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
277
345
|
|
|
278
346
|
elif isinstance(thing, Label):
|
|
279
347
|
folium.Marker(
|
|
280
|
-
location=[thing.
|
|
348
|
+
location=[thing.point.lat, thing.point.lon],
|
|
281
349
|
icon=folium.DivIcon(html=f"""
|
|
282
350
|
<div style="font-family: {thing.font};
|
|
283
351
|
font-size: {thing.size}px;
|
|
@@ -291,15 +359,15 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
291
359
|
|
|
292
360
|
elif isinstance(thing, Html):
|
|
293
361
|
folium.Marker(
|
|
294
|
-
location=[thing.
|
|
362
|
+
location=[thing.point.lat, thing.point.lon],
|
|
295
363
|
icon=folium.DivIcon(html=thing.code),
|
|
296
364
|
popup=thing.popup,
|
|
297
365
|
).add_to(map_)
|
|
298
366
|
|
|
299
367
|
elif isinstance(thing, Line):
|
|
300
368
|
folium.PolyLine(
|
|
301
|
-
locations=[(
|
|
302
|
-
for
|
|
369
|
+
locations=[(point.lat, point.lon)
|
|
370
|
+
for point in thing.points_sequence],
|
|
303
371
|
color=thing.color,
|
|
304
372
|
weight=thing.width,
|
|
305
373
|
opacity=thing.opacity,
|
|
@@ -308,8 +376,8 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
308
376
|
|
|
309
377
|
elif isinstance(thing, Area):
|
|
310
378
|
folium.Polygon(
|
|
311
|
-
locations=[(
|
|
312
|
-
for
|
|
379
|
+
locations=[(point.lat, point.lon)
|
|
380
|
+
for point in thing.points_sequence],
|
|
313
381
|
color=thing.border_color,
|
|
314
382
|
weight=thing.border_width,
|
|
315
383
|
fill_color=thing.color,
|
|
@@ -320,9 +388,9 @@ def draw_map(*things, center=(0, 0), zoom=1.5, tiles="cartodbpositron"):
|
|
|
320
388
|
return map_
|
|
321
389
|
|
|
322
390
|
|
|
323
|
-
# add shapely support if present
|
|
324
391
|
try:
|
|
325
|
-
|
|
392
|
+
# add shapely support if present
|
|
393
|
+
from shapely.geometry import (
|
|
326
394
|
Point as ShpPoint,
|
|
327
395
|
LineString as ShpLineString,
|
|
328
396
|
LinearRing as ShpLinearRing,
|
|
@@ -342,3 +410,16 @@ try:
|
|
|
342
410
|
except ImportError:
|
|
343
411
|
# shapely not present, do nothing
|
|
344
412
|
pass
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
try:
|
|
416
|
+
# add shapely support if present
|
|
417
|
+
# (https://telluric.readthedocs.io/en/latest/index.html)
|
|
418
|
+
from telluric import GeoVector, FeatureCollection, GeoFeature
|
|
419
|
+
|
|
420
|
+
auto_convert(GeoVector, lambda gv: gv.get_shape(gv.crs))
|
|
421
|
+
auto_convert(GeoFeature, lambda gf: gf.geometry)
|
|
422
|
+
auto_convert(FeatureCollection, lambda fc: fc.geometries)
|
|
423
|
+
except ImportError:
|
|
424
|
+
# telluric not present, do nothing
|
|
425
|
+
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|