[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 edges

[2]:
c1 = [[0,0], [0, 10], [10, 10], [10, 0], [0, 0]]
p1 = Polygon(c1)
c2 = [[10, 2], [10, 8], [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/nonplanaredges_2_0.png

The two polygons are visually contiguous, but are not planar enforced as the right edge of the left polygon and the left edge of right polygon 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/dev38/lib/python3.8/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 edges

geoplanar can detect and report nonplanar edges:

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

Fixing nonplanar edges

[5]:
geoplanar.is_planar_enforced(gdf)
[5]:
False
[6]:
gdf1 = geoplanar.fix_npe_edges(gdf)
[7]:
geoplanar.non_planar_edges(gdf1)
[7]:
defaultdict(set, {})
[8]:
w1 = libpysal.weights.Queen.from_dataframe(gdf1)
w1.neighbors
[8]:
{0: [1], 1: [0]}
[9]:
geoplanar.is_planar_enforced(gdf1)
[9]:
True

Planar Enforcement Violation: Overlapping and non-planar enforced edges

[10]:
from shapely.geometry import Polygon
[11]:

t1 = Polygon([[0,0],[10,10], [20,0]])
[12]:
t1
[12]:
_images/nonplanaredges_17_0.svg
[13]:
b1 = Polygon([[5,5], [20,5], [20,-10], [0,-10]])
b1
[13]:
_images/nonplanaredges_18_0.svg
[14]:
gdf = geopandas.GeoDataFrame(geometry=[t1,b1])
[15]:
gdf.plot(edgecolor='k',facecolor="none",alpha=0.5) # non planar enforcement

[15]:
<AxesSubplot:>
_images/nonplanaredges_20_1.png

The two features overlap and would appear to share vertices, but they in fact do not share vertices. Again, because this violates planar enforcement, this results in two polygons not being Queen neighbors:

[16]:
import libpysal

w = libpysal.weights.Queen.from_dataframe(gdf)
/home/serge/anaconda3/envs/dev38/lib/python3.8/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 edges

geoplanar will use a failed contiguity check as part of a check for nonplanar enforced edges in the polygons of a geoseries:

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

Correcting nonplanar edges

[18]:
gdf_fixed = geoplanar.fix_npe_edges(gdf)
geoplanar.non_planar_edges(gdf_fixed)
[18]:
defaultdict(set, {})

Default is to work on a copy

[19]:
geoplanar.non_planar_edges(gdf)
[19]:
defaultdict(set, {0: {1}})
[20]:
geoplanar.fix_npe_edges(gdf, inplace=True)

[20]:
geometry
0 POLYGON ((0.00000 0.00000, 5.00000 5.00000, 10...
1 POLYGON ((5.00000 5.00000, 15.00000 5.00000, 2...
[21]:
geoplanar.non_planar_edges(gdf)
[21]:
defaultdict(set, {})
[22]:
w = libpysal.weights.Queen.from_dataframe(gdf)
w.neighbors
[22]:
{0: [1], 1: [0]}