4

I am trying to loop through a set of polygons in shapely so using python) to determine whether they overlap or not. I do not want to do it manually as later i want to generalise the procedure and do this for a number of polygons imported from a shapefile (through Fiona). These are the polygons I am now testing polA = Polygon([(0,0), (3,0), (3,3), (0,3)]) polB = Polygon([(2,-1), (5,-1), (5,2), (2,2)]) polC = Polygon([(5,2), (8,2), (8,5), (5,5)]) I created a collection from these collection = [polA, polB, polC] and now I want a for loop to go through the list and check each polygon if it overlaps with the next. But nothing I try works, because I don't know how to loop and successfully test all the possible combinations. Don't know if I am understood. Does anyone have any idea how to do this using Shapely of Fiona?

  • It is a pure Python problem, search on the web for ""Comparing the next item in a list" and you will get a lot of solutions – gene Oct 5 '14 at 10:07
  • The thing is I do not want to repeat the intersection with the polygons I have already checked. For example, if I have polA and polB checked, I do not want to check polB with polA as for more polygons it will take a lot of time. Is that possible? Because, from searching I have to do all possible combinations. My python knowledge is not that advanced and maybe I get sth wrong. – GeomP Oct 5 '14 at 10:36
  • look below for some solutions – gene Oct 5 '14 at 11:22
7

Some solutions according to the position of an element in a list:

polA = Polygon([(0,0), (3,0), (3,3), (0,3)])
polB = Polygon([(2,-1), (5,-1), (5,2), (2,2)])
polC = Polygon([(5,2), (8,2), (8,5), (5,5)]) 
collection = [polA, polB, polC]

Iterating by index:

for i in range(len(collection)-1):
    print collection[i], collection[i+1], collection[i].touches(collection[i+1])
POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) False
POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) True

Iterating with itertools (standard module), all combinations without repeated elements

import itertools
for pol in  itertools.combinations(collection, 2):
    print pol[0],pol[1], pol[0].touches(pol[1])
 POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) False
 POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) False
 POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) True

or with the suggestion of Mike T

for pol1, pol2 in  itertools.combinations(collection, 2):
     print pol1, pol2, pol1.touches(pol2)
 POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) False
 POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) False
 POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) True

Compare with

for pol in  itertools.permutations(collection, 2):
    print pol[0],pol[1], pol[0].touches(pol[1]) 
POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) False
POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) False
POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) False
POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) True
POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) False
POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) True

Look also at Python - Previous and next values inside a loop

from itertools import tee, islice, chain, izip
def previous_and_next(some_iterable):
    prevs, items, nexts = tee(some_iterable, 3)
    prevs = chain([None], prevs)
    nexts = chain(islice(nexts, 1, None), [None])
    return izip(prevs, items, nexts)
 for previous, item, nxt in previous_and_next(collection):
      print "Item is now", item, "next is", nxt, "previous is", previous

 Item is now POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) next is POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) previous is None
 Item is now POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) next is POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) previous is POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))
 Item is now POLYGON ((5 2, 8 2, 8 5, 5 5, 5 2)) next is None previous is POLYGON ((2 -1, 5 -1, 5 2, 2 2, 2 -1))
  • Oh my god! Thank you so much! So many different things... itertools.combinations does what I want! – GeomP Oct 5 '14 at 11:38
  • You can also use for A, B in ... A.touches(B) for improved readability – Mike T Oct 5 '14 at 23:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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