fractopo.branches_and_nodes module
Functions for extracting branches and nodes from trace maps.
branches_and_nodes is the main entrypoint.
- fractopo.branches_and_nodes.additional_snapping_func(trace: LineString, idx: int, additional_snapping: list[tuple[int, Point]]) LineString
Insert points into LineStrings to make sure trace abutting trace.
E.g.
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> idx = 0 >>> point = Point(2.25, 0.1) >>> additional_snapping = [ ... (0, point), ... ] >>> additional_snapping_func(trace, idx, additional_snapping).wkt 'LINESTRING (0 0, 1 0, 2 0, 2.25 0.1, 3 0)'
When idx doesn’t match -> no additional snapping
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> idx = 1 >>> point = Point(2.25, 0.1) >>> additional_snapping = [ ... (0, point), ... ] >>> additional_snapping_func(trace, idx, additional_snapping).wkt 'LINESTRING (0 0, 1 0, 2 0, 3 0)'
- fractopo.branches_and_nodes.angle_to_point(point: Point, nearest_point: Point, comparison_point: Point) float
Calculate the angle between two vectors.
Vectors are made from the given points: Both vectors have the same first point, nearest_point, and second point is either point or comparison_point.
Returns angle in degrees.
E.g.
>>> point = Point(1, 1) >>> nearest_point = Point(0, 0) >>> comparison_point = Point(-1, 1) >>> angle_to_point(point, nearest_point, comparison_point) 90.0
>>> point = Point(1, 1) >>> nearest_point = Point(0, 0) >>> comparison_point = Point(-1, 2) >>> angle_to_point(point, nearest_point, comparison_point) 71.56505117707799
- fractopo.branches_and_nodes.determine_branch_identity(number_of_i_nodes: int, number_of_xy_nodes: int, number_of_e_nodes: int) str
Determine the identity of a branch.
Is based on the amount of I-, XY- and E-nodes and returns it as a string.
E.g.
>>> determine_branch_identity(2, 0, 0) 'I - I'
>>> determine_branch_identity(1, 1, 0) 'C - I'
>>> determine_branch_identity(1, 0, 1) 'I - E'
- fractopo.branches_and_nodes.determine_insert_approach(nearest_point_idx: int, trace_point_dists: list[tuple[int, Point, float]], snap_threshold: float, point: Point, nearest_point: Point) tuple[int, bool]
Determine if to insert or replace point.
- fractopo.branches_and_nodes.filter_non_unique_traces(traces: GeoSeries, snap_threshold: float) GeoSeries
Filter out traces that are not unique.
- fractopo.branches_and_nodes.get_branch_identities(branches: GeoSeries, nodes: GeoSeries, node_identities: list, snap_threshold: float) list[str]
Determine the types of branches for a GeoSeries of branches.
i.e. C-C, C-I or I-I, + (C-E, E-E, I-E)
>>> branches = gpd.GeoSeries( ... [ ... LineString([(1, 1), (2, 2)]), ... LineString([(2, 2), (3, 3)]), ... LineString([(3, 0), (2, 2)]), ... LineString([(2, 2), (-2, 5)]), ... ] ... ) >>> nodes = gpd.GeoSeries( ... [ ... Point(2, 2), ... Point(1, 1), ... Point(3, 3), ... Point(3, 0), ... Point(-2, 5), ... ] ... ) >>> node_identities = ["X", "I", "I", "I", "E"] >>> snap_threshold = 0.001 >>> get_branch_identities(branches, nodes, node_identities, snap_threshold) ['C - I', 'C - I', 'C - I', 'C - E']
- fractopo.branches_and_nodes.insert_point_to_linestring(trace: LineString, point: Point, snap_threshold: float) LineString
Insert/modify point to trace LineString.
The point location is determined to fit into the LineString without changing the geometrical order of LineString vertices (which only makes sense if LineString is sublinear.)
TODO: Does not work for 2.5D geometries (Z-coordinates). Z-coordinates will be lost.
E.g.
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> point = Point(1.25, 0.1) >>> insert_point_to_linestring(trace, point, 0.01).wkt 'LINESTRING (0 0, 1 0, 1.25 0.1, 2 0, 3 0)'
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> point = Point(2.25, 0.1) >>> insert_point_to_linestring(trace, point, 0.01).wkt 'LINESTRING (0 0, 1 0, 2 0, 2.25 0.1, 3 0)'
- fractopo.branches_and_nodes.is_endpoint_close_to_boundary(endpoint: Point, areas: list[Polygon | MultiPolygon], snap_threshold: float) bool
Check if endpoint is within snap_threshold of areas boundaries.
- fractopo.branches_and_nodes.node_identities_from_branches(branches: GeoSeries, areas: GeoSeries | GeoDataFrame, snap_threshold: float) tuple[list[Point], list[str]]
Resolve node identities from branch data.
>>> branches_list = [ ... LineString([(0, 0), (1, 1)]), ... LineString([(2, 2), (1, 1)]), ... LineString([(2, 0), (1, 1)]), ... ] >>> area_polygon = Polygon([(-5, -5), (-5, 5), (5, 5), (5, -5)]) >>> branches = gpd.GeoSeries(branches_list) >>> areas = gpd.GeoSeries([area_polygon]) >>> snap_threshold = 0.001 >>> nodes, identities = node_identities_from_branches( ... branches, areas, snap_threshold ... ) >>> [node.wkt for node in nodes] ['POINT (0 0)', 'POINT (1 1)', 'POINT (2 2)', 'POINT (2 0)'] >>> identities ['I', 'Y', 'I', 'I']
- fractopo.branches_and_nodes.node_identity(endpoint: Point, idx: int, areas: GeoSeries | GeoDataFrame, endpoints_geoseries: GeoSeries, endpoints_spatial_index: Any, snap_threshold: float) str
Determine node identity of endpoint.
- fractopo.branches_and_nodes.report_snapping_loop(loops: int, allowed_loops: int)
Report snapping looping.
- fractopo.branches_and_nodes.resolve_trace_candidates(trace: LineString, idx: int, traces_spatial_index, traces: list[LineString], snap_threshold: float) list[LineString]
Resolve spatial index intersection to actual intersection candidates.
- fractopo.branches_and_nodes.simple_snap(trace: LineString, trace_candidates: list[LineString], snap_threshold: float) tuple[LineString, bool]
Modify conditionally trace to snap to any of trace_candidates.
E.g.
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> trace_candidates = ( ... [LineString([(3.0001, -3), (3.0001, 0), (3, 3)])] ... ) >>> snap_threshold = 0.001 >>> snapped = simple_snap(trace, trace_candidates, snap_threshold) >>> snapped[0].wkt, snapped[1] ('LINESTRING (0 0, 1 0, 2 0, 3.0001 0)', True)
Do not snap overlapping.
>>> trace = LineString([(0, 0), (1, 0), (2, 0), (3.0002, 0)]) >>> trace_candidates = ( ... [LineString([(3.0001, -3), (3.0001, 0), (3, 3)])] ... ) >>> snap_threshold = 0.001 >>> snapped = simple_snap(trace, trace_candidates, snap_threshold) >>> snapped[0].wkt, snapped[1] ('LINESTRING (0 0, 1 0, 2 0, 3.0002 0)', False)
- fractopo.branches_and_nodes.snap_others_to_trace(idx: int, trace: LineString, snap_threshold: float, traces: list[LineString], traces_spatial_index: Any, areas: list[Polygon | MultiPolygon] | None, final_allowed_loop: bool = False) tuple[LineString, bool]
Determine whether and how to snap trace to traces.
E.g.
Trace gets new coordinates to snap other traces to it:
>>> idx = 0 >>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> snap_threshold = 0.001 >>> traces = [trace, LineString([(1.5, 3), (1.5, 0.00001)])] >>> traces_spatial_index = gpd.GeoSeries(traces).sindex >>> areas = None >>> snapped = snap_others_to_trace( ... idx, trace, snap_threshold, traces, traces_spatial_index, areas ... ) >>> snapped[0].wkt, snapped[1] ('LINESTRING (0 0, 1 0, 1.5 1e-05, 2 0, 3 0)', True)
Trace itself is not snapped by snap_others_to_trace:
>>> idx = 0 >>> trace = LineString([(0, 0), (1, 0), (2, 0), (3, 0)]) >>> snap_threshold = 0.001 >>> traces = [trace, LineString([(3.0001, -3), (3.0001, 0), (3, 3)])] >>> traces_spatial_index = gpd.GeoSeries(traces).sindex >>> areas = None >>> snapped = snap_others_to_trace( ... idx, trace, snap_threshold, traces, traces_spatial_index, areas ... ) >>> snapped[0].wkt, snapped[1] ('LINESTRING (0 0, 1 0, 2 0, 3 0)', False)
- fractopo.branches_and_nodes.snap_trace_simple(idx: int, trace: LineString, snap_threshold: float, traces: list[LineString], traces_spatial_index: Any, final_allowed_loop: bool = False) tuple[LineString, bool]
Determine whether and how to perform simple snap.
- fractopo.branches_and_nodes.snap_trace_to_another(trace_endpoints: list[Point], another: LineString, snap_threshold: float) tuple[LineString, bool]
Add point to another trace to snap trace to end at another trace.
I.e. modifies and returns another
- fractopo.branches_and_nodes.snap_traces(traces: list[LineString], snap_threshold: float, areas: list[Polygon | MultiPolygon] | None = None, final_allowed_loop=False) tuple[list[LineString], bool]
Snap traces to end exactly at other traces.