예제 #1
0
def moment_of_inertia(collection):
    """
    Computes the moment of inertia of the polygon.

    This treats each boundary point as a point-mass of 1.

    Thus, for constant unit mass at each boundary point,
    the MoI of this pointcloud is

    \sum_i d_{i,c}^2

    where c is the centroid of the polygon

    Altman's OS_1 measure, cited in Boyce and Clark (1964), also used in Weaver
    and Hess (1963).
    """
    ga = _cast(collection)
    coords = pygeos.get_coordinates(ga)
    geom_ixs = numpy.repeat(numpy.arange(len(ga)),
                            pygeos.get_num_coordinates(ga))
    centroids = pygeos.get_coordinates(pygeos.centroid(ga))[geom_ixs]
    squared_euclidean = numpy.sum((coords - centroids)**2, axis=1)
    dists = (pandas.DataFrame.from_dict(
        dict(d2=squared_euclidean,
             geom_ix=geom_ixs)).groupby("geom_ix").d2.sum()).values
    return pygeos.area(ga) / numpy.sqrt(2 * dists)
예제 #2
0
def test_set_coords(geoms, count, has_ring, include_z):
    arr_geoms = np.array(geoms, np.object_)
    n = 3 if include_z else 2
    coords = get_coordinates(arr_geoms,
                             include_z=include_z) + np.random.random((1, n))
    new_geoms = set_coordinates(arr_geoms, coords)
    assert_equal(coords, get_coordinates(new_geoms, include_z=include_z))
예제 #3
0
def test_apply(geoms, include_z):
    geoms = np.array(geoms, np.object_)
    coordinates_before = get_coordinates(geoms, include_z=include_z)
    new_geoms = apply(geoms, lambda x: x + 1, include_z=include_z)
    assert new_geoms is not geoms
    coordinates_after = get_coordinates(new_geoms, include_z=include_z)
    assert_allclose(coordinates_before + 1, coordinates_after, equal_nan=True)
예제 #4
0
def test_apply(geoms):
    geoms = np.array(geoms, np.object)
    coordinates_before = get_coordinates(geoms)
    new_geoms = apply(geoms, lambda x: x + 1)
    assert new_geoms is not geoms
    coordinates_after = get_coordinates(new_geoms)
    assert_equal(coordinates_before + 1, coordinates_after)
예제 #5
0
def cut_line_at_points(line, cut_points, tolerance=1e-6):
    """Cut a pygeos line geometry at points.
    If there are no interior points, the original line will be returned.

    Parameters
    ----------
    line : pygeos Linestring
    cut_points : list-like of pygeos Points
        will be projected onto the line; those interior to the line will be
        used to cut the line in to new segments.
    tolerance : float, optional (default: 1e-6)
        minimum distance from endpoints to consider the points interior
        to the line.

    Returns
    -------
    MultiLineStrings (or LineString, if unchanged)
    """
    if not pg.get_type_id(line) == 1:
        raise ValueError("line is not a single linestring")

    vertices = pg.get_point(line, range(pg.get_num_points(line)))
    offsets = pg.line_locate_point(line, vertices)
    cut_offsets = pg.line_locate_point(line, cut_points)
    # only keep those that are interior to the line and ignore those very close
    # to endpoints or beyond endpoints
    cut_offsets = cut_offsets[(cut_offsets > tolerance)
                              & (cut_offsets < offsets[-1] - tolerance)]

    if len(cut_offsets) == 0:
        # nothing to cut, return original
        return line

    # get coordinates of new vertices from the cut points (interpolated onto the line)
    cut_offsets.sort()

    # add in the last coordinate of the line
    cut_offsets = np.append(cut_offsets, offsets[-1])

    # TODO: convert this to a pygos ufunc
    coords = pg.get_coordinates(line)
    cut_coords = pg.get_coordinates(
        pg.line_interpolate_point(line, cut_offsets))
    lines = []
    orig_ix = 0
    for cut_ix in range(len(cut_offsets)):
        offset = cut_offsets[cut_ix]

        segment = []
        if cut_ix > 0:
            segment = [cut_coords[cut_ix - 1]]
        while offsets[orig_ix] < offset:
            segment.append(coords[orig_ix])
            orig_ix += 1

        segment.append(cut_coords[cut_ix])
        lines.append(pg.linestrings(segment))

    return pg.multilinestrings(lines)
예제 #6
0
def test_set_coords(geoms, count, has_ring):
    geoms = np.array(geoms, np.object)
    if has_ring:
        # do not randomize; linearrings / polygons should stay closed
        coords = get_coordinates(geoms) + np.random.random((1, 2))
    else:
        coords = np.random.random((count, 2))
    new_geoms = set_coordinates(geoms, coords)
    assert_equal(coords, get_coordinates(new_geoms))
예제 #7
0
    def get_ring_coords(polygon):
        # outer ring must be reversed to be counterclockwise[::-1]
        coords = [pg.get_coordinates(pg.get_exterior_ring(polygon)).tolist()]
        for i in range(pg.get_num_interior_rings(polygon)):
            # inner rings must be reversed to be clockwise[::-1]
            coords.append(
                pg.get_coordinates(pg.get_interior_ring(polygon, i)).tolist())

        return coords
예제 #8
0
파일: main.py 프로젝트: oknuutti/fppmap
def perspective_projection(df,
                           sc_coords,
                           sc_heading,
                           fov,
                           width,
                           height,
                           debug=False):
    lat, lon, alt = sc_coords
    head, tilt, roll = sc_heading

    crs_cart = CRS.from_string('+proj=cart')
    transformer = Transformer.from_crs(df.crs, crs_cart)

    # cartesian coordinates:
    #   x-axis points from the Earth center to the point of longitude=0, latitude=0
    #   y-axis points from the Earth center to the point of longitude=90, latitude=0
    #   z-axis points to the North pole

    # satellite location in cartesian coords
    sc_pos_v = np.array(transformer.transform(lat, lon, alt))

    # get rotation and projection matrices
    rot_mx = get_rot_mx(lat, lon, head, tilt, roll)
    cam_mx = get_cam_mx(fov, width, height)

    if debug:
        # test with svalbard coords
        sval = np.array(transformer.transform(78.148, 16.043, 520))
        sc_sv = sval - sc_pos_v
        sc_sv_cf = rot_mx.dot(sc_sv) * 1e-3
        sv_im = cam_mx.dot(sc_sv_cf)
        print('svalbard at [km] %s, in image [px]: %s' %
              (sc_sv_cf, sv_im[:2] / sv_im[2]))

    data = df.geometry.values.data
    coords = pygeos.get_coordinates(data,
                                    include_z=True)  # order out: lon, lat
    shape = coords.shape
    fc = coords.flatten()
    fc[np.isnan(fc)] = 0
    coords = fc.reshape(shape)
    loc = transformer.transform(coords[:, 1], coords[:, 0],
                                coords[:, 2])  # order in: lat, lon
    loc = np.stack(loc, axis=1)
    rel_loc = loc - sc_pos_v

    # remove features that are farther away than the horizon
    r = np.linalg.norm(loc[0, :])
    horizon_dist = math.sqrt((r + alt)**2 - r**2)
    mask = np.linalg.norm(rel_loc, axis=1) > horizon_dist
    rel_loc[mask, :] = np.nan

    # rotate and project to image
    img_coords = cam_mx.dot(rot_mx).dot(rel_loc.T).T
    img_coords = img_coords[:, :2] / img_coords[:, 2:]
    new_data = pygeos.set_coordinates(data.copy(), img_coords)
    new_geom = GeoSeries(GeometryArray(new_data),
                         crs=crs_cart,
                         name=df.geometry.name)
    df.geometry = new_geom[new_geom.is_valid]
예제 #9
0
def close_gaps(df, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    """
    geom = df.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return snapped
예제 #10
0
def convert_crs(gdf, current_crs="epsg:4326"):
    """[summary]

    Args:
        gdf ([type]): [description]

    Returns:
        [type]: [description]
    """
    if current_crs == "epsg:4326":
        lat = pygeos.geometry.get_y(pygeos.centroid(gdf['geometry'].iloc[0]))
        lon = pygeos.geometry.get_x(pygeos.centroid(gdf['geometry'].iloc[0]))
        # formula below based on :https://gis.stackexchange.com/a/190209/80697
        approximate_crs = "epsg:" + str(
            int(32700 - np.round((45 + lat) / 90, 0) * 100 +
                np.round((183 + lon) / 6, 0)))
    else:
        approximate_crs = "epsg:4326"

    #from pygeos/issues/95
    geometries = gdf['geometry']
    coords = pygeos.get_coordinates(geometries)
    transformer = pyproj.Transformer.from_crs(current_crs,
                                              approximate_crs,
                                              always_xy=True)
    new_coords = transformer.transform(coords[:, 0], coords[:, 1])
    result = pygeos.set_coordinates(geometries.copy(), np.array(new_coords).T)
    return result, approximate_crs
예제 #11
0
    def _dense_point_array(self, geoms, distance, index):
        """
        geoms - array of pygeos lines
        """
        # interpolate lines to represent them as points for Voronoi
        points = np.empty((0, 2))
        ids = []

        if pygeos.get_type_id(geoms[0]) not in [1, 2, 5]:
            lines = pygeos.boundary(geoms)
        else:
            lines = geoms
        lengths = pygeos.length(lines)
        for ix, line, length in zip(index, lines, lengths):
            if length > distance:  # some polygons might have collapsed
                pts = pygeos.line_interpolate_point(
                    line,
                    np.linspace(0.1,
                                length - 0.1,
                                num=int((length - 0.1) // distance)),
                )  # .1 offset to keep a gap between two segments
                points = np.append(points, pygeos.get_coordinates(pts), axis=0)
                ids += [ix] * len(pts)

        return points, ids
예제 #12
0
def test_get_coords(geoms, x, y, include_z):
    actual = get_coordinates(np.array(geoms, np.object_), include_z=include_z)
    if not include_z:
        expected = np.array([x, y], np.float64).T
    else:
        expected = np.array([x, y, [np.nan] * len(x)], np.float64).T
    assert_equal(actual, expected)
예제 #13
0
def test_get_coords_3d(geoms, x, y, z, include_z):
    actual = get_coordinates(np.array(geoms, np.object_), include_z=include_z)
    if include_z:
        expected = np.array([x, y, z], np.float64).T
    else:
        expected = np.array([x, y], np.float64).T
    assert_equal(actual, expected)
예제 #14
0
파일: network.py 프로젝트: ElcoK/snkit
def add_distances(network):
    #Find crs of current gdf and arbitrary point(lat,lon) for new crs
    current_crs = "epsg:4326"
    #The commented out crs does not work in all cases
    #current_crs = [*network.edges.crs.values()]
    #current_crs = str(current_crs[0])
    print(network.nodes.iloc[0])
    print(network.nodes)
    lat = pygeom.get_y(network.nodes['geometry'].iloc[0])
    lon = pygeom.get_x(network.nodes['geometry'].iloc[0])
    # formula below based on :https://gis.stackexchange.com/a/190209/80697
    approximate_crs = "epsg:" + str(
        int(32700 - np.round((45 + lat) / 90, 0) * 100 +
            np.round((183 + lon) / 6, 0)))
    #from pygeos/issues/95
    geometries = network.edges['geometry']
    coords = pygeos.get_coordinates(geometries)
    transformer = pyproj.Transformer.from_crs(current_crs,
                                              approximate_crs,
                                              always_xy=True)
    new_coords = transformer.transform(coords[:, 0], coords[:, 1])
    result = pygeos.set_coordinates(geometries.copy(), np.array(new_coords).T)
    dist = pygeos.length(result)
    edges = network.edges.copy()
    edges['distance'] = dist
    return Network(nodes=network.nodes, edges=edges)
예제 #15
0
def export_csv(gdf,
               path,
               latlon=False,
               geom=True,
               lat_name='lat',
               lon_name='lot',
               geom_name='geometry',
               column_names=None,
               selection=False,
               virtual=True,
               chunksize=1000000,
               **kwargs):
    """ Writes GeoDataFrame to a CSV spatial file.
    """
    import pandas as pd

    sep = kwargs.pop('delimiter', ',')

    column_names = column_names or gdf.get_column_names(virtual=virtual,
                                                        strings=True)
    dtypes = gdf[column_names].dtypes
    fields = column_names[:]
    if latlon:
        fields.append(lat_name)
        fields.append(lon_name)
    if geom:
        fields.append(geom_name)

    geom_arr = gdf.geometry._geometry
    if selection not in [None, False] or gdf.filtered:
        mask = gdf.evaluate_selection_mask(selection)
        geom_arr = geom_arr.filter(mask)

    for i1, i2, chunks in gdf.evaluate_iterator(column_names,
                                                chunk_size=chunksize,
                                                selection=selection):
        if latlon:
            coordinates = pg.get_coordinates(
                pg.centroid(pg.from_wkb(geom_arr[i1:i2]))).T
            chunks.append(coordinates[0])
            chunks.append(coordinates[1])
        if geom:
            chunks.append(pg.to_wkt(pg.from_wkb(geom_arr[i1:i2])))
        chunk_dict = {col: values for col, values in zip(fields, chunks)}
        chunk_pdf = pd.DataFrame(chunk_dict)

        if i1 == 0:  # Only the 1st chunk should have a header and the rest will be appended
            mode = 'w'
            header = True
        else:
            mode = 'a'
            header = False

        chunk_pdf.to_csv(path_or_buf=path,
                         mode=mode,
                         header=header,
                         sep=sep,
                         index=False,
                         **kwargs)
예제 #16
0
    def transform_geometry(self, geom, rs, max_points=5):
        """Transforms a geometry embedding new points.

        In case geom is (multi)line or (multi)polygon, it adds points collinear to their neighbours, so that an equivalent geometry is generated. The number of extra points depends on the number of vertices in the geometry.

        Arguments:
            geom (pygeos.Geometry): Geometry
            rs (numpy.RandomState): Random State
            max_points (int): Maximum value of extra points.

        Returns:
            (pygeos.Geometry)

        Raises:
            ValueError: When geometry type is not supported.
        """
        type_ = pg.get_type_id(geom)
        if type_ == 1 or type_ == 3:
            # LINESTRING or POLYGON
            vertices = pg.get_coordinates(geom)
            size = min(max_points, math.ceil(len(vertices) / 6))
            vert_ids = rs.randint(1, len(vertices), size)
            vert_ids.sort()
            new = []
            for idx in vert_ids:
                xa, ya = vertices[idx - 1]
                xb, yb = vertices[idx]
                if xa == xb:
                    x = xa
                    y = self._random_float(rs, ya, yb)
                else:
                    x = self._random_float(rs, xa, xb)
                    y = (yb - ya) * (x - xa) / (xb - xa) + ya
                x = _round(x, [xa, xb])
                y = _round(y, [ya, yb])
                new.append((idx, [x, y]))
            offset = 0
            extended = []
            for idx, entry in new:
                extended.extend(vertices[offset:idx])
                extended.append(entry)
                offset = idx
            extended.extend(vertices[offset:])
            extended = np.array(extended)
            result = pg.linestrings(extended) if type_ == 1 else pg.polygons(
                extended)
        elif type_ == 5 or type_ == 6:
            # MULTILINESTRING or MULTIPOLYGON
            parts = pg.get_parts(geom)
            part_idx = rs.randint(0, len(parts))
            parts[part_idx] = self.transform_geometry(parts[part_idx], rs)
            result = pg.multilinestrings(
                parts) if type_ == 5 else pg.multipolygons(parts)
        else:
            raise ValueError(
                'geom should be linestring, polygon, multilinestring, or multipolygon.'
            )

        return result
예제 #17
0
def get_inverted_coordinates(arr):
    def invert_list(a):
        if isinstance(a[0], np.ndarray):
            return np.array([np.flip(array) for array in a])
        else:
            return np.flip(a)

    return invert_list(pg.get_coordinates(pg.from_wkb(arr)))
예제 #18
0
def test_pickle(geom):
    if pygeos.get_type_id(geom) == 2:
        # Linearrings get converted to linestrings
        expected = pygeos.linestrings(pygeos.get_coordinates(geom))
    else:
        expected = geom
    pickled = pickle.dumps(geom)
    assert pygeos.equals_exact(pickle.loads(pickled), expected)
예제 #19
0
def transform(arr, src_crs, tgt_crs):
    transformer = pyproj.Transformer.from_crs(src_crs, tgt_crs, always_xy=True)

    geometry = pg.from_wkb(arr)
    coords = pg.get_coordinates(geometry)
    new_coords = transformer.transform(coords[:, 0], coords[:, 1])
    projected = pg.set_coordinates(geometry, np.array(new_coords).T)
    return pg.to_wkb(projected)
예제 #20
0
 def transform_geoseries(geometry):
     target_crs = pyproj.crs.CRS(target)
     if target_crs == geometry.crs:
         return geometry
     cm.check.crs(target_crs)
     cm.check.crs(geometry.crs)
     transformer = pyproj.Transformer.from_crs(
         geometry.crs, target_crs, always_xy=True)
     if not all(pygeos.has_z(geometry.array.data)):
         coords = pygeos.get_coordinates(
             geometry.array.data, include_z=False)
         new_coords = transformer.transform(coords[:, 0], coords[:, 1])
     else:
         coords = pygeos.get_coordinates(
             geometry.array.data, include_z=True)
         new_coords = transformer.transform(
             coords[:, 0], coords[:, 1], coords[:, 2])
     return pygeos.set_coordinates(geometry.array.data.copy(), np.array(new_coords).T)
예제 #21
0
def convert_point_to_constant_box(input_array, box_size):
    input_array = np.copy(input_array)
    for i in range(input_array.shape[0]):
        x, y = get_coordinates(centroid(input_array[i, 0]))[0]
        input_array[i, 0] = box(x - (box_size / 2),
                                y - (box_size / 2),
                                x + (box_size / 2),
                                y + (box_size / 2))

    return input_array
예제 #22
0
def test_set_coords_mixed_dimension(include_z):
    geoms = np.array([point, point_z], dtype=object)
    coords = get_coordinates(geoms, include_z=include_z)
    new_geoms = set_coordinates(geoms, coords * 2)
    if include_z:
        # preserve original dimensionality
        assert not pygeos.has_z(new_geoms[0])
        assert pygeos.has_z(new_geoms[1])
    else:
        # all 2D
        assert not pygeos.has_z(new_geoms).any()
예제 #23
0
def naive_compute_threshold_distance_similarity_matrix(sorted_detections, ground_truths, threshold):
    """Computes a similarity based on euclidean distance between all pairs of geometries in a naive fashion.

    Args:
        sorted_detections (ndarray, list) : A ndarray of detections stored as:

                * Bounding boxes for a given class where each row is a detection stored as:
                  ``[BoundingBox, confidence]``
                * Polygons for a given class where each row is a detection stored as:
                  ``[Polygon, confidence]``
                * Points for a given class where each row is a detection stored as:
                  ``[Point, confidence]``

        ground_truths (ndarray,list) : A ndarray of ground truth stored as:

            * Bounding boxes for a given class where each row is a ground truth stored as:
              ``[BoundingBox]``
            * Polygons for a given class where each row is a ground truth stored as:
              ``[Polygon]``
            * Points for a given class where each row is a ground truth stored as:
              ``[Point]``

    Returns:
        ndarray : An similarity matrix (#detections, #ground truth)
    """

    # We prepare the distance matrix (#detection, #gt)
    distance_matrix = np.zeros((sorted_detections.shape[0], len(ground_truths)))

    # Naive iterative distance matrix construction (Note: we iterate over the sorted detections)
    for k, ground_truth in enumerate(ground_truths):
        for m, detection in enumerate(sorted_detections):
            detection_x, detection_y = get_coordinates(centroid(detection[0])).T
            ground_truth_x, ground_truth_y = get_coordinates(centroid(ground_truth[0])).T

            if np.absolute(detection_x - ground_truth_x) > threshold \
                    or np.absolute(detection_y - ground_truth_y) > threshold:
                distance_matrix[m, k] = np.inf
            else:
                distance_matrix[m, k] = distance(centroid(detection[0]), centroid(ground_truth[0]))
    return 1 - distance_matrix
예제 #24
0
def close_gaps(gdf, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    Parameters
    ----------
    gdf : GeoDataFrame, GeoSeries
        GeoDataFrame  or GeoSeries containing LineString representation of a network.
    tolerance : float
        nodes within a tolerance will be snapped together

    Returns
    -------
    GeoSeries
    
    See also
    --------
    momepy.extend_lines
    momepy.remove_false_nodes

    """
    geom = gdf.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance / 2)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return gpd.GeoSeries(snapped, crs=gdf.crs)
예제 #25
0
def _extend_line(coords, target, tolerance, snap=True):
    """
    Extends a line geometry to snap on the target within a tolerance.
    """
    if snap:
        extrapolation = _get_extrapolated_line(
            coords[-4:] if len(coords.shape) == 1 else coords[-2:].flatten(),
            tolerance,
        )
        int_idx = target.sindex.query(extrapolation, predicate="intersects")
        intersection = pygeos.intersection(
            target.iloc[int_idx].geometry.values.data, extrapolation)
        if intersection.size > 0:
            if len(intersection) > 1:
                distances = {}
                ix = 0
                for p in intersection:
                    distance = pygeos.distance(p, pygeos.points(coords[-1]))
                    distances[ix] = distance
                    ix = ix + 1
                minimal = min(distances.items(), key=operator.itemgetter(1))[0]
                new_point_coords = pygeos.get_coordinates(
                    intersection[minimal])

            else:
                new_point_coords = pygeos.get_coordinates(intersection[0])
            coo = np.append(coords, new_point_coords)
            new = np.reshape(coo, (int(len(coo) / 2), 2))

            return new
        return coords

    extrapolation = _get_extrapolated_line(
        coords[-4:] if len(coords.shape) == 1 else coords[-2:].flatten(),
        tolerance,
        point=True,
    )
    return np.vstack([coords, extrapolation])
예제 #26
0
def heatmap(pois,
            basemap_provider='OpenStreetMap',
            basemap_name='Mapnik',
            width='100%',
            height='100%',
            radius=10):
    """Generates a heatmap of the input POIs.

    Parameters:
        pois (GeoDataFrame): A POIs GeoDataFrame.
        basemap_provider (string): The basemap provider.
        basemap_name: The basemap itself as named by the provider.
            List and preview of available providers and their basemaps can be found in https://leaflet-extras.github.io/leaflet-providers/preview/
        width (integer or percentage): Width of the map in pixels or percentage (default: 100%).
        height (integer or percentage): Height of the map in pixels or percentage (default: 100%).
        radius (float): Radius of each point of the heatmap (default: 10).

    Returns:
        A Folium Map object displaying the heatmap generated from the POIs.
    """

    # Set the crs to WGS84
    if pois.geometry.crs == 'EPSG:4326':
        pass
    else:
        pois.geometry.to_crs('EPSG:4326')

    # Automatically center the map at the center of the gdf's bounding box
    bb = pois.geometry.total_bounds()
    map_center = pg.get_coordinates(pg.centroid(bb))[0].tolist()

    tiles, attribution, max_zoom = get_provider_info(basemap_provider,
                                                     basemap_name)
    heat_map = folium.Map(location=map_center,
                          tiles=tiles,
                          attr=attribution,
                          max_zoom=max_zoom,
                          width=width,
                          height=height)

    # Automatically set zoom level
    bounds = pg.total_bounds(bb)
    heat_map.fit_bounds(([bounds[1], bounds[0]], [bounds[3], bounds[2]]))

    # List comprehension to make list of lists
    heat_data = pois.geometry.get_coordinates(invert=True)
    # Plot it on the map
    HeatMap(heat_data, radius=radius).add_to(heat_map)

    return heat_map
예제 #27
0
파일: occult.py 프로젝트: vmario89/occult
def occult(lines: LineCollection, tolerance: float) -> LineCollection:
    """
    Remove occulted lines.

    The order of the geometries in 'lines' matters, see example below.

    'tolerance' controls the distance tolerance between the first and last points
    of a geometry to consider it closed.

    Examples:
        $ vpype line 0 0 5 5 rect 2 2 1 1 occult show  # line is occulted by rect

        $ vpype rect 2 2 1 1 line 0 0 5 5 occult show  # line is NOT occulted by rect,
        as the line is drawn after the rectangle.
    """

    line_arr = np.array(
        [pygeos.linestrings(list(zip(line.real, line.imag))) for line in lines]
    )

    for i, line in enumerate(line_arr):
        coords = pygeos.get_coordinates(line)

        if math.hypot(coords[-1, 0] - coords[0, 0], coords[-1, 1] - coords[0, 1]) < tolerance:
            tree = pygeos.STRtree(line_arr[:i])
            p = pygeos.polygons(coords)
            geom_idx = tree.query(p, predicate="intersects")
            line_arr[geom_idx] = pygeos.set_operations.difference(line_arr[geom_idx], p)

    new_lines = LineCollection()
    for geom in line_arr:
        for i in range(pygeos.get_num_geometries(geom)):
            coords = pygeos.get_coordinates(pygeos.get_geometry(geom, i))
            new_lines.append(coords[:, 0] + coords[:, 1] * 1j)

    return new_lines
예제 #28
0
def transform(data, func):
    if compat.USE_PYGEOS:
        coords = pygeos.get_coordinates(data)
        new_coords = func(coords[:, 0], coords[:, 1])
        result = pygeos.set_coordinates(data.copy(), np.array(new_coords).T)
    else:
        from shapely.ops import transform

        n = len(data)
        result = np.empty(n, dtype=object)
        for i in range(n):
            geom = data[i]
            result[i] = geom if _isna(geom) else transform(func, geom)

    return result
예제 #29
0
def second_areal_moment(collection):
    """
    Using equation listed on en.wikipedia.org/Second_Moment_of_area, the second
    moment of area is actually the cross-moment of area between the X and Y
    dimensions:

    I_xy = (1/24)\sum^{i=N}^{i=1} (x_iy_{i+1} + 2*x_iy_i + 2*x_{i+1}y_{i+1} +
    x_{i+1}y_i)(x_iy_i - x_{i+1}y_i)

    where x_i, y_i is the current point and x_{i+1}, y_{i+1} is the next point,
    and where x_{n+1} = x_1, y_{n+1} = 1.

    This relation is known as the:
    - second moment of area
    - moment of inertia of plane area
    - area moment of inertia
    - second area moment

    and is *not* the mass moment of inertia, a property of the distribution of
    mass around a shape.
    """
    ga = _cast(collection)
    result = numpy.zeros(len(ga))
    n_holes_per_geom = pygeos.get_num_interior_rings(ga)
    for i, geometry in enumerate(ga):
        n_holes = n_holes_per_geom[i]
        for hole_ix in range(n_holes):
            hole = pygeos.get_coordinates(pygeos.get_interior_ring(
                ga, hole_ix))
            result[i] -= _second_moa_ring(hole)
        n_parts = pygeos.get_num_geometries(geometry)
        for part in pygeos.get_parts(geometry):
            result[i] += _second_moa_ring(pygeos.get_coordinates(part))
    # must divide everything by 24 and flip if polygon is clockwise.
    signflip = numpy.array([-1, 1])[pygeos.is_ccw(ga).astype(int)]
    return result * (1 / 24) * signflip
예제 #30
0
 def mbr(self):
     """Returns the Minimum Bounding Rectangle.
     Returns:
         (string) The WKT representation of the MBR.
     """
     if not self._has_geometry:
         warnings.warn('DataFrame is not spatial.')
         return None
     total_bounds = self.df.geometry.total_bounds()
     transformer = pyproj.Transformer.from_crs(self.crs,
                                               "EPSG:4326",
                                               always_xy=True)
     coords = pg.get_coordinates(total_bounds)
     new_coords = transformer.transform(coords[:, 0], coords[:, 1])
     transformed = pg.set_coordinates(total_bounds, np.array(new_coords).T)
     return pg.to_wkt(transformed)