1515from 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
3137class StreetTask (BaseTask ):
32- pass
38+ geometry : str
39+ data : str
40+
3341
3442class 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