1import numpy as np
2
3from shapely.geometry import Point, Polygon
4from pandas import Series
5
6from geopandas import GeoDataFrame, GeoSeries
7from geopandas.array import from_shapely
8
9from geopandas.testing import assert_geodataframe_equal, assert_geoseries_equal
10import pytest
11
12s1 = GeoSeries(
13    [
14        Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
15        Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
16    ]
17)
18s2 = GeoSeries(
19    [
20        Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]),
21        Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
22    ]
23)
24
25
26s3 = Series(
27    [
28        Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]),
29        Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
30    ]
31)
32
33a = from_shapely(
34    [
35        Polygon([(0, 2), (0, 0), (2, 0), (2, 2)]),
36        Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
37    ]
38)
39
40s4 = Series(a)
41
42df1 = GeoDataFrame({"col1": [1, 2], "geometry": s1})
43df2 = GeoDataFrame({"col1": [1, 2], "geometry": s2})
44
45s4 = s1.copy()
46s4.crs = 4326
47s5 = s2.copy()
48s5.crs = 27700
49
50s6 = GeoSeries(
51    [
52        Polygon([(0, 3), (0, 0), (2, 0), (2, 2)]),
53        Polygon([(2, 2), (4, 2), (4, 4), (2, 4)]),
54    ]
55)
56
57df4 = GeoDataFrame(
58    {"col1": [1, 2], "geometry": s1.copy(), "geom2": s4.copy(), "geom3": s5.copy()},
59    crs=3857,
60)
61df5 = GeoDataFrame(
62    {"col1": [1, 2], "geometry": s1.copy(), "geom3": s5.copy(), "geom2": s4.copy()},
63    crs=3857,
64)
65
66
67@pytest.mark.filterwarnings("ignore::UserWarning")
68def test_geoseries():
69    assert_geoseries_equal(s1, s2)
70    assert_geoseries_equal(s1, s3, check_series_type=False, check_dtype=False)
71    assert_geoseries_equal(s3, s2, check_series_type=False, check_dtype=False)
72    assert_geoseries_equal(s1, s4, check_series_type=False)
73
74    with pytest.raises(AssertionError) as error:
75        assert_geoseries_equal(s1, s2, check_less_precise=True)
76    assert "1 out of 2 geometries are not almost equal" in str(error.value)
77    assert "not almost equal: [0]" in str(error.value)
78
79    with pytest.raises(AssertionError) as error:
80        assert_geoseries_equal(s2, s6, check_less_precise=False)
81    assert "1 out of 2 geometries are not equal" in str(error.value)
82    assert "not equal: [0]" in str(error.value)
83
84
85def test_geodataframe():
86    assert_geodataframe_equal(df1, df2)
87
88    with pytest.raises(AssertionError):
89        assert_geodataframe_equal(df1, df2, check_less_precise=True)
90
91    with pytest.raises(AssertionError):
92        assert_geodataframe_equal(df1, df2[["geometry", "col1"]])
93
94    assert_geodataframe_equal(df1, df2[["geometry", "col1"]], check_like=True)
95
96    df3 = df2.copy()
97    df3.loc[0, "col1"] = 10
98    with pytest.raises(AssertionError):
99        assert_geodataframe_equal(df1, df3)
100
101    assert_geodataframe_equal(df5, df4, check_like=True)
102    df5.geom2.crs = 3857
103    with pytest.raises(AssertionError):
104        assert_geodataframe_equal(df5, df4, check_like=True)
105
106
107def test_equal_nans():
108    s = GeoSeries([Point(0, 0), np.nan])
109    assert_geoseries_equal(s, s.copy())
110    assert_geoseries_equal(s, s.copy(), check_less_precise=True)
111
112
113def test_no_crs():
114    df1 = GeoDataFrame({"col1": [1, 2], "geometry": s1}, crs=None)
115    df2 = GeoDataFrame({"col1": [1, 2], "geometry": s1}, crs={})
116    assert_geodataframe_equal(df1, df2)
117
118
119def test_ignore_crs_mismatch():
120    df1 = GeoDataFrame({"col1": [1, 2], "geometry": s1.copy()}, crs="EPSG:4326")
121    df2 = GeoDataFrame({"col1": [1, 2], "geometry": s1}, crs="EPSG:31370")
122
123    with pytest.raises(AssertionError):
124        assert_geodataframe_equal(df1, df2)
125
126    # assert that with `check_crs=False` the assert passes, and also does not
127    # generate any warning from comparing both geometries with different crs
128    with pytest.warns(None) as record:
129        assert_geodataframe_equal(df1, df2, check_crs=False)
130
131    assert len(record) == 0
132
133
134def test_almost_equal_but_not_equal():
135    s_origin = GeoSeries([Point(0, 0)])
136    s_almost_origin = GeoSeries([Point(0.0000001, 0)])
137    assert_geoseries_equal(s_origin, s_almost_origin, check_less_precise=True)
138    with pytest.raises(AssertionError):
139        assert_geoseries_equal(s_origin, s_almost_origin)
140