def remove_null_geometries(data: geopandas.GeoDataFrame): nulls = data.geometry.values == None log.info(f"found {len(nulls)} null geometries") if np.any(nulls): log.info("Found null entries") return data[data.geometry.values != None] # remove null geometries else: return data
def polygons_to_lines(polygons): polygons.geometry = polygons.buffer(0) polygons = explode_multipolygons(polygons) polygons = remove_null_geometries(polygons) polygons = remove_truly_duplicated_geometries(polygons) log.info(polygons) tj = topojson.Topology(polygons) out = extract_numpy_arcs(tj) glines = [asLineString(e) for e in out] asg = geopandas.GeoDataFrame(geometry=glines) return asg, polygons
def mappy_construct(lines: geopandas.GeoDataFrame, points: geopandas.GeoDataFrame, output: str, units_field: str, layer_name="geomap", auto_extend=0, overwrite=False, debug=False): log.info("Executing mappy construct") log.info(f"CRS lines: {lines.crs}") log.info(f"CRS points: {points.crs}") out_args = {} out_args["layers"] = [] if lines.crs != points.crs: log.warning("points and lines layers has different CRS, reprojecting...") points = points.to_crs(lines.crs) if os.path.exists(output): log.debug(f"File {output} exists!") existing_layers = fiona.listlayers(output) if layer_name in existing_layers and overwrite is not True: log.error(f"output geopackage {output} already contains a layer named {layer_name}.") return out_args if auto_extend != 0: log.info("extend_lines enabled, lines are extended") lines = extend_lines(lines, auto_extend) if debug: lines.to_file(output, layer="debug_extended_lines", driver="GPKG") out_args["layers"].append(lines) if debug: intersections = compute_self_intersections_points(lines) intersections.to_file(output, layer="debug_self_intersections", driver="GPKG") out_args["layers"].append("debug_self_intersections") polygons = polygonize(lines) if debug: polygons.to_file(output, layer="debug_polygons", driver="GPKG") out_args["layers"].append("debug_polygons") out = transfer_units_to_polygons(polygons, points, units_field) out.crs = None # for now, then use the same as lines # from mappy.dev_tests import test_geopandas_save_gpkg # test_geopandas_save_gpkg() try: out.to_file(output, layer=layer_name, driver="GPKG") except Exception as e: print(e) raise e out_args["layers"].append(layer_name) out_args["gpkg"] = output return out_args
def mappy_deconstruct(polygons, units_field, output_gpkg, lines_layer_name, points_layer_name): log.info("Executing mappy deconstruct") lines, polygons = polygons_to_lines(polygons) # it also returns a cleaned version of the polygonal layer points = generate_label_points(polygons) points = transfer_polygons_fields_to_points(points, polygons) points.reset_index() # points.crs = None lines.to_file(output_gpkg, layer=lines_layer_name, driver="GPKG") try: points.to_file(output_gpkg, layer=points_layer_name, driver="GPKG") except Exception as e: raise e # return points out_args = {} out_args["layers"] = [] out_args["layers"].append(points) out_args["layers"].append(lines) return out_args
def transfer_units_to_polygons(polygons: geopandas.GeoDataFrame, units: geopandas.GeoDataFrame, units_field: str): """ this could be obtained with a spatial joint, but with this we have more control to perform checks and know what is going on e.g. geopandas.sjoin( polygons, units, how="left", op='contains').plot(column= units_field) :param polygons: :param units: :param units_field: :return: A copy of polygons with the units """ outids = [] for pol in polygons.geometry: ids = get_points_inside(pol, units.geometry) log.info(f"found {len(ids)} polygon_ids: {ids}") thisunit = units[units_field][ids].values log.info(f"thisunit {thisunit}") if len(ids) > 1: log.warning("more than two points were found in the same polygon") if np.all(thisunit == thisunit[0]): log.warning("no prob, because point to the same unit") else: log.warning("The unit contains points with mismatched indicator points. Setting to None") thisunit = [None] if len(ids) < 1: log.error("cannot associate some polygons to an unit, missing points in unit definition file?") thisunit = [None] myunit = thisunit[0] outids.append(myunit) from copy import deepcopy out_polygons = deepcopy(polygons) out_polygons[units_field] = outids return out_polygons