2

I've a very large linear shapefile wich represents pipes. I need to determine the position of every intersection between lines in this shape, only where no vertices already exists (I think with 0,-1 vertices) to create a new punctual layer. I've already tried some methods with lines intersection and validity checker with no luck.

In the following image I need to find the point indicated with the blue arrow, not the red circles. The red line (and the pink line intersected) is continuous.enter image description here

1
  • Do you want to identify intersection points if one of the lines has a vertex? Or just identify intersection points where both lines do not have a vertex? Commented yesterday

3 Answers 3

2

As of QGIS 3.44 there is the tool Self-Intersections from the Check Geometry category.

enter image description here

Result

enter image description here

2
  1. Line Intersections to find points where different lines cross

  2. Extract vertices to extract all existing vertices

  3. Extract by expression Line intersection points that have no vertice nearby

array_length(array:= overlay_nearest(layer:= @Extract_vertices_OUTPUT , expression:=1, max_distance:=1))=0

Replace @Extract_vertices_OUTPUT with your vertice layer name.

enter image description here

1

This python script which you can run from the console with create points where 2 lines intersect and one or both does not have a vertex at the intersection points. It does not look for self-intersection.

# create point layer with points where either intersecting line or both do not have a vertex

from qgis.core import (
    QgsProject, QgsGeometry, QgsFeature, QgsPointXY, QgsSpatialIndex
)

LAYER_NAME = "pipes"
pipes = QgsProject.instance().mapLayersByName(LAYER_NAME)[0]

epsg = pipes.crs().authid()
out = QgsVectorLayer(f"Point?crs={epsg}", f"{LAYER_NAME}_ints_one_or_none_vertices", "memory")
prov = out.dataProvider()
out.updateFields()

# Build vertex dictionary: { feature_id : set((x,y),...) }
vertex_dict = {}

for f in pipes.getFeatures():
    verts = set()
    for v in f.geometry().vertices():
        verts.add((v.x(), v.y()))
    vertex_dict[f.id()] = verts


index = QgsSpatialIndex(pipes.getFeatures())

added = 0

for f in pipes.getFeatures():
    geomA = f.geometry()
    bbox = geomA.boundingBox()
    candidates = index.intersects(bbox)

    for cid in candidates:

        # skip self-intersections
        if cid == f.id():
            continue

        # ensure pair only processed once
        if cid < f.id():
            continue

        f2 = pipes.getFeature(cid)
        geomB = f2.geometry()

        inter = geomA.intersection(geomB)
        if inter.isEmpty():
            continue

        pts = inter.asMultiPoint() if inter.isMultipart() else [inter.asPoint()]

        for p in pts:
            pt = (p.x(), p.y())

            # Count how many of the two lines have a vertex at this point
            has_vertex_A = pt in vertex_dict[f.id()]
            has_vertex_B = pt in vertex_dict[cid]
            count_vertices = has_vertex_A + has_vertex_B


            # 0 -> no vertex on either line (add)
            # 1 -> exactly one line has a vertex (add)
            # 2 -> both lines have a vertex (skip)
            if count_vertices == 2:
                continue

            # Add the point
            feat = QgsFeature(out.fields())
            feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(p)))
            prov.addFeature(feat)
            added += 1

QgsProject.instance().addMapLayer(out)
print(f"Done — added {added} intersection points (where 0 or 1 lines have vertices).")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.