Skip to content

Commit 1187561

Browse files
committed
feat: add geometry to StreetTask and refactoring
1 parent 481030c commit 1187561

File tree

1 file changed

+33
-124
lines changed
  • mapswipe_workers/mapswipe_workers/project_types/street

1 file changed

+33
-124
lines changed

mapswipe_workers/mapswipe_workers/project_types/street/project.py

Lines changed: 33 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515
from mapswipe_workers.generate_stats.project_stats import (
1616
get_statistics_for_integer_result_project,
1717
)
18-
from mapswipe_workers.project_types.project import (
19-
BaseProject, BaseTask, BaseGroup
18+
from mapswipe_workers.utils.validate_input import (
19+
check_if_layer_is_empty,
20+
load_geojson_to_ogr,
21+
build_multipolygon_from_layer_geometries,
22+
check_if_layer_has_too_many_geometries,
23+
save_geojson_to_file,
24+
multipolygon_to_wkt
2025
)
21-
from mapswipe_workers.utils.process_mapillary import get_image_ids
26+
from mapswipe_workers.project_types.project import BaseProject, BaseTask, BaseGroup
27+
from mapswipe_workers.utils.process_mapillary import get_image_metadata
2228

2329

2430
@dataclass
@@ -29,18 +35,22 @@ class StreetGroup(BaseGroup):
2935

3036
@dataclass
3137
class StreetTask(BaseTask):
32-
pass
38+
geometry: str
39+
data: str
40+
3341

3442
class StreetProject(BaseProject):
3543
def __init__(self, project_draft):
3644
super().__init__(project_draft)
3745
self.groups: Dict[str, StreetGroup] = {}
38-
self.tasks: Dict[str, List[StreetTask]] = (
39-
{}
40-
)
46+
self.tasks: Dict[str, List[StreetTask]] = {}
4147

4248
self.geometry = project_draft["geometry"]
43-
self.imageList = get_image_ids()
49+
ImageMetadata = get_image_metadata(self.geometry)
50+
51+
52+
self.imageIds = ImageMetadata["ids"]
53+
self.imageGeometries = ImageMetadata["geometries"]
4454

4555
def save_tasks_to_firebase(self, projectId: str, tasks: dict):
4656
firebase = Firebase()
@@ -62,131 +72,29 @@ def get_per_project_statistics(project_id, project_info):
6272
)
6373

6474
def validate_geometries(self):
65-
raw_input_file = (
66-
f"{DATA_PATH}/input_geometries/raw_input_{self.projectId}.geojson"
75+
self.inputGeometriesFileName = save_geojson_to_file(
76+
self.projectId, self.geometry
6777
)
78+
layer, datasource = load_geojson_to_ogr(self.projectId, self.inputGeometriesFileName)
6879

69-
if not os.path.isdir(f"{DATA_PATH}/input_geometries"):
70-
os.mkdir(f"{DATA_PATH}/input_geometries")
71-
72-
valid_input_file = (
73-
f"{DATA_PATH}/input_geometries/valid_input_{self.projectId}.geojson"
74-
)
80+
# check if inputs fit constraints
81+
check_if_layer_is_empty(self.projectId, layer)
7582

76-
logger.info(
77-
f"{self.projectId}"
78-
f" - __init__ - "
79-
f"downloaded input geometries from url and saved as file: "
80-
f"{raw_input_file}"
83+
multi_polygon, project_area = build_multipolygon_from_layer_geometries(
84+
self.projectId, layer
8185
)
82-
self.inputGeometries = raw_input_file
83-
84-
# open the raw input file and get layer
85-
driver = ogr.GetDriverByName("GeoJSON")
86-
datasource = driver.Open(raw_input_file, 0)
87-
try:
88-
layer = datasource.GetLayer()
89-
LayerDefn = layer.GetLayerDefn()
90-
except AttributeError:
91-
raise CustomError("Value error in input geometries file")
92-
93-
# create layer for valid_input_file to store all valid geometries
94-
outDriver = ogr.GetDriverByName("GeoJSON")
95-
# Remove output geojson if it already exists
96-
if os.path.exists(valid_input_file):
97-
outDriver.DeleteDataSource(valid_input_file)
98-
outDataSource = outDriver.CreateDataSource(valid_input_file)
99-
outLayer = outDataSource.CreateLayer(
100-
"geometries", geom_type=ogr.wkbMultiPolygon
101-
)
102-
for i in range(0, LayerDefn.GetFieldCount()):
103-
fieldDefn = LayerDefn.GetFieldDefn(i)
104-
outLayer.CreateField(fieldDefn)
105-
outLayerDefn = outLayer.GetLayerDefn()
106-
107-
# check if raw_input_file layer is empty
108-
feature_count = layer.GetFeatureCount()
109-
if feature_count < 1:
110-
err = "empty file. No geometries provided"
111-
# TODO: How to user logger and exceptions?
112-
logger.warning(f"{self.projectId} - check_input_geometry - {err}")
113-
raise CustomError(err)
114-
elif feature_count > 100000:
115-
err = f"Too many Geometries: {feature_count}"
116-
logger.warning(f"{self.projectId} - check_input_geometry - {err}")
117-
raise CustomError(err)
118-
119-
# get geometry as wkt
120-
# get the bounding box/ extent of the layer
121-
extent = layer.GetExtent()
122-
# Create a Polygon from the extent tuple
123-
ring = ogr.Geometry(ogr.wkbLinearRing)
124-
ring.AddPoint(extent[0], extent[2])
125-
ring.AddPoint(extent[1], extent[2])
126-
ring.AddPoint(extent[1], extent[3])
127-
ring.AddPoint(extent[0], extent[3])
128-
ring.AddPoint(extent[0], extent[2])
129-
poly = ogr.Geometry(ogr.wkbPolygon)
130-
poly.AddGeometry(ring)
131-
wkt_geometry = poly.ExportToWkt()
132-
133-
# check if the input geometry is a valid polygon
134-
for feature in layer:
135-
feat_geom = feature.GetGeometryRef()
136-
geom_name = feat_geom.GetGeometryName()
137-
fid = feature.GetFID()
138-
139-
if not feat_geom.IsValid():
140-
layer.DeleteFeature(fid)
141-
logger.warning(
142-
f"{self.projectId}"
143-
f" - check_input_geometries - "
144-
f"deleted invalid feature {fid}"
145-
)
146-
147-
# we accept only POLYGON or MULTIPOLYGON geometries
148-
elif geom_name not in ["POLYGON", "MULTIPOLYGON"]:
149-
layer.DeleteFeature(fid)
150-
logger.warning(
151-
f"{self.projectId}"
152-
f" - check_input_geometries - "
153-
f"deleted non polygon feature {fid}"
154-
)
15586

156-
else:
157-
# Create output Feature
158-
outFeature = ogr.Feature(outLayerDefn)
159-
# Add field values from input Layer
160-
for i in range(0, outLayerDefn.GetFieldCount()):
161-
outFeature.SetField(
162-
outLayerDefn.GetFieldDefn(i).GetNameRef(), feature.GetField(i)
163-
)
164-
outFeature.SetGeometry(feat_geom)
165-
outLayer.CreateFeature(outFeature)
166-
outFeature = None
167-
168-
# check if layer is empty
169-
if layer.GetFeatureCount() < 1:
170-
err = "no geometries left after checking validity and geometry type."
171-
logger.warning(f"{self.projectId} - check_input_geometry - {err}")
172-
raise Exception(err)
87+
check_if_layer_has_too_many_geometries(self.projectId, multi_polygon)
17388

17489
del datasource
175-
del outDataSource
17690
del layer
17791

178-
self.inputGeometriesFileName = valid_input_file
179-
180-
logger.info(
181-
f"{self.projectId}"
182-
f" - check_input_geometry - "
183-
f"filtered correct input geometries and created file: "
184-
f"{valid_input_file}"
185-
)
92+
logger.info(f"{self.projectId}" f" - validate geometry - " f"input geometry is correct.")
93+
wkt_geometry = multipolygon_to_wkt(multi_polygon)
18694
return wkt_geometry
18795

18896
def create_groups(self):
189-
self.numberOfGroups = math.ceil(len(self.imageList) / self.groupSize)
97+
self.numberOfGroups = math.ceil(len(self.imageIds) / self.groupSize)
19098
for group_id in range(self.numberOfGroups):
19199
self.groups[f"g{group_id}"] = StreetGroup(
192100
projectId=self.projectId,
@@ -206,13 +114,14 @@ def create_tasks(self):
206114
task = StreetTask(
207115
projectId=self.projectId,
208116
groupId=group_id,
209-
taskId=self.imageList.pop(),
117+
data=str(self.imageGeometries.pop()),
118+
geometry="",
119+
taskId=self.imageIds.pop(),
210120
)
211121
self.tasks[group_id].append(task)
212122

213123
# list now empty? if usual group size is not reached
214124
# the actual number of tasks for the group is updated
215-
if not self.imageList:
125+
if not self.imageIds:
216126
group.numberOfTasks = i + 1
217127
break
218-

0 commit comments

Comments
 (0)