[1]:
import geopandas
import numpy
import matplotlib.pyplot as plt
import geoplanar
import libpysal
from shapely.geometry import Polygon

Planar Enforcement Violation: non-planar enforced touches#

[2]:
c1 = [[0,0], [0, 10], [10, 10], [10, 0], [0, 0]]
p1 = Polygon(c1)
c2 = [[10, 2], [20, 8], [20, 2], [10, 2]]
p2 = Polygon(c2)
gdf = geopandas.GeoDataFrame(geometry=[p1, p2])
base = gdf.plot(edgecolor='k', facecolor="none",alpha=0.5)
c1 = numpy.array(c1)
c2 = numpy.array(c2)
_ = base.scatter(c1[:,0], c1[:,1])
_ =base.scatter(c2[:,0], c2[:,1])


_images/nonplanartouches_2_0.png

The two polygons are visually contiguous share no vertices. This will result in the two polygons not being Queen neighbors, since a necessary (and sufficient) condition for the latter is at least one shared vertex.

[3]:
w = libpysal.weights.Queen.from_dataframe(gdf)
/home/serge/anaconda3/envs/dev39/lib/python3.10/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There are 2 islands with ids: 0, 1.
  warnings.warn(message)

Detecting nonplanar touches#

geoplanar can detect and report nonplanar edges:

[4]:
geoplanar.non_planar_edges(gdf)
[4]:
defaultdict(set, {0: {1}})

Fixing nonplanar edges#

[5]:
gdf1 = geoplanar.fix_npe_edges(gdf)
/home/serge/anaconda3/envs/dev39/lib/python3.10/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There are 2 islands with ids: 0, 1.
  warnings.warn(message)
[6]:
geoplanar.non_planar_edges(gdf1)
[6]:
defaultdict(set, {})
[7]:
w1 = libpysal.weights.Queen.from_dataframe(gdf1)
w1.neighbors
[7]:
{0: [1], 1: [0]}

Default is to work on a copy#

[8]:
geoplanar.non_planar_edges(gdf)
/home/serge/anaconda3/envs/dev39/lib/python3.10/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There are 2 islands with ids: 0, 1.
  warnings.warn(message)
[8]:
defaultdict(set, {0: {1}})
[9]:
geoplanar.fix_npe_edges(gdf, inplace=True)

[9]:
geometry
0 POLYGON ((0.00000 0.00000, 0.00000 10.00000, 1...
1 POLYGON ((10.00000 2.00000, 20.00000 8.00000, ...
[10]:
geoplanar.non_planar_edges(gdf)
[10]:
defaultdict(set, {})
[11]:
w = libpysal.weights.Queen.from_dataframe(gdf)
w.neighbors
[11]:
{0: [1], 1: [0]}

Handle MultiPolygons#

[12]:
from shapely.geometry import MultiPolygon
c1 = [[0,0], [0, 10], [10, 10], [10, 0], [0, 0]]
p1 = Polygon(c1)
c2 = [[10, 2], [20, 8], [20, 2], [10, 2]]
p3 = Polygon([ [21, 2], [21, 4], [23,3] ])

#p2 = Polygon(c2)
p2 = MultiPolygon([Polygon(c2), p3])

gdf = geopandas.GeoDataFrame(geometry=[p1, p2])
base = gdf.plot(edgecolor='k', facecolor="none",alpha=0.5)
c1 = numpy.array(c1)
c2 = numpy.array(c2)
_ = base.scatter(c1[:,0], c1[:,1])
_ =base.scatter(c2[:,0], c2[:,1])


_images/nonplanartouches_18_0.png
[13]:
res = geoplanar.non_planar_edges(gdf)
/home/serge/anaconda3/envs/dev39/lib/python3.10/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There are 2 islands with ids: 0, 1.
  warnings.warn(message)
[14]:
res
[14]:
defaultdict(set, {0: {1}})
[14]:
gdf1 = geoplanar.fix_npe_edges(gdf)

/home/serge/anaconda3/envs/edu_concordance/lib/python3.9/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There are 2 islands with ids: 0, 1.
  warnings.warn(message)
[15]:
gdf1.geometry[0].wkt
[15]:
'POLYGON ((0 0, 0 10, 10 10, 10 2, 10 0, 0 0))'
[16]:
gdf.geometry[0].wkt
[16]:
'POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))'
[ ]: