def create_feature(self, layer, featureDict, expected_type, srs=None): try: geom_dict = featureDict["geometry"] if not geom_dict: raise EsriFeatureLayerException("No Geometry Information") geom_type = geom_dict["type"] feature = ogr.Feature(layer.GetLayerDefn()) coords = self.get_geom_coords(geom_dict) f_json = json.dumps({"type": geom_type, "coordinates": coords}) geom = ogr.CreateGeometryFromJson(f_json) if geom and srs: geom.Transform(srs) if geom and expected_type != geom.GetGeometryType(): geom = ogr.ForceTo(geom, expected_type) if geom and expected_type == geom.GetGeometryType( ) and geom.IsValid(): feature.SetGeometry(geom) for prop, val in featureDict["properties"].items(): name = str(SLUGIFIER(prop)).encode('utf-8') value = val if value and layer.GetLayerDefn().GetFieldIndex( name) != -1: feature.SetField(name, value) layer.CreateFeature(feature) except Exception as e: logger.error(e)
def create_feature(self, layer, featureDict, expected_type, srs=None): created = False try: geom_dict = featureDict["geometry"] if not geom_dict: raise EsriFeatureLayerException("No Geometry Information") geom_type = geom_dict["type"] feature = ogr.Feature(layer.GetLayerDefn()) coords = self.get_geom_coords(geom_dict) f_json = json.dumps({"type": geom_type, "coordinates": coords}) geom = ogr.CreateGeometryFromJson(f_json) if geom and srs: geom.Transform(srs) if geom and expected_type != geom.GetGeometryType(): geom = ogr.ForceTo(geom, expected_type) if geom and expected_type == geom.GetGeometryType( ) and geom.IsValid(): feature.SetGeometry(geom) for prop, val in featureDict["properties"].items(): name = str(SLUGIFIER(prop)) value = val if value and layer.GetLayerDefn().GetFieldIndex( name) != -1: # replace id/code with mapped valued for subtypes if prop in self.esri_serializer.subtypes_fields: type_field_value = featureDict["properties"][ self.esri_serializer.subtype_field_name] # It is supposed to find the value, but check in case the data is not correct if value in self.esri_serializer.subtypes[ type_field_value][prop]: value = self.esri_serializer.subtypes[ type_field_value][prop][value] # It is supposed to find the value, but check in case the data is not correct elif prop in self.esri_serializer.fields_domains \ and value in self.esri_serializer.fields_domains[prop]: # replace id/code with mapped value for domain coded values value = self.esri_serializer.fields_domains[prop][ value] feature.SetField(name, value) created = layer.CreateFeature(feature) == ogr.OGRERR_NONE except Exception as e: logger.error('Failed to create feature', e) return created
def correct(in_layer, layer_name="", epsg=3857): """ This function standardizes a vector layer: 1. Multipart to singleparts 2. 3D polygon to 2D polygon 3. Reprojection 4. Fix geometry for self intersections Parameters ---------- in_layer : ogr layer layer_name : string, optional The default is ''. epsg : int, optional The default is 3857. Raises ------ ValueError For a z-type geometry Returns ------- out_datasource : ogr datasource """ try: # retrieving lost features lost_features = [] in_feature_count = in_layer.GetFeatureCount() # Get inspatial reference and geometry from in shape geom_type = in_layer.GetGeomType() in_spatial_ref = in_layer.GetSpatialRef() in_layer.ResetReading() mem_datasource = create_mem_ds() mem_layer = mem_datasource.CreateLayer(layer_name, in_spatial_ref, geom_type) layer_defn = in_layer.GetLayerDefn() for i in range(layer_defn.GetFieldCount()): field_defn = layer_defn.GetFieldDefn(i) mem_layer.CreateField(field_defn) print("info", "check - Multipart to singlepart") lost_feat = multipoly2poly(in_layer, mem_layer) lost_features = lost_features + lost_feat if mem_layer.GetFeatureCount() == 0: print("error", "Multipart to singlepart failed") return 1 spatial_ref_3857 = osr.SpatialReference() spatial_ref_3857.ImportFromEPSG(int(epsg)) reproject = osr.CoordinateTransformation(in_spatial_ref, spatial_ref_3857) flatten = False geom_name = ogr.GeometryTypeToName(geom_type) if "3D" in geom_name: print("warning", "geom type: " + geom_name) print("info", "Flattening to 2D") flatten = True elif geom_type < 0: print("error", "geometry invalid, most likely has a z-type") raise ValueError( "geometry invalid, most likely has a z-type", "geom type: ", geom_name, ) # Create output dataset and force dataset to multiparts if geom_type == 6: geom_type = 3 # polygon elif geom_type == 5: geom_type = 2 # linestring elif geom_type == 4: geom_type = 1 # point out_datasource = create_mem_ds() out_layer = out_datasource.CreateLayer(layer_name, spatial_ref_3857, geom_type) layer_defn = in_layer.GetLayerDefn() # Copy fields from memory layer to output dataset for i in range(layer_defn.GetFieldCount()): out_layer.CreateField(layer_defn.GetFieldDefn(i)) print("info", "check - Reproject layer to {}".format(str(epsg))) for out_feat in tqdm(mem_layer): out_geom = out_feat.GetGeometryRef() try: out_geom, valid = fix_geometry(out_geom) except Exception as e: print(e) print(out_feat.GetFID()) if not valid: print("warning", "geometry invalid even with buffer, skipping") lost_features.append(out_feat.GetFID()) continue # Force and transform geometry out_geom = ogr.ForceTo(out_geom, geom_type) out_geom.Transform(reproject) # flattening to 2d if flatten: out_geom.FlattenTo2D() # Set geometry and create feature out_feat.SetGeometry(out_geom) out_layer.CreateFeature(out_feat) print("info", "check - delete ogc_fid if exists") out_layer_defn = out_layer.GetLayerDefn() for n in range(out_layer_defn.GetFieldCount()): field = out_layer_defn.GetFieldDefn(n) if field.name == "ogc_fid": out_layer.DeleteField(n) break print("info", "check - Features count") out_feature_count = out_layer.GetFeatureCount() if len(lost_features) > 0: print( "warning", "Lost {} features during corrections".format( len(lost_features)), ) print("warning", "FIDS: {}".format(lost_features)) elif in_feature_count > out_feature_count: print("warning", "In feature count greater than out feature count") else: pass except Exception as e: print(e) finally: mem_layer = None mem_datasource = None out_layer = None print("Finished vector corrections") return out_datasource, layer_name