3

I have a polygon layer with one polygon and a line layer with a lot of lines. I need to check lines lie on the polygon boundaries or not and if they are add them into a graph. I couldn't think of anything better that convert polygon boundaries to a line layer and I tried to write such code to build a graph but it doesn't work. In fact I need to add polygon boundaries to a graph.

How can I do this?

import networkx as nx
from qgis.core import *
import processing

from shapely.geometry import Polygon, Point, LineString
from shapely.ops import unary_union

polygon_layer = QgsProject.instance().mapLayersByName("polygon")[0]
polygon_feature = polygon_layer.getFeature(0)
polygon = Polygon(polygon_feature.geometry().asMultiPolygon()[0])
polygons = [p for p in polygon_feature.geometry().asMultiPolygon()]
selected_polygon = Polygon(polygons[0][0])

G = nx.Graph()

for vertex in selected_polygon.exterior.coords:
    G.add_node(vertex)

temp_lines = processing.run("native:polygonstolines", {'INPUT': polygon_layer, 'OUTPUT':'TEMPORARY_OUTPUT'})["OUTPUT"]
QgsProject.instance().addMapLayer(temp_lines)                

for node1 in G.nodes:
    for node2 in G.nodes:
        if node1 != node2:
            line = LineString([node1, node2]) 
            for feature in temp_lines.getFeatures():
                geom = feature.geometry().asMultiPolyline()
                if line.within(geom):
                    G.add_edge(node1, node2, weight=Point(node1).distance(Point(node2)))

enter image description here

I also tried to convert polygon to lines, explode it through PyQGIS and then add it into graph, but I got incorrect geometry error (Too few point).

For example, I have such a polygon (red) and lines (blue). And I need to select only boundaries lines (yellow) or both inside and boundaries lines and add them into a graph. I don't need lines outside or partly outside the polygon.

enter image description here

enter image description here

enter image description here

0

1 Answer 1

1

shapely: intersects(), contains(), crosses(), equals(), touches(),within() ...

enter image description here

from qgis.core import *
import processing

from shapely.geometry import Polygon, Point, LineString
from shapely.wkt import loads

polygonLayer = QgsProject.instance().mapLayersByName("Polygon")[0]
polygonFeature = polygonLayer.getFeatures()
for feature in polygonFeature:
    wkt = feature.geometry().asWkt()
    polygonShapely = loads(wkt)
    
lineLayer = QgsProject.instance().mapLayersByName("Line")[0]
lineFeature = lineLayer.getFeatures()

selection = []

for feature in lineFeature:
    wkt = feature.geometry().asWkt()
    lineShapley = loads(wkt)
    if lineShapley.touches(polygonShapely) or lineShapley.within(polygonShapely):
        selection.append(feature.id())
    else:
        pass

lineLayer.select(selection)

EDIT 14. Jan. 2024:

I've tried to rebuild your polygon. As far as I understand your comment the line 2 and 3 in my new drawing touch the polygon in the vertices. So it will be selected with touches(). So you could change touches() with covered_by().

If you go through the documentation shapley binary predicates you will find a combination that fits for you. You could also try to use not in some cases (just as example):

if not lineShapley.covered_by(polygonShapely)

or filter a selection again in a second loop.

enter image description here

for feature in lineFeature:
    wkt = feature.geometry().asWkt()
    lineShapley = loads(wkt)
    if lineShapley.covered_by(polygonShapely) or lineShapley.within(polygonShapely):
        selection.append(feature.id())
    else:
        pass

If you run into an issue with covered_by() you could think about reducing precession of your geometry, or using a small buffer.

enter image description here

2
  • Thank you! But I have a problem with two horizontal lines for my polygon. Touches algorythm select them too.
    – grassu
    Commented Jan 14 at 14:05
  • I've customized the code with covered_by
    – Xeppit
    Commented Jan 14 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.