4

I have a group of Polygon objects and need to iterate through each of their edges in a repeatable way. My preferred method is anti-clockwise from the closest point to the lower left corner of the bounding box.

I can ensure the polygon points are anti-clockwise by:

polygon = shapely.geometry.polygon.orient(polygon)

I can find my desired starting point using:

polygon = shapely.geometry.Polygon(...)
lower_left = shapely.geometry.Point(bbox[:2])
nearest_pt = min(self.polygon.exterior.coords, 
                  key=lambda x: shapely.geometry.Point(x).distance(lower_left))

My question is how can I make the LinearRing of the Polygon object start from that corner?

Jamie Bull
  • 12,889
  • 15
  • 77
  • 116

2 Answers2

3

This works but it's possibly not very efficient.

perimeter = polygon.exterior.coords
new_coords = []
first_vertex = nearest_pt  # as found in the question above
two_tours = itertools.chain(perimeter, perimeter)
for v in two_tours:
    if shapely.geometry.Point(v) == first_vertex:
        new_coords.append(v)
        while len(new_coords) < len(perimeter):
            new_coords.append(two_tours.next())
        break
polygon = shapely.geometry.Polygon(new_coords)
Jamie Bull
  • 12,889
  • 15
  • 77
  • 116
0

The answer of Jamie Bull works, but there is one little flaw. Because the itertools.chain takes two times the coordinate sequence and thus the repeated point of the polygon ends up in the 'two_tours' four times.

To counter this, replace this line:

two_tours = itertools.chain(perimeter, perimeter)

with this:

two_tours = itertools.chain(perimeter[:-1], perimeter)
perimeter = polygon.exterior.coords
new_coords = []
first_vertex = nearest_pt  # as found in the question above
two_tours = itertools.chain(perimeter[:-1], perimeter)
for v in two_tours:
    if shapely.geometry.Point(v) == first_vertex:
        new_coords.append(v)
        while len(new_coords) < len(perimeter):
            new_coords.append(two_tours.next())
        break
polygon = shapely.geometry.Polygon(new_coords)
Mudimans
  • 1
  • 2