Skip to content

AbstractUgrid.intersect_linestring cannot intersect with multiple disconnected linestrings #359

@JoerivanEngelen

Description

@JoerivanEngelen

I was a bit confused with the AbstractUgrid.intersect_linestring method. The docstring mentions it is to "Intersect linestrings" (plural). Looking at the code and the method name, it is to intersect with a single linestring.

I was trying to intersect multiple cross-sections linestrings with a network, and ran into the problem that it returned too much intersections. This is caused by:

edges = np.stack((xy[:-1], xy[1:]), axis=1)

which connects all seperate linestring with each other.

This seems to work to create edges where linestrings are not connected:

    def intersect_linestring(
        self,
        obj: Union[xr.DataArray, xr.Dataset],
        linestring: "shapely.geometry.LineString",  # type: ignore # noqa
    ) -> Union[xr.DataArray, xr.Dataset]:
...
        xys, linesection_ids = shapely.get_coordinates([linestrings], return_index=True)
        _, split_ids = np.unique(linesection_ids, return_index=True)
        split_xys = np.split(xys, split_ids[1:])
        
        edges = np.concatenate([np.stack((xy[:-1], xy[1:]), axis=1) for xy in split_xys], axis=0)
        edge_line_ids = np.delete(linesection_ids, split_ids)
        edge_index, core_index, intersections = self.intersect_edges(edges)
        # Linestring ids, which can be added to coords
        line_ids = edge_line_ids[edge_index]
        ...
        coords, core_index = get_sorted_section_coords(
            s, intersection_for_coord, line_ids, dim, core_index, self.name
        )
        ...

I also thought it is useful to keep the linestring ids and add them to coords:

def get_sorted_section_coords(
    s: FloatArray, xy: FloatArray, line_ids: IntArray, dim: str, index: IntArray, name: str
):
    order = np.argsort(s)
    coords = {
        f"{name}_x": (dim, xy[order, 0]),
        f"{name}_y": (dim, xy[order, 1]),
        f"{name}_s": (dim, s[order]),
        f"{name}_line_id": (dim, line_ids[order]),
    }
    return coords, index[order]

@Huite Let me know if this is within the scope of intersect_linestring or requires a separate method intersect_linestrings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions