Example #1
0
    def from_online_srtm_database(bounds, path_to_dem_file=DEFAULT_OUTPUT, product="SRTM1", margin=0,
                                  no_data_value=-32768):
        """ Import DEM tile from SRTM3 or SRTM1 online dataset

        Based on "elevation" module. Be careful that at the moment, SRTM3 product
        does not seem to work properly.
        :param bounds:
        :param path_to_dem_file:
        :param product: "SRTM1" or "SRTM3"
        :param margin: margin (in %) around DEM
        :param no_data_value: no data filling value (default = -32768)
        :return:
        """
        from subprocess import CalledProcessError
        import elevation

        try:
            check_string(product, {'SRTM1', 'SRTM3'})
        except ValueError as e:
            raise DigitalElevationModelError("Invalid product name '%s': %s" % (product, e))

        try:
            elevation.clip(bounds, output=path_to_dem_file, margin="%s" % (margin/100), product=product)
        except CalledProcessError as e:
            raise DigitalElevationModelError("Internal subprocess error: %s" % e)
        except (ValueError, TypeError, KeyError) as e:
            raise DigitalElevationModelError("Invalid input argument: %s" % e)

        # Return instance of DigitalElevationModel
        return DigitalElevationModel(path_to_dem_file, no_data_value=no_data_value)
Example #2
0
    def get_shortest_path_length(self,
                                 node_start,
                                 node_end,
                                 method: str = "networkx"):
        """ Get dijkstra shortest path length

        :param node_start: shapely Point
        :param node_end: shapely Point
        :param method: {'internal', 'networkx'}
        :return: length of path in m
        """
        check_string(method, ("internal", "networkx"))
        if method == "internal":
            edge_path = self.get_shortest_path(node_start, node_end)
            length = 0
            if edge_path is not None and edge_path != []:
                for edge in edge_path.geometry:
                    length += edge.length
            elif edge_path is None:
                return None
        else:
            node_start = (node_start.x, node_start.y)
            node_end = (node_end.x, node_end.y)
            length = nx.dijkstra_path_length(self.graph, node_start, node_end)

        return length
Example #3
0
    def find_disconnected_islands_and_fix(self,
                                          tolerance=None,
                                          method="delete"):
        """ Find disconnected components in network

        Find disconnected components/islands graphs in multi-graph
        and apply method (fix/reconnect, keep, delete) with respect
        to a given tolerance
        :param tolerance:
        :param method:
        :return:
        """
        method = check_string(
            method, {'reconnect_and_delete', 'reconnect_and_keep', 'delete'})
        sub_graphs = list((self._graph.subgraph(c)
                           for c in nx.connected_components(self._graph)))
        main_component = max(sub_graphs, key=len)
        sub_graphs.remove(main_component)

        idx_edge = []
        if method == "delete":
            for graph in sub_graphs:
                for edge in graph.edges:
                    try:
                        idx_edge.append(self.from_to.index((edge[0], edge[1])))
                    except ValueError:
                        idx_edge.append(self.from_to.index((edge[1], edge[0])))

        elif method == 'reconnect_and_delete':
            pass
        elif method == 'reconnect_and_keep':
            pass

        return self.drop(self.index[idx_edge])
Example #4
0
    def compute_slope(self, slope_format="percent"):
        """ Compute slope from DEM

        :return:
        """
        slope_format = check_string(slope_format, {'percent', 'degree'})
        return self._compute_slope(slope_format)
Example #5
0
def ql_query(osm_type, tag, values=None, bounds=None, polygon_coord=None, timeout=180):
    """ QL query (thanks to https://github.com/yannforget/OSMxtract for inspiration !)

    :param osm_type: OSM geometry type str {'node', 'way', 'relation', 'nwr'}
    :param tag: OSM tag to query
    :param values: str/list of possible values for the provided OSM tag
    :param bounds: geometry bounds
    :param polygon_coord: location's polygon list of coordinates
    :param timeout:
    :return:
    """
    osm_type = check_string(osm_type, ('node', 'way', 'relation', 'nwr'))

    if isinstance(values, str):
        values = [values]

    if bounds and not polygon_coord:
        west, south, east, north = bounds
        boundary = f'({south:.6f},{west:.6f},{north:.6f},{east:.6f})'
    elif polygon_coord and not bounds:
        boundary = f'(poly:"{polygon_coord}")'
    else:
        raise QlQueryError("Must define either geometry bounds or polygon coordinates")

    if values:
        if len(values) > 1:
            tags = f'["{ tag }"~"{ "|".join(values) }"]'
        else:
            tags = f'["{ tag }"="{ values[0] }"]'
    else:
        tags = f'["{tag}"]'

    return f'[out:json][timeout:{timeout}];{osm_type}{tags}{boundary};out geom;'
Example #6
0
    def set_max_speed(self, attr_name, speed_dic, speed_format='km/h'):
        """ Set max allowed speed at intersection

        :param attr_name:
        :param speed_dic:
        :param speed_format:
        :return:
        """
        check_string(speed_format, ('m/s', 'km/h'))
        self._check_attr_and_dic(attr_name, speed_dic)

        for key in speed_dic.keys():
            if not isinstance(speed_dic[key], (float, int)):
                raise RoadNodeError("Speed value must be numeric but is '%s'" %
                                    type(speed_dic[key]))
            self._gpd_df.loc[
                self[attr_name] == key,
                "max_speed"] = speed_dic[key] / SPEED_RATIO[speed_format]
Example #7
0
    def __init__(self, ellipsoid_model: str):

        ellipsoid_model = check_string(ellipsoid_model,
                                       list(REF_ELLIPSOID.keys()))
        self._f = 1 / REF_ELLIPSOID[ellipsoid_model]['rf']
        self._a = REF_ELLIPSOID[ellipsoid_model]['a']
        self._b = self._a - self._a * self._f
        self._e = math.sqrt(1 - (self._b**2 / self._a**2))
        self._model = ellipsoid_model
Example #8
0
def json_to_geodataframe(response, geometry_type):
    """ Convert JSON responses to

    :param response: json response
    :param geometry_type: type of geometry to extract ('point', 'linestring', 'polygon', 'multipolygon')
    :return:
    """
    geometry_type = check_string(geometry_type, ('point', 'linestring', 'polygon'))

    if geometry_type == 'point':
        return gpd.GeoDataFrame.from_features(_to_point_features(response), crs=default_crs)
    else:
        return gpd.GeoDataFrame.from_features(_to_features(response, geometry_type), crs=default_crs)
Example #9
0
    def table_to_layer(self, table_name, schema=None, geom_type=None, bounds=None, polygon_extent=None):
        """ Convert table from database to GeoLayer instance

        :param table_name: name of table (case sensitive)
        :param schema: database schema (case sensitive)
        :param geom_type: geometry type
        :param bounds: bounding box (x_min, y_min, x_max, y_max)
        :param polygon_extent: shapely polygon
        :return:
        """
        if schema is None:
            schema = "public"

        if bounds is not None and polygon_extent is None:
            sql_string = f'SELECT * FROM "{schema}"."{table_name}" WHERE "{schema}"."{table_name}".geom && ' \
                         f'ST_MakeEnvelope({bounds[0]}, {bounds[1]}, {bounds[2]}, {bounds[3]})'
        elif polygon_extent is not None and bounds is None:
            sql_string = f'SELECT * FROM "{schema}"."{table_name}" WHERE ST_Within("{schema}"."{table_name}".geom, ' \
                         f'{polygon_extent})'
        else:
            sql_string = f'SELECT * FROM "{schema}"."{table_name}"'

        df = GeoDataFrame.from_postgis(sql_string, self.engine)

        if table_name in self.get_table_names(schema) and geom_type is None:
            try:
                layer = PolygonLayer(df, name=table_name)
            except GeoLayerError:
                try:
                    layer = LineLayer(df, name=table_name)
                except GeoLayerError:
                    layer = PointLayer(df, name=table_name)
        elif table_name in self.get_table_names(schema) and geom_type is not None:
            try:
                geom_type = check_string(geom_type, ("point", "line", "polygon"))
            except ValueError:
                raise SpatialDatabaseError("Invalid geometry type '%s'. Must be 'point', 'line' or 'polygon'." %
                                           geom_type)
            layer = self.layer_class[geom_type](df, name=table_name)
        else:
            raise SpatialDatabaseError("No table named '%s' in database '%s'" % (table_name, self.db_name))

        return layer