def determine_nodes_intersecting_sets( trace_series_two_sets: Tuple[gpd.GeoSeries, gpd.GeoSeries], set_names_two_sets: Tuple[str, str], node_series_xy: gpd.GeoSeries, buffer_value: float, ) -> List[bool]: """ Conduct a spatial intersect between nodes and traces. Node GeoDataFrame contains only X- and Y-nodes and the trace GeoDataFrame only two sets. Returns boolean array of based on intersections. E.g. >>> traces = gpd.GeoSeries([LineString([(0, 0), (1, 1)])]), gpd.GeoSeries( ... [LineString([(0, 1), (0, -1)])] ... ) >>> set_names_two_sets = ("1", "2") >>> nodes_xy = gpd.GeoSeries([Point(0, 0), Point(1, 1), Point(0, 1), Point(0, -1)]) >>> buffer_value = 0.001 >>> determine_nodes_intersecting_sets( ... traces, set_names_two_sets, nodes_xy, buffer_value ... ) [True, False, False, False] """ def _intersects_both( point: Point, prep_traces_first: prepared.PreparedGeometry, prep_traces_second: prepared.PreparedGeometry, buffer_value: float, ): return prep_traces_first.intersects( point.buffer(buffer_value)) and prep_traces_second.intersects( point.buffer(buffer_value)) assert len(set_names_two_sets) == 2 trace_series_first_set = trace_series_two_sets[0] trace_series_second_set = trace_series_two_sets[1] prep_traces_first = prepare_geometry_traces(trace_series_first_set) prep_traces_second = prepare_geometry_traces(trace_series_second_set) intersects_both_sets = [ _intersects_both(point, prep_traces_first, prep_traces_second, buffer_value=buffer_value) for point in node_series_xy.geometry.values ] return intersects_both_sets
def test_prepare_geometry_traces(trace_series: gpd.GeoSeries): """ Test prepare_geometry_traces. """ prepared_traces = prepare_geometry_traces(trace_series) assert isinstance(prepared_traces, PreparedGeometry) assert isinstance(prepared_traces.context, MultiLineString) assert all( [prepared_traces.intersects(trace) for trace in trace_series.geometry.values] )
def determine_intersects( trace_series_two_sets: Tuple[gpd.GeoSeries, gpd.GeoSeries], set_names_two_sets: Tuple[str, str], node_series_xy_intersects: gpd.GeoSeries, node_types_xy_intersects: np.ndarray, buffer_value: float, ) -> pd.DataFrame: """ Determine how abutments and crosscuts occur between two sets. E.g. >>> traces = gpd.GeoSeries([LineString([(0, 0), (1, 1)])]), gpd.GeoSeries( ... [LineString([(0, 1), (0, -1)])] ... ) >>> set_names_two_sets = ("1", "2") >>> node_series_xy_intersects = gpd.GeoSeries([Point(0, 0)]) >>> node_types_xy_intersects = np.array(["Y"]) >>> buffer_value = 0.001 >>> determine_intersects( ... traces, ... set_names_two_sets, ... node_series_xy_intersects, ... node_types_xy_intersects, ... buffer_value, ... ) node nodeclass sets error 0 POINT (0 0) Y (1, 2) False """ # TODO: No DataFrames -> Refactor to something else # TODO: Refactor intersect logic (but it works for now) intersectframe = pd.DataFrame( columns=["node", "nodeclass", "sets", "error"]) if len(node_series_xy_intersects) == 0: # No intersections between sets logging.debug("No intersections between sets.") return intersectframe first_set, second_set = ( set_names_two_sets[0], set_names_two_sets[1], ) # sets for comparison trace_series_first_set = trace_series_two_sets[0] trace_series_second_set = trace_series_two_sets[1] first_set_prep = prepare_geometry_traces(trace_series_first_set) second_set_prep = prepare_geometry_traces(trace_series_second_set) # Creates a rtree from all start- and endpoints of set 1 # Used in deducting in which set a trace abuts (Y-node) first_set_points = list( chain(*list( trace_series_first_set.geometry.apply( get_trace_endpoints).values))) assert all(isinstance(p, Point) for p in first_set_points) first_setpointtree = STRtree(first_set_points) node: Point node_class: str for node, node_class in zip(node_series_xy_intersects, node_types_xy_intersects): assert isinstance(node, Point) assert isinstance(node_class, str) # for idx, row in intersecting_nodes_frame.iterrows(): # node = row.geometry # c = row.c l1 = first_set_prep.intersects(node.buffer( buffer_value)) # Checks if node intersects set 1 traces. l2 = second_set_prep.intersects(node.buffer( buffer_value)) # Checks if node intersects set 2 traces. if (l1 is False) and (l2 is False): # DEBUGGING raise ValueError( f"Node {node} does not intersect both sets" f" {first_set} and {second_set}\n l1 is {l1} and l2 is {l2}") try: addition = determine_intersect( node=node, node_class=node_class, l1=l1, l2=l2, first_set=first_set, second_set=second_set, first_setpointtree=first_setpointtree, buffer_value=buffer_value, ) except ValueError: # NO RELATIONS FOR NODE IS GIVEN AS ERROR == TRUE (ERROR). # addition gets overwritten if there are no errors addition = { "node": node, "nodeclass": node_class, "sets": set_names_two_sets, "error": True, } # DEBUGGING intersectframe = intersectframe.append( addition, ignore_index=True) # Append frame with result return intersectframe