I am trying to create a path planning algorithm for a robotic mower to cut all the grass in a defined area while avoiding obstacles or restricted areas. I am using the Python Shapely library to define the geometry of the area. In the following image, the mowing area is marked blue and the restricted area is marked red.
My current approach is to generate parallel lines at regular intervals between the bounds of the area, then cut them into segments wherever they intersect the obstacle or map boundary. Here is an image to illustrate that.

Once I have my line segments, I want to use turn each point on the map from the area, obstacle, and intersections into nodes on a graph. The graph should faithfully represent each point's adjacency to the others. Afterward, I plan to make a traversal algorithm that visits each node at least once.
I want to know if there is a succinct way to convert geometric features from Shapely into a connected graph for my purposes.
Here is the relevant code for generating the geometry for the mowing area and intersecting lines:
import numpy as np
from shapely.geometry import Point, Polygon, LineString, MultiLineString, GeometryCollection
def generate_intersections(areaCoords, obstacleCoords, spacing = 1.0):
# Create Shapely polygons
area = Polygon(areaCoords)
obstacle = Polygon(obstacleCoords)
map = area.difference(obstacle)
# Obtain bounding box
minX, minY, maxX, maxY = area.bounds
# Generate parallel lines within bounding box
lines = []
y = minY
while y <= maxY:
lines.append(LineString( [(minX,y),(maxX,y)] ))
y += spacing
# Cut lines where they intersect with Boundaries/Obstacle,
intersections = []
for line in lines:
parallel = []
intersection = line.intersection(map)
if intersection.is_empty:
continue
# Line intersects with boundaries only
if isinstance(intersection, LineString):
coords = list(intersection.xy)
parallel.append(coords)
# Line intersects with obstacle and boundaries
elif isinstance(intersection, (MultiLineString, GeometryCollection)):
for g in list(intersection.geoms):
parallel.append(list(g.xy))
intersections.append(parallel)
return intersections
if __name__ == "__main__":
# Polygon Coordinates
areaCoords = [(2,0),(14,0),(14,12),(2,12)]
obstacleCoords = [(4,5),(9,5),(9,9),(4,9)]
# Get intersecting points
intersections = generate_intersections(areaCoords,obstacleCoords,2.0)



