0
# Geometry and Polygon Access
1
2
Advanced functionality for accessing timezone polygon geometry, boundary coordinates, and spatial relationships. These capabilities enable applications requiring detailed geographic data, custom spatial analysis, or integration with GIS systems.
3
4
## Capabilities
5
6
### Timezone Geometry Retrieval
7
8
Functions for retrieving complete timezone polygon geometry including boundaries and holes.
9
10
```python { .api }
11
def get_geometry(
12
self,
13
tz_name: Optional[str] = "",
14
tz_id: Optional[int] = 0,
15
use_id: bool = False,
16
coords_as_pairs: bool = False
17
) -> List[Union[List[CoordPairs], List[CoordLists]]]:
18
"""
19
Retrieve complete geometry of a timezone including all boundary polygons and holes.
20
21
Parameters:
22
- tz_name: Timezone name from timezone_names list (e.g., 'Europe/Berlin')
23
- tz_id: Timezone ID (index in timezone_names, 0 to nr_of_zones-1)
24
- use_id: If True, use tz_id parameter instead of tz_name
25
- coords_as_pairs: If True, return coordinates as [(lng,lat), ...] pairs,
26
if False, return as ([longitudes], [latitudes]) lists
27
28
Returns:
29
- Multipolygon data structure: [[polygon1, hole1, hole2...], [polygon2, ...], ...]
30
Each polygon/hole is coordinate pairs or separate longitude/latitude lists
31
32
Raises:
33
- ValueError: If timezone name doesn't exist or tz_id is out of range
34
- TypeError: If tz_id is not an integer when use_id=True
35
"""
36
37
def get_polygon(
38
self,
39
boundary_id: int,
40
coords_as_pairs: bool = False
41
) -> List[Union[CoordPairs, CoordLists]]:
42
"""
43
Get coordinates of a specific boundary polygon including its holes.
44
45
Parameters:
46
- boundary_id: ID of the boundary polygon (0 to nr_of_polygons-1)
47
- coords_as_pairs: If True, return coordinates as [(lng,lat), ...] pairs,
48
if False, return as ([longitudes], [latitudes]) lists
49
50
Returns:
51
- List where first element is boundary polygon, remaining elements are holes
52
"""
53
54
def coords_of(self, boundary_id: int = 0) -> np.ndarray:
55
"""
56
Get raw coordinates of a boundary polygon from the dataset.
57
58
Parameters:
59
- boundary_id: ID of the boundary polygon (0 to nr_of_polygons-1)
60
61
Returns:
62
- NumPy array of polygon coordinates in internal format
63
"""
64
```
65
66
### Polygon Spatial Operations
67
68
Functions for spatial relationships and polygon testing.
69
70
```python { .api }
71
def inside_of_polygon(self, boundary_id: int, x: int, y: int) -> bool:
72
"""
73
Check if a point is inside a boundary polygon, accounting for holes.
74
75
Parameters:
76
- boundary_id: ID of the boundary polygon
77
- x: X-coordinate of point (longitude converted to integer format)
78
- y: Y-coordinate of point (latitude converted to integer format)
79
80
Returns:
81
- True if point is inside boundary polygon and not in any holes
82
"""
83
```
84
85
### Zone and Boundary Mapping
86
87
Functions for navigating relationships between zones, boundaries, and coordinates.
88
89
```python { .api }
90
def zone_id_of(self, boundary_id: int) -> int:
91
"""
92
Get the zone ID that a boundary polygon belongs to.
93
94
Parameters:
95
- boundary_id: ID of the boundary polygon
96
97
Returns:
98
- Zone ID (index in timezone_names)
99
100
Raises:
101
- ValueError: If zone_ids data is not available
102
"""
103
104
def zone_ids_of(self, boundary_ids: np.ndarray) -> np.ndarray:
105
"""
106
Get zone IDs for multiple boundary polygons.
107
108
Parameters:
109
- boundary_ids: Array of boundary polygon IDs
110
111
Returns:
112
- Array of corresponding zone IDs
113
"""
114
115
def zone_name_from_id(self, zone_id: int) -> str:
116
"""
117
Get timezone name from zone ID.
118
119
Parameters:
120
- zone_id: Zone identifier (0 to nr_of_zones-1)
121
122
Returns:
123
- Timezone name (e.g., 'Europe/Berlin')
124
125
Raises:
126
- ValueError: If zone_id is out of range
127
"""
128
129
def zone_name_from_boundary_id(self, boundary_id: int) -> str:
130
"""
131
Get timezone name directly from boundary polygon ID.
132
133
Parameters:
134
- boundary_id: ID of the boundary polygon
135
136
Returns:
137
- Timezone name that the boundary belongs to
138
"""
139
```
140
141
### Shortcut System Access
142
143
Functions for working with the spatial indexing system used for performance optimization.
144
145
```python { .api }
146
def get_boundaries_in_shortcut(self, *, lng: float, lat: float) -> np.ndarray:
147
"""
148
Get all boundary polygon IDs in the shortcut area containing the coordinates.
149
150
Parameters:
151
- lng: Longitude in degrees (-180.0 to 180.0)
152
- lat: Latitude in degrees (-90.0 to 90.0)
153
154
Returns:
155
- Array of boundary polygon IDs in the H3 hexagon containing the point
156
"""
157
158
def most_common_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
159
"""
160
Get the most common zone ID in the shortcut area.
161
162
Note: 'Most common' means the zone with boundary polygons having
163
the most total coordinates in the shortcut area.
164
165
Parameters:
166
- lng: Longitude in degrees (-180.0 to 180.0)
167
- lat: Latitude in degrees (-90.0 to 90.0)
168
169
Returns:
170
- Zone ID of most common zone, or None if no polygons in area
171
"""
172
173
def unique_zone_id(self, *, lng: float, lat: float) -> Optional[int]:
174
"""
175
Get zone ID if unique within the shortcut area.
176
177
Parameters:
178
- lng: Longitude in degrees (-180.0 to 180.0)
179
- lat: Latitude in degrees (-90.0 to 90.0)
180
181
Returns:
182
- Zone ID if only one zone in area, None if multiple or no zones
183
"""
184
```
185
186
## Usage Examples
187
188
### Complete Timezone Geometry
189
190
```python
191
from timezonefinder import TimezoneFinder
192
193
tf = TimezoneFinder()
194
195
# Get complete geometry for a timezone
196
geometry = tf.get_geometry(tz_name='Europe/Berlin', coords_as_pairs=False)
197
198
print(f"Europe/Berlin has {len(geometry)} polygon(s)")
199
200
for i, polygon_with_holes in enumerate(geometry):
201
boundary = polygon_with_holes[0] # Boundary polygon
202
holes = polygon_with_holes[1:] # Hole polygons (if any)
203
204
lngs, lats = boundary
205
print(f"Polygon {i}: {len(lngs)} boundary points, {len(holes)} holes")
206
207
# Process each hole
208
for j, hole in enumerate(holes):
209
hole_lngs, hole_lats = hole
210
print(f" Hole {j}: {len(hole_lngs)} points")
211
```
212
213
### Coordinate Pair Format
214
215
```python
216
from timezonefinder import TimezoneFinder
217
218
tf = TimezoneFinder()
219
220
# Get geometry as coordinate pairs
221
geometry = tf.get_geometry(tz_name='Europe/Berlin', coords_as_pairs=True)
222
223
for i, polygon_with_holes in enumerate(geometry):
224
boundary = polygon_with_holes[0] # [(lng1, lat1), (lng2, lat2), ...]
225
holes = polygon_with_holes[1:]
226
227
print(f"Polygon {i} boundary:")
228
print(f" First point: {boundary[0]}")
229
print(f" Last point: {boundary[-1]}")
230
print(f" Total points: {len(boundary)}")
231
232
for j, hole in enumerate(holes):
233
print(f" Hole {j}: {len(hole)} points")
234
```
235
236
### Individual Polygon Access
237
238
```python
239
from timezonefinder import TimezoneFinder
240
241
tf = TimezoneFinder()
242
243
# Get a specific boundary polygon by ID
244
boundary_id = 100
245
polygon_data = tf.get_polygon(boundary_id, coords_as_pairs=False)
246
247
boundary = polygon_data[0]
248
holes = polygon_data[1:]
249
250
lngs, lats = boundary
251
print(f"Boundary {boundary_id}: {len(lngs)} points, {len(holes)} holes")
252
253
# Get zone information for this boundary
254
zone_id = tf.zone_id_of(boundary_id)
255
zone_name = tf.zone_name_from_id(zone_id)
256
print(f"Boundary {boundary_id} belongs to zone {zone_id}: {zone_name}")
257
```
258
259
### Spatial Analysis
260
261
```python
262
from timezonefinder import TimezoneFinder
263
import numpy as np
264
265
tf = TimezoneFinder()
266
267
# Analyze boundaries in a specific area
268
lng, lat = 13.358, 52.5061 # Berlin coordinates
269
boundary_ids = tf.get_boundaries_in_shortcut(lng=lng, lat=lat)
270
271
print(f"Found {len(boundary_ids)} boundaries near Berlin")
272
273
# Group by timezone
274
zone_ids = tf.zone_ids_of(boundary_ids)
275
unique_zones = np.unique(zone_ids)
276
277
print(f"These boundaries belong to {len(unique_zones)} different timezones:")
278
for zone_id in unique_zones:
279
zone_name = tf.zone_name_from_id(zone_id)
280
count = np.sum(zone_ids == zone_id)
281
print(f" {zone_name}: {count} boundaries")
282
283
# Find most common zone
284
most_common_id = tf.most_common_zone_id(lng=lng, lat=lat)
285
if most_common_id is not None:
286
most_common_name = tf.zone_name_from_id(most_common_id)
287
print(f"Most common zone: {most_common_name}")
288
```
289
290
### GIS Integration Example
291
292
```python
293
from timezonefinder import TimezoneFinder
294
import json
295
296
def timezone_to_geojson(tf, tz_name):
297
"""Convert timezone geometry to GeoJSON format."""
298
geometry = tf.get_geometry(tz_name=tz_name, coords_as_pairs=True)
299
300
features = []
301
for i, polygon_with_holes in enumerate(geometry):
302
boundary = polygon_with_holes[0]
303
holes = polygon_with_holes[1:]
304
305
# GeoJSON coordinates: [exterior_ring, interior_ring1, interior_ring2, ...]
306
coordinates = [boundary] # Exterior ring
307
coordinates.extend(holes) # Interior rings (holes)
308
309
feature = {
310
"type": "Feature",
311
"properties": {
312
"timezone": tz_name,
313
"polygon_id": i
314
},
315
"geometry": {
316
"type": "Polygon",
317
"coordinates": coordinates
318
}
319
}
320
features.append(feature)
321
322
return {
323
"type": "FeatureCollection",
324
"features": features
325
}
326
327
# Usage
328
tf = TimezoneFinder()
329
geojson = timezone_to_geojson(tf, 'Europe/Berlin')
330
331
# Save to file
332
with open('berlin_timezone.geojson', 'w') as f:
333
json.dump(geojson, f, indent=2)
334
335
print(f"Exported {len(geojson['features'])} polygons for Europe/Berlin")
336
```
337
338
### Custom Spatial Queries
339
340
```python
341
from timezonefinder import TimezoneFinder
342
from timezonefinder.utils import coord2int
343
344
tf = TimezoneFinder()
345
346
def find_overlapping_zones(lng, lat, radius_degrees=0.1):
347
"""Find all timezones within a radius of a point."""
348
# Sample points in a grid around the center
349
step = radius_degrees / 10
350
zones = set()
351
352
for dlng in [-radius_degrees, 0, radius_degrees]:
353
for dlat in [-radius_degrees, 0, radius_degrees]:
354
test_lng = lng + dlng
355
test_lat = lat + dlat
356
357
# Get boundaries in this area
358
boundaries = tf.get_boundaries_in_shortcut(lng=test_lng, lat=test_lat)
359
360
# Convert coordinates for polygon testing
361
x = coord2int(test_lng)
362
y = coord2int(test_lat)
363
364
# Test each boundary
365
for boundary_id in boundaries:
366
if tf.inside_of_polygon(boundary_id, x, y):
367
zone_name = tf.zone_name_from_boundary_id(boundary_id)
368
zones.add(zone_name)
369
370
return list(zones)
371
372
# Find zones near a border area
373
border_zones = find_overlapping_zones(lng=8.5, lat=47.5, radius_degrees=0.5)
374
print(f"Zones near Swiss-German border: {border_zones}")
375
```