示例#1
0
    def _snap_internal_edges(self, lane_to_poly, snap_threshold=2):
        # HACK: Internal edges that have tight curves, when buffered their ends do not
        #       create a tight seam with the connected lanes. This procedure attempts
        #       to remedy that with snapping.
        for lane_id in lane_to_poly:
            lane = self.lane_by_id(lane_id)

            # Only do snapping for internal edge lanes
            if not lane.getEdge().isSpecial():
                continue

            lane_shape = lane_to_poly[lane_id]
            incoming = self.lane_by_id(lane_id).getIncoming()[0]
            incoming_shape = lane_to_poly.get(incoming.getID())
            if incoming_shape:
                lane_shape = Polygon(
                    snap(lane_shape, incoming_shape, snap_threshold))
                lane_to_poly[lane_id] = lane_shape

            outgoing = self.lane_by_id(lane_id).getOutgoing()[0].getToLane()
            outgoing_shape = lane_to_poly.get(outgoing.getID())
            if outgoing_shape:
                lane_shape = Polygon(
                    snap(lane_shape, outgoing_shape, snap_threshold))
                lane_to_poly[lane_id] = lane_shape
示例#2
0
def snap_endpoints(linestring, geom, tol):
    linelist = linestring.coords
    assert len(linelist) == 2
    p0 = snap(Point(linelist[0]), geom, tol)
    p1 = snap(Point(linelist[-1]), geom, tol)  
    #return LineString([Point(p0)] + list(map(Point, linelist[1:-1])) + [Point(pn)])
    return LineString([Point(p0), Point(p1)])
示例#3
0
def make_polygon(things, tolerance=None):
    """
    Constructs a rough-estimate polygon from a list of CGM elements such as
    POLYLINE.

    This is a rough estimate because CIRCULAR_ARC_POINT elements are not
    modeled exactly but instead the start and end points of the arc are used
    to create a straight line.
    """
    if is_area(things):
        return Polygon(things)
    else:
        # Assume this is multiple elements parsed from a CGM file
        lines = []
        for cmd, data in things:
            if cmd == 'POLYLINE':
                lines.append(LineString(data))
            elif cmd == 'CIRCULAR_ARC_POINT':
                lines.append(LineString(data[0], data[2]))

        collection = GeometryCollection(lines)

        # If tolerance is provided create a grid of vertices to snap the lines
        # into
        if tolerance:
            min_x, min_y, max_x, max_y = collection.bounds

            # round the min values down and max values up
            min_x = int(min_x - (min_x % tolerance))
            min_y = int(min_y - (min_y % tolerance))
            max_x = int(max_x + (tolerance - (max_x % tolerance)))
            max_y = int(max_y + (tolerance - (max_y % tolerance)))

            x_range = range(min_x, max_x + 1, tolerance)
            y_range = range(min_y, max_y + 1, tolerance)
            grid_coords = [(i, j) for j in x_range for i in y_range]
            snap_grid = Polygon(grid_coords)

            snapped_collection = snap(collection, snap_grid, tolerance)
            stuff = polygonize_full(snapped_collection)
        else:
            stuff = polygonize_full(collection)

        polygons = []
        for collection in stuff:
            print(collection)
            if collection and isinstance(collection[0], Polygon):
                for poly in collection:
                    plt.plot(*poly.exterior.xy)
                    polygons.append(poly)
            elif collection and tolerance is not None:
                #new_poly = _normalize_lines(collection, tolerance)
                #plt.plot(*new_poly.exterior.xy)
                #polygons.append(new_poly)
                for line in collection:
                    x_list.extend(line.xy[0])
                    y_list.extend(line.xy[1])

        plt.show()
        return polygons
示例#4
0
    def _snap_external_holes(self, lane_to_poly, snap_threshold=2):
        for lane_id in lane_to_poly:
            lane = self.lane_by_id(lane_id)

            # Only do snapping for external edge lane holes
            if lane.getEdge().isSpecial():
                continue

            incoming = self.lane_by_id(lane_id).getIncoming()
            if incoming and incoming[0].getEdge().isSpecial():
                continue

            outgoing = self.lane_by_id(lane_id).getOutgoing()
            if outgoing:
                outgoing_lane = outgoing[0].getToLane()
                if outgoing_lane.getEdge().isSpecial():
                    continue

            lane_shape = lane_to_poly[lane_id]
            for x, y in lane_shape.exterior.coords:
                for nl, dist in self.nearest_lanes(
                    (x, y),
                        max(10, 2 * self._default_lane_width),
                        include_junctions=False,
                ):
                    if (not nl) or (nl and nl.getEdge().isSpecial()):
                        continue
                    nl_shape = lane_to_poly.get(nl.getID())
                    if nl_shape:
                        lane_shape = Polygon(
                            snap(lane_shape, nl_shape, snap_threshold))
            lane_to_poly[lane_id] = lane_shape
示例#5
0
 def best_diagonal(self) -> Optional[LineString]:
     if self.has_holes:
         e = self.source.exterior
         i = min(self.source.interiors, key=lambda i: i.distance(e))
         v1, v2 = sorted(i.coords[:-1],
                         key=lambda x: e.distance(Point(x)))[:2]
         d1 = e.project(Point(v1))
         d2 = e.project(Point(v2))
         e1 = e.interpolate(d1)
         e2 = e.interpolate(d2)
         c1 = cut(e, d1)
         c2 = cut(e, d2)
         if c1 or c2:
             self.source = Polygon(e, self.source.interiors)
         return snap(LineString([e2, v2, v1, e1]), self.source.boundary,
                     0.01)
     while self.cache:
         try:
             _, d, k = min(
                 ((d.length, d, k) for k, d in self.cache.items() if d),
                 key=operator.itemgetter(0))
         except ValueError as e:
             print("!!!!EEEEE!!!!!")
             return None
         if self.source.boundary.covers(d):
             # HACK: should never happend but it does
             del self.cache[k]
         else:
             return d
     return None
示例#6
0
def split_line_by_nearest_points(gdf_line, gdf_points, tolerance, crs):
    """
    Split the union of lines with the union of points resulting

    :param GeoDataFrame gdf_line:  GeoDataFrame with multiple rows of connecting line segments
    :param GeoDataFrame gdf_points: geodataframe with multiple rows of single points

    :returns: ``gdf_segments`` (GeoDataFrame of segments)
    :rtype: GeoDataFrame

    https://github.com/ojdo/python-tools/blob/master/shapelytools.py#L144
    """

    # union all geometries
    line = gdf_line.geometry.unary_union
    line._crs = crs
    snap_points = gdf_points.geometry.unary_union
    snap_points._crs = crs

    # snap and split coords on line
    # returns GeometryCollection
    # snap_points = snap(coords, line, tolerance)
    # snap_points._crs = crs
    split_line = split(line, snap(snap_points, line, tolerance))
    split_line._crs = crs
    segments = [feature for feature in split_line if feature.length > 0.01]

    gdf_segments = gdf(geometry=segments, crs=crs)
    # gdf_segments.columns = ['index', 'geometry']

    return gdf_segments
示例#7
0
def build_travel_edges(shape, fill_angle):
    r"""Given a graph, compute the interior travel edges.

    We want to fill the shape with a grid of line segments that can be used for
    travel stitch routing.  Our goals:

      * not too many edges so that the shortest path algorithm is speedy
      * don't travel in the direction of the fill stitch rows so that the
        travel stitch doesn't visually disrupt the fill stitch pattern

    To do this, we'll fill the shape with three gratings: one at +45 degrees
    from the fill stitch angle, one at -45 degrees, and one at +90 degrees.
    The pattern looks like this:

    /|\|/|\|/|\
    \|/|\|/|\|/
    /|\|/|\|/|\
    \|/|\|/|\|/

    Returns: (endpoints, edges)
        endpoints - the points on travel edges that intersect with the boundary
                    of the shape
        edges     - the line segments we can travel on, as individual LineString
                    instances
    """

    # If the shape is smaller, we'll have less room to maneuver and it's more likely
    # we'll travel around the outside border of the shape.  Counteract that by making
    # the grid denser.
    if shape.area < 10000:
        scale = 0.5
    else:
        scale = 1.0

    grating1 = travel_grating(shape, fill_angle + math.pi / 4,
                              scale * 2 * PIXELS_PER_MM)
    grating2 = travel_grating(shape, fill_angle - math.pi / 4,
                              scale * 2 * PIXELS_PER_MM)
    grating3 = travel_grating(shape, fill_angle - math.pi / 2,
                              scale * math.sqrt(2) * PIXELS_PER_MM)

    debug.add_layer("auto-fill travel")
    debug.log_line_strings(grating1, "grating1")
    debug.log_line_strings(grating2, "grating2")
    debug.log_line_strings(grating3, "grating3")

    endpoints = [
        coord for mls in (grating1, grating2, grating3) for ls in mls
        for coord in ls.coords
    ]

    diagonal_edges = ensure_multi_line_string(
        grating1.symmetric_difference(grating2))

    # without this, floating point inaccuracies prevent the intersection points from lining up perfectly.
    vertical_edges = ensure_multi_line_string(
        snap(grating3.difference(grating1), diagonal_edges, 0.005))

    return endpoints, chain(diagonal_edges, vertical_edges)
示例#8
0
def v_cell_n(n: int, tacke: List[List[float]]):

    pol_U = Polygon()
    for i in range(n):
        pol_i = v_cell(i, tacke)
        pol_i = snap(pol_i, pol_U, 0.01)
        pol_U = pol_U.union(pol_i)
    return pol_U
示例#9
0
def get_split_lines(line: LineString, point: Point) -> List[LineString]:
    """Splits a line at nearest intersecting point.
    Returns:
        A list containing two LineString objects.
    """
    snap_line = snap(line, point, 0.01)
    result = split(snap_line, point)
    if (len(result) < 2):
        print('Error in splitting line at point: only one line in the result')
    return result
示例#10
0
def split_line_at_point(line: LineString, split_point: Point, tolerance: float=0.01) -> List[LineString]:
    """Splits a line at nearest intersecting point.
    Returns:
        A list containing two LineString objects.
    """
    snap_line = snap(line, split_point, tolerance)
    split_lines = split(snap_line, split_point)
    if (len(split_lines) == 1):
        raise ValueError('Split lines to only one line instead of 2 - split point was probably not on the line')
    return split_lines[0], split_lines[1]
示例#11
0
def _find_parallel(_networkX_graph: nx.Graph, _line_start_nd, _line_end_nd,
                   _parallel_nd, _buffer_dist):
    line_geom = _networkX_graph[_line_start_nd][_line_end_nd]['geom']
    p_x = _networkX_graph.nodes[_parallel_nd]['x']
    p_y = _networkX_graph.nodes[_parallel_nd]['y']
    parallel_point = geometry.Point(p_x, p_y)

    # returns tuple of nearest from respective input geom
    # want the nearest point on the line at index 1
    nearest_point = ops.nearest_points(parallel_point, line_geom)[1]

    # check if the distance from the parallel point to the nearest point is within buffer distance
    if parallel_point.distance(nearest_point) > _buffer_dist:
        return None

    # in some cases the line will be pointing away, but is still short enough to be within max
    # in these cases, check that the closest point is not actually the start of the line geom (or very near to it)
    s_x = _networkX_graph.nodes[_line_start_nd]['x']
    s_y = _networkX_graph.nodes[_line_start_nd]['y']
    line_start_point = geometry.Point(s_x, s_y)
    if nearest_point.distance(line_start_point) < 1:
        return None

    # if a valid nearest point has been found, go ahead and split the geom
    # use a snap because rounding precision errors will otherwise cause issues
    split_geoms = ops.split(ops.snap(line_geom, nearest_point, 0.01),
                            nearest_point)
    # if (relatively rare) the split is still not successful
    if len(split_geoms) != 2:
        logger.warning(
            f'Attempt to split line geom for {_line_start_nd}-{_line_end_nd} did not return two geoms: '
            f'{split_geoms}')
        return None
    # otherwise, unpack the geoms
    part_a, part_b = split_geoms
    # generate a new node name by concatenating the source nodes
    new_nd_name = f'{_line_start_nd}_{_line_end_nd}'
    _networkX_graph.add_node(new_nd_name, x=nearest_point.x, y=nearest_point.y)
    _networkX_graph.add_edge(_line_start_nd, new_nd_name)
    _networkX_graph.add_edge(_line_end_nd, new_nd_name)
    if np.allclose((s_x, s_y), part_a.coords[0][:2], atol=0.001, rtol=0) or \
            np.allclose((s_x, s_y), part_a.coords[-1][:2], atol=0.001, rtol=0):
        _networkX_graph[_line_start_nd][new_nd_name]['geom'] = part_a
        _networkX_graph[_line_end_nd][new_nd_name]['geom'] = part_b
    else:
        # double check matching geoms
        if not np.allclose((s_x, s_y), part_b.coords[0][:2], atol=0.001, rtol=0) and \
                not np.allclose((s_x, s_y), part_b.coords[-1][:2], atol=0.001, rtol=0):
            raise ValueError('Unable to match split geoms to existing nodes')
        _networkX_graph[_line_start_nd][new_nd_name]['geom'] = part_b
        _networkX_graph[_line_end_nd][new_nd_name]['geom'] = part_a

    # the existing edge should be removed later to avoid in-place errors during loop cycle
    # also return the parallel point and the newly paired parallel node
    return (_line_start_nd, _line_end_nd), (_parallel_nd, new_nd_name)
def snap_shapely_geometries(geom_list, tolerance):
    for i in range(len(geom_list)):
        geom = geom_list[i]
        for j in range(len(geom_list)):
            target_geom = geom_list[j]
            if target_geom != geom:
                nearest = nearest_points(geom, target_geom)
                if nearest[0].distance(nearest[1]) <= tolerance:
                    snapped = snap(geom, target_geom, tolerance)
                    geom = snapped
                    geom_list[i] = snapped
示例#13
0
def make_bridge_profile(brug, legger):
    logging.info(f'Begin bridge profile for {brug["CODE"]}')
    line = []
    buffer_size = 0
    while len(line) is 0:
        buffer_size += 0.5
        line = legger[legger.geometry.intersects(brug.geometry.buffer(buffer_size))]
        if buffer_size > 5:
            logging.info(f'No waterline found, skipped bridge: {brug["CODE"]}')
            return None, None
    line = line.iloc[0]
    snapped = snap(brug.geometry, line.geometry, 1)
    dist_normalized = line.geometry.project(snapped, normalized=True)
    bottom = line['WS_BH_BOVENSTROOMS_L'] - dist_normalized * (line['WS_BH_BOVENSTROOMS_L']-line['WS_BH_BENEDENSTROOMS_L'])
    geom_length = line.geometry.length
    dist = dist_normalized * geom_length
    if dist + 5 < geom_length:
        help_dist = dist + 5
    else:
        help_dist = dist - 5
    height = brug['HOOGTEONDE'] - bottom
    if height < 0.1:
        height = 2
    xyz = _make_xyz(row=line, distance_main=dist, distance_help=help_dist,
                    bottom_level=bottom, bottom_width=brug['WS_DOORSTR'],
                    talud_l=0.01, talud_r=0.01, total_depth = height)
    logging.info(f'Made XYZ: {xyz.wkt}')
    new_points = gpd.GeoDataFrame()
    for i in range(len(list(xyz.coords))):
        new = gpd.GeoDataFrame(geometry=[Point(list(xyz.coords)[i])],
                               data={'code': [f"{brug['CODE']}_{i + 1}"],
                                     'codeVolgnummer': [i + 1],
                                     'ProfielCode': [f'{brug["CODE"]}'],
                                     'TypeProfielCode': [3],
                                     'RuwheidsTypeCode': [4],
                                     'RuwheidsWaardeLaag': [75],
                                     'RuwheidsWaardeHoog': [75]},
                               crs='EPSG:28992')
        new_points = new_points.append(new)
    logging.info('Made Bridge DWP')
    brug_hydamo = gpd.GeoDataFrame(geometry=[brug.geometry],
                                   data={'code': brug['CODE'],
                                         'hoogteonderzijde': [brug['HOOGTEONDE']],
                                         'dwarsprofielcode': [f"{brug['CODE']}"],
                                         'lengte': [brug['WS_DOORS_1']],
                                         'ruwheidstypecode': [4],
                                         'RuwheidsWaarde': [75],
                                         'intreeverlies': [0],
                                         'uittreeverlies': [0]},
                                   crs='EPSG:28992')
    logging.info('Made Bridge Hydamo')
    return new_points, brug_hydamo
示例#14
0
 def add_to_cache(self, p: Point2D, a: Point2D, b: Point2D) -> None:
     if self.visible(p, a) and self.visible(p, b):
         edge = LineString([a, b])
         p1 = edge.interpolate(edge.project(Point(p)))
         # e = self.source.exterior
         # d1 = e.project(p1)
         # if cut(e, d1):
         #     self.source = Polygon(e, self.source.interiors)
         diagonal = snap(LineString((p, p1)), self.source, 0.01)
     else:
         diagonal = None
     if diagonal:
         self.nr_vertices.add(p)
     self.cache[(p, a, b)] = diagonal
示例#15
0
 def split_track(self, track, point):
     # Snap Point
     new_track  = ops.snap(track, point, snap_tolerance)
     
     while not new_track.contains(point):
         if new_track.project(point) == 0:
             # The split has a tolerance issue with the prior track.
             # We therefore create a new mini-trail, and let the old
             # trail be carried forward.
             print("Making mini segment at %s" % str(point))
             point = new_track.interpolate(snap_tolerance*1.1)
         # Use the nearest point functionality to try and estimate a suitable node point on the line
         point, __ = ops.nearest_points(track, point)
         new_track = ops.snap(track, point, snap_tolerance)
         if not new_track.contains(point):
             raise Exception("Unable to snap %s to track at %f" % (str(point),snap_tolerance))
         
     result = ops.split(new_track, point)
     
     if len(result) == 1:
         return(result[0], None)
         
     return (result[0], result[1])
示例#16
0
def split(AA, BB):
    A = deepcopy(AA)
    B = deepcopy(BB)
    """Splits A and B into A-B, A inter B, and B-A"""
    if (not A) or (not B):
        return (A, None, B)
    try:
        AmB = A.difference(B)
        AiB = A.intersection(B)
        BmA = B.difference(A)
    except:
        nA = snap(A, B, 1e-3)
        AmB = nA.difference(B)
        AiB = nA.intersection(B)
        BmA = B.difference(nA)
    return (polOnly(AmB), polOnly(AiB), polOnly(BmA))
示例#17
0
    def split_line(line, pps):
        """Split 'line' by all intersecting 'pps' (as multipoint).
        Returns:
            new_lines (list): a list of all line segments after the split
        """
        # IMPORTANT FIX for ensuring intersection between splitters and the line
        # but no need for updating edges_meter manually because the old lines will be
        # replaced anyway
        line = snap(line, pps, 1e-8)  # slow?

        try:
            new_lines = list(split(line, pps))  # split into segments
            return new_lines
        except TypeError as e:
            print('Error when splitting line: {}\n{}\n{}\n'.format(
                e, line, pps))
            return []
示例#18
0
    def test_snap(self):
        
        # input geometries
        square = Polygon([(1,1), (2, 1), (2, 2), (1, 2), (1, 1)])
        line = LineString([(0,0), (0.8, 0.8), (1.8, 0.95), (2.6, 0.5)])
                
        square_coords = square.exterior.coords[:]
        line_coords = line.coords[:]

        result = snap(line, square, 0.5)

        # test result is correct
        self.assertTrue(isinstance(result, LineString))
        self.assertEqual(result.coords[:], [(0.0, 0.0), (1.0, 1.0), (2.0, 1.0), (2.6, 0.5)])
        
        # test inputs have not been modified
        self.assertEqual(square.exterior.coords[:], square_coords)
        self.assertEqual(line.coords[:], line_coords)
示例#19
0
 def split(self, diagonal: LineString) -> Tuple['APolygon', 'APolygon']:
     try:
         left, right = split(self.source, diagonal)
     except ValueError:
         diagonal1 = snap(scale(diagonal,
                                1.01,
                                1.01,
                                1.01,
                                origin=diagonal.coords[0]),
                          self.source,
                          tolerance=0.01)
         try:
             left, right = split(self.source, diagonal1)
         except ValueError as e:
             print(self.source.wkt)
             print(diagonal1.wkt)
             raise e
     return (APolygon(left, parent=self), APolygon(right, parent=self))
示例#20
0
    def test_snap(self):

        # input geometries
        square = Polygon([(1, 1), (2, 1), (2, 2), (1, 2), (1, 1)])
        line = LineString([(0, 0), (0.8, 0.8), (1.8, 0.95), (2.6, 0.5)])

        square_coords = square.exterior.coords[:]
        line_coords = line.coords[:]

        result = snap(line, square, 0.5)

        # test result is correct
        self.assertTrue(isinstance(result, LineString))
        self.assertEqual(result.coords[:], [(0.0, 0.0), (1.0, 1.0), (2.0, 1.0),
                                            (2.6, 0.5)])

        # test inputs have not been modified
        self.assertEqual(square.exterior.coords[:], square_coords)
        self.assertEqual(line.coords[:], line_coords)
def split_line_at_point(line: LineString,
                        split_point: Point,
                        tolerance: float = 0.01) -> List[LineString]:
    """Splits a line at nearest intersecting point.
    Returns:
        A list containing two LineString objects.
    """
    # try with many snapping distances as sometimes this fails to split line into two parts
    for snap_dist in (tolerance, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001,
                      0.00000001):
        snap_line = snap(line, split_point, snap_dist)
        split_lines = split(snap_line, split_point)
        if len(split_lines) > 1:
            break
    if len(split_lines) == 1:
        raise ValueError(
            'Split lines to only one line instead of 2 - split point was probably not on the line'
        )

    return split_lines[0], split_lines[1]
示例#22
0
    def _snap_internal_holes(self, lane_to_poly, snap_threshold=2):
        for lane_id in lane_to_poly:
            lane = self.lane_by_id(lane_id)

            # Only do snapping for internal edge lane holes
            if not lane.getEdge().isSpecial():
                continue
            lane_shape = lane_to_poly[lane_id]
            for x, y in lane_shape.exterior.coords:
                for nl, dist in self.nearest_lanes(
                    (x, y),
                        max(10, 2 * self._default_lane_width),
                        include_junctions=False,
                ):
                    if not nl:
                        continue
                    nl_shape = lane_to_poly.get(nl.getID())
                    if nl_shape:
                        lane_shape = Polygon(
                            snap(lane_shape, nl_shape, snap_threshold))
            lane_to_poly[lane_id] = lane_shape
示例#23
0
def polygon_split(polygon=[], splitLine=[]):
    """Split a polygon into two other polygons along splitLine. This is a wrapper for
	    Shapely split function.

	Attempts to split a polygon into two other polygons.

	Args:
		polygon: Shapely polygon object.
		splitLine: Shapely LineString object.

	Returns:
		(P1, P2): A tuple of Shapely polygons resulted from the split. If error occured,
		returns [].

	"""

    if not splitLine or not polygon or not polygon.is_valid or len(
            splitLine.coords) != 2:
        return []

    # There is a bazilion ways that the inputs can cause a failure of this method. Rather then
    # spending all of this effort in checking the inputs, I decided to avoid inputs checking and
    # wrap the core algorithm in a try-catch block and only check the validity of the output.
    try:

        snapped = snap(splitLine, polygon.exterior, SNAP_TOLLERANCE)
        result = split(polygon, snapped)

        # Only allow cuts that generate 2 polygons. TODO: Check types of resulting geometries.
        if len(result) == 2:
            return result
        else:
            return []

    except:
        logger.debug(
            "Split was not succseful. Check the validity of the inputs.")
        return []
示例#24
0
def snap_ends(gdf, tolerance, digits=None):
    """Snap all end-vertices within a specified tolerance."""
    sindex = gdf.sindex
    snapped = []
    for index, row in gdf.iterrows():
        # rough selection on index
        buffer_geom = row['geometry'].buffer(tolerance)
        # precise selection on distance < tolerance
        gdf_selec = gdf.iloc[list(sindex.intersection(buffer_geom.bounds))].copy()
        gdf_selec['distance'] = gdf_selec.distance(row['geometry'])
        gdf_selec = gdf_selec.loc[gdf_selec['distance'] < tolerance]
        # only snap to features that will not be modified
        gdf_selec = gdf_selec.loc[gdf_selec.index.isin(snapped)]
        # snapping to remaining objects
        geom = row['geometry']
        # round digits (optionally)
        if digits:
            geom = LineString([[round(coord, ndigits=digits) for
                               coord in coords] for coords in geom.coords])

        if not gdf_selec.empty:
            geom_coords = list(geom.coords)

            for _, row_selec in gdf_selec.iterrows():
                for dst_vert in [0, -1]:
                    for src_vert in [0, -1]:
                        geom_coords[dst_vert] = snap(
                            Point(geom_coords[dst_vert]),
                            Point(row_selec['geometry'].coords[src_vert]),
                            tolerance=1).coords[0]
            geom = LineString(geom_coords)
        # write feature in original GeoDataFrame
        gdf.loc[index, 'geometry'] = geom
        # mark index as snapped
        snapped += [index]

    return gdf
示例#25
0
    def check_track(self, track):
        """
        Sometime track GPX files are effectively doubled -- tracks are there and back,
        rather than just 1-way segments.  This method returns only the 1-way segment
        for the track
        """
        mp = track.length / 2
        mp = Point(track.interpolate(mp))
        new_track = ops.snap(track, mp, snap_tolerance)
        if not new_track.contains(mp):
            print("Unable to snap track")
            return track
        result = ops.split(new_track, mp)

        result[0].intersects(result[1])
        isect = result[0].intersection(result[1])

        if isect.type == "Point":
            return track

        if len(isect) / (len(result[0].coords) - 1) > .5:
            return result[0]
        else:
            return track
示例#26
0
def get_raindropPath(flw, projected_xy, nhdFlowline, flowlines,
                     transformToRaster, transformToWGS84):

    # Convert the flowlines to a geopandas dataframe

    linestringlist = []
    for pair in flowlines['features'][0]['geometry']['coordinates'][0]:
        linestringlist.append((pair[0], pair[1]))

    linestring = LineString(linestringlist)

    # Project the flowlines to the same crs as the flw raster
    projectedNHD = transform_geom(transformToRaster,
                                  linestring)  # dfNHD.geometry[0][0]

    # Convert the flowline coordinates to a format that can be iterated
    line = list(projectedNHD.coords)
    print('created list of nhd coords  ')

    # Loop thru the flowline coordinates, grab the xy coordinantes and put them in separate lists.
    # Use these lists in the index function of pyflwdir to grap the ids of the cell in which these points fall
    # lastID = len(line) - 1
    xlist = []
    ylist = []
    nhdCellList = []
    for i in line:
        # if i == line[lastID]:    # Pass the last point in the flowline. Sometimes this point is outside of
        #     pass                 # the flw raster and this will cause flw.index() to fail.
        # if i != line[lastID]:
        xlist = (i[0])
        ylist = (i[1])
        cellIndex = flw.index(xlist, ylist)
        nhdCellList.append(cellIndex)
    print('nhd converted to raster  ')

    # create mask from in the same of the flw raster
    nhdMask = np.zeros(flw.shape, dtype=bool)

    # Set the flowline cells to true
    nhdMask.flat[nhdCellList] = True

    # trace downstream
    path, dist = flw.path(xy=projected_xy, mask=nhdMask)

    # get points on raindropPath
    pathPoints = flw.xy(path)

    # loop thru the downstream path points and create a dict of coords
    lastPointID = pathPoints[0][0].size - 1
    i = 0
    coordlist = {'type': 'LineString', 'coordinates': []}
    while i <= lastPointID:
        x = pathPoints[0][0][i]
        y = pathPoints[1][0][i]
        coordlist['coordinates'].append([x, y])
        i += 1

    if len(coordlist['coordinates']) < 2:
        print('Failed to trace raindrop path! Try another point. ')
    if len(coordlist['coordinates']) >= 2:
        print('traced raindrop path   ')

    # Convert the dict of coords to ogr geom
    pathGeom = GeometryCollection([shape(coordlist)])

    # Project the ogr geom to WGS84
    projectedPathGeom = transform(transformToWGS84, pathGeom)

    # Snap raindropPath points to the flowline within a ~35m buffer
    snapPath = snap(projectedPathGeom[0], nhdFlowline, .00045)

    # Convert snapPath to a geometry collection
    snapPath = GeometryCollection([snapPath])

    # Grap all the points of intersection between the raindropPath and the flowline
    intersectionpoints = nhdFlowline.intersection(snapPath)

    # Filter the intersecting points by geometry type. The downstream path
    # will then be split by each point in the intersectionpoints geom.
    if type(intersectionpoints) == shapely.geometry.multipoint.MultiPoint:
        for i in intersectionpoints:
            splitPoint = snap(Point(i.coords), snapPath, .0002)
            snapPath = split(snapPath[0], splitPoint)
    if type(intersectionpoints) == shapely.geometry.linestring.LineString:
        for i in intersectionpoints.coords:
            splitPoint = snap(Point(i), snapPath, .0002)
            snapPath = split(snapPath[0], splitPoint)
    if type(intersectionpoints) == shapely.geometry.point.Point:
        splitPoint = snap(intersectionpoints, snapPath, .0002)
        snapPath = split(snapPath[0], splitPoint)
    if type(intersectionpoints
            ) == shapely.geometry.multilinestring.MultiLineString or type(
                intersectionpoints
            ) == shapely.geometry.collection.GeometryCollection:
        for i in intersectionpoints:
            for j in i.coords:
                splitPoint = snap(Point(j), snapPath, .0002)
                snapPath = split(snapPath[0], splitPoint)

    # The first linestring in the snapPath geometry collection in the raindropPath
    raindropPath = snapPath[0]

    return raindropPath
示例#27
0
def test_problem_geometry():
    extents = box((-445.140000, -132.380000), (445.140000, 160.910000))
    extents = geo.Polygon(extents)
    layers = tuple(
        draw((-103.900000, -6.380000),
             dxdy=(
                 (103.140000 - -103.900000, 0),
                 (270.430000 - 103.140000, 160.910000 - -6.380000),
                 (-271.190000 - 270.430000, 0),
             )))
    layers_p = geo.Polygon(layers)
    select_backfill = geo.Polygon(
        box((-103.900000, -6.380000), (103.140000, 142.910000)))
    insitu = extents.difference(layers_p)
    other_backfill = layers_p.difference(select_backfill)

    mat_seq = (insitu, other_backfill, select_backfill)
    geo.MultiPolygon(mat_seq)

    layer_strings = (
        ((-1000, 0.100000), (-103.900000, 0.100000), (-67.900000, 0.100000),
         (-67.900000, 9.310000), (-57.170000, 0.100000), (-45.890000,
                                                          0.130000),
         (-34.610000, 0.120000), (-23.330000, 0.110000), (-12.050000,
                                                          0.060000), (0, 0),
         (10.520000, -0.050000), (21.800000, -0.100000), (33.080000,
                                                          -0.160000),
         (44.360000, -0.260000), (55.640000, -0.380000), (66.630000, 8.790000),
         (66.630000, -0.380000), (103.140000, -0.380000), (1000, -0.380000)),
        ((-1000, 12.100000), (-103.900000, 12.100000), (-82.900000, 12.100000),
         (-67.900000, 9.310000), (66.630000, 8.790000), (81.630000, 11.620000),
         (103.140000, 11.620000), (1000, 11.620000)),
        ((-1000, 24.100000), (-103.900000, 24.100000), (-67.650000, 24.100000),
         (66.620000, 23.620000), (103.140000, 23.620000), (1000, 23.620000)),
        ((-1000, 36.100000), (-103.900000, 36.100000), (-67.430000, 36.100000),
         (66.650000, 35.620000), (103.140000, 35.620000), (1000, 35.620000)),
        ((-1000, 48.100000), (-103.900000, 48.100000), (-67.290000, 48.100000),
         (66.680000, 47.620000), (103.140000, 47.620000), (1000, 47.620000)),
        ((-1000, 60.100000), (-103.900000, 60.100000), (-67.130000, 60.100000),
         (66.730000, 59.620000), (103.140000, 59.620000), (1000, 59.620000)),
        ((-1000, 72.100000), (-103.900000, 72.100000), (-66.960000, 72.100000),
         (66.800000, 71.620000), (103.140000, 71.620000), (1000, 71.620000)),
        ((-1000, 84.100000), (-103.900000, 84.100000), (-66.750000, 84.100000),
         (66.860000, 83.620000), (103.140000, 83.620000), (1000, 83.620000)),
        ((-1000, 96.100000), (-103.900000, 96.100000), (-66.550000, 96.100000),
         (66.920000, 95.620000), (103.140000, 95.620000), (1000, 95.620000)),
        ((-1000, 108.100000), (-103.900000, 108.100000),
         (-66.420000, 108.100000), (67.010000, 107.620000),
         (103.140000, 107.620000), (1000, 107.620000)),
        ((-1000, 122.230000), (-103.900000, 122.230000),
         (-82.900000, 122.230000), (-66.360000, 121.850000),
         (67.140000, 120.970000), (81.630000, 119.620000),
         (103.140000, 119.620000), (1000, 119.620000)),
        ((-1000, 130.910000), (-103.900000, 130.910000),
         (-55.400000, 130.910000), (-44.240000, 130.600000),
         (-33.070000, 130.310000), (-21.900000, 130.070000),
         (-10.730000, 129.920000), (0, 129.810000), (11.600000, 129.740000),
         (22.770000, 129.770000), (33.940000, 129.840000), (45.110000,
                                                            129.950000),
         (56.280000, 130.120000), (103.140000, 130.120000), (1000,
                                                             130.120000)),
        ((-1000, 142.910000), (-103.900000, 142.910000), (0, 142.910000),
         (103.140000, 142.910000), (1000, 142.910000)),
        ((-1000, 151.910000), (-103.900000, 151.910000), (0, 151.910000),
         (103.140000, 151.910000), (1000, 151.910000)),
    )

    split_polygons = [layers_p]
    layer_strings = geo.MultiLineString(
        [geo.LineString(l) for l in layer_strings])
    geo.GeometryCollection(
        [layer_strings, insitu, other_backfill, select_backfill])

    layer_multi_polygons = []
    for layer_string in (geo.LineString(l) for l in layer_strings):
        lhs = []
        rhs = []
        for split_polygon in split_polygons:
            layer_string = ops.snap(layer_string, split_polygon, 0.1)
            left, right = splitLR(split_polygon, layer_string)
            lhs.extend(list(left))
            rhs.extend(list(right))
        split_polygons = lhs
        layer_multi_polygons.append(geo.MultiPolygon(rhs))
    layer_multi_polygons.append(geo.MultiPolygon(lhs))
    layer1 = insitu.union(layer_multi_polygons[0])
    layer1 = layer1 if hasattr(layer1, "__iter__") else geo.MultiPolygon(
        [layer1])
    layer_multi_polygons = [layer1, *layer_multi_polygons[1:]]
    geo.MultiPolygon([p for p_set in layer_multi_polygons for p in p_set])

    assert len(layer_multi_polygons) == 15
示例#28
0
    dump(door, f)

with open(outputpath + fpnumber + '/' + fpnumber + '_wall.geojson') as f:
    wall_v = gj.load(f)
wall_vecs = [
    wall_v['features'][i]['geometry'] for i in range(len(wall_v['features']))
]  #geojson obj
wall_vecs = [shape(wall_vecs[i]) for i in range(len(wall_vecs))]  #shapely obj
wall_lines = sp.ops.linemerge(wall_vecs)
# wall_poly = sp.ops.polygonize(wall_lines)

ksk = []
for i in range(len(door_line)):
    kiki = []
    for j in range(len(wall_lines)):  #여기 수정이 필요할듯
        new_door_line = snap(door_line[i], wall_lines[j],
                             tolerance=2)  #벽 라인에 대해서 문 라인을 스냅핑
        if door_line[i] == new_door_line:
            continue
        else:
            kiki.append(new_door_line)
    ksk.append(kiki)

new_door_gj = []  #폐합하는 door
for i in range(len(ksk)):
    for j in range(len(ksk[i])):
        new_door_gj.append(Feature(geometry=ksk[i][j], properties={}))

new_door = FeatureCollection(new_door_gj)
with open(outputpath + fpnumber + '/' + fpnumber + '_door_new_line.geojson',
          'w') as f:
    dump(new_door, f)
示例#29
0
def split_polygon(polygon: Polygon, line: LineString) -> List[Polygon]:
    line = snap(line, polygon, 0.1)
    return sum([g(x) for x in split(polygon, line)], [])
示例#30
0
def intersection(g1: BaseGeometry, g2: BaseGeometry, tolerance: float = 0.1) -> BaseGeometry:
    return snap(g2, g1, tolerance=0.1).intersection(g1)
示例#31
0
print(LineString(coords).crosses(LineString([(0, 1), (1, 0)])))
print(LineString(coords).crosses(LineString([(0, 0), (0.5, 0.5)])))
# is_simple 如果功能本身不交叉,则返回 true
print(LineString([(0, 0), (1, 1), (1, -1), (0, 1)]).is_simple)

print("---------------Polygon-----------------")
polygon = Polygon([(0, 0), (0, 2), (2, 2), (2, 0)])
print(polygon.area)
print(polygon.length)
# bounds 边界框 (最小、最小、最大、最大)元组
print(polygon.bounds)
# 组件 环, exterior 外部、 interiors 内部
print(list(polygon.exterior.coords))
print(list(polygon.interiors))

print("---------------snap-----------------")
square = Polygon([(1, 1), (2, 1), (2, 2), (1, 2), (1, 1)])
line = LineString([(0, 0), (0.8, 0.8), (1.8, 0.95), (2.6, 0.5)])
result = snap(line, square, 0.5)
print(result.wkt)

# 未成功测试, substring
# line = LineString(([0, 0], [2, 0]))
# result = substring(line, 0.5, 0.6)
# print(result.wkt)

print("---------------geos-----------------")
print("shapely version : ", shapely.__version__)
print("shapely geos version : ", shapely.geos.geos_version)
print("shapely geos version string : ", shapely.geos.geos_version_string)