-
Notifications
You must be signed in to change notification settings - Fork 0
/
locations.py
99 lines (79 loc) · 3.15 KB
/
locations.py
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
"""
Load GeoJSON file with a number of named locations defined by polygons. Accept
a point and return list of locations it is in.
"""
import json
import numpy as np
import gnss_tools
import shapely
class LocationTagger:
def __init__(self, geojson_file):
self.geojson_file = geojson_file
self.locations_wgs84 = {}
self.locations_polygons = {}
self.enu_origin = None
self.load_geojson(geojson_file)
def load_geojson(self, geojson_file):
"""
Load the GeoJSON file containing location polygons in WGS-84
coordinates and convert them to shapely polygons in ENU coordinates.
Save also the ENU frame origin.
Parameters:
geojson_file (str): The path to the GeoJSON file.
"""
# Get list of polygons from the GeoJSON file
with open(geojson_file, "rt") as f:
data = json.load(f)
polygon_centers = np.empty((2, 0))
for feature in data["features"]:
# Skip non-polygon features
if feature["geometry"]["type"] != "Polygon":
continue
name = feature["properties"]["name"]
# Swap the coordinates so latitude goes first
polygon_wgs84 = np.flip(
np.array(feature["geometry"]["coordinates"])[0].T, axis=0
)
self.locations_wgs84[name] = polygon_wgs84
polygon_centers = np.append(
polygon_centers, np.mean(polygon_wgs84, axis=1).reshape(2, 1), axis=1
)
# Use the mean of the polygon centers as the ENU frame origin
locations_center = np.mean(polygon_centers, axis=1).reshape(2, 1)
self.enu_origin = locations_center
# Convert the polygon coordinates to ENU
locations = {}
for name, polygon_wgs84 in self.locations_wgs84.items():
polygon_enu = gnss_tools.WGS84_to_ENU(
gnss_tools.prep_coords_wgs84(polygon_wgs84),
gnss_tools.prep_coords_wgs84(locations_center),
)
polygon_shapely = shapely.Polygon(polygon_enu.T)
locations[name] = polygon_shapely
self.locations_polygons = locations
def tag_points(self, points):
"""
Assign a list of locations to each given point.
Parameters:
points (np.ndarray): A numpy array containing the WGS-84 coordinates
with (3, N) or (2, N) shape, where the first row is latitude,
the second row is longitude, and the third row is altitude (if
present). Latitude and longitude are in degrees, and altitude is in
meters.
"""
# Convert the point coordinates to ENU
points_enu = gnss_tools.WGS84_to_ENU(
gnss_tools.prep_coords_wgs84(points),
gnss_tools.prep_coords_wgs84(self.enu_origin),
)
# Tag the points
tags = []
for point_enu in points_enu.T:
tags.append(
[
name
for name, polygon in self.locations_polygons.items()
if polygon.contains(shapely.geometry.Point(point_enu))
]
)
return tags