Repository: martinfleis/momepy
Pull request #182 (2020-06-25 19:39:20)

ENH: Fixed squareness for non-Polygon geom types
I added a condition for multi-polygon geometries

codecov[bot]: # [Codecov](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=h1) Report
> Merging [#182](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=desc) into [master](https://codecov.io/gh/martinfleis/momepy/commit/579393d37b486c208c6c8abad7417c7388e7d384&el=desc) will **increase** coverage by `0.00%`.
> The diff coverage is `86.66%`.

[![Impacted file tree graph](https://codecov.io/gh/martinfleis/momepy/pull/182/graphs/tree.svg?width=650&height=150&src=pr&token=i04999UxkK)](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #182   +/-   ##
=======================================
  Coverage   94.21%   94.22%           
=======================================
  Files          11       11           
  Lines        2663     2665    +2     
=======================================
+ Hits         2509     2511    +2     
  Misses        154      154           
```


| [Impacted Files](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [momepy/shape.py](https://codecov.io/gh/martinfleis/momepy/pull/182/diff?src=pr&el=tree#diff-bW9tZXB5L3NoYXBlLnB5) | `96.47% <85.71%> (+0.01%)` | :arrow_up: |
| [momepy/utils.py](https://codecov.io/gh/martinfleis/momepy/pull/182/diff?src=pr&el=tree#diff-bW9tZXB5L3V0aWxzLnB5) | `83.25% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=footer). Last update [fd68bdd...362ebd0](https://codecov.io/gh/martinfleis/momepy/pull/182?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

martinfleis: Thanks :). The failure in Travis CI is a known regression in the latest GeoPandas, so we can ignore that and merge this fix. There might be more of this kind, so feel free to do the same fix for those if you find them. Returning `np.nan` makes more sense than raising an error here.

Patch:
diff --git a/momepy/shape.py b/momepy/shape.py
index ddc6878..1a3bdda 100644
--- a/momepy/shape.py
+++ b/momepy/shape.py
@@ -855,41 +855,45 @@ class Squareness:
 
         # fill new column with the value of area, iterating over rows one by one
         for geom in tqdm(gdf.geometry, total=gdf.shape[0]):
-            angles = []
-            points = list(geom.exterior.coords)  # get points of a shape
-            stop = len(points) - 1  # define where to stop
-            for i in np.arange(
-                len(points)
-            ):  # for every point, calculate angle and add 1 if True angle
-                if i == 0:
-                    continue
-                elif i == stop:
-                    a = np.asarray(points[i - 1])
-                    b = np.asarray(points[i])
-                    c = np.asarray(points[1])
-                    ang = _angle(a, b, c)
-
-                    if ang <= 175:
-                        angles.append(ang)
-                    elif _angle(a, b, c) >= 185:
-                        angles.append(ang)
-                    else:
+            if geom.type == "Polygon":
+                angles = []
+                points = list(geom.exterior.coords)  # get points of a shape
+                stop = len(points) - 1  # define where to stop
+                for i in np.arange(
+                    len(points)
+                ):  # for every point, calculate angle and add 1 if True angle
+                    if i == 0:
                         continue
+                    elif i == stop:
+                        a = np.asarray(points[i - 1])
+                        b = np.asarray(points[i])
+                        c = np.asarray(points[1])
+                        ang = _angle(a, b, c)
+
+                        if ang <= 175:
+                            angles.append(ang)
+                        elif _angle(a, b, c) >= 185:
+                            angles.append(ang)
+                        else:
+                            continue
 
-                else:
-                    a = np.asarray(points[i - 1])
-                    b = np.asarray(points[i])
-                    c = np.asarray(points[i + 1])
-                    ang = _angle(a, b, c)
-
-                    if _angle(a, b, c) <= 175:
-                        angles.append(ang)
-                    elif _angle(a, b, c) >= 185:
-                        angles.append(ang)
                     else:
-                        continue
-            deviations = [abs(90 - i) for i in angles]
-            results_list.append(np.mean(deviations))
+                        a = np.asarray(points[i - 1])
+                        b = np.asarray(points[i])
+                        c = np.asarray(points[i + 1])
+                        ang = _angle(a, b, c)
+
+                        if _angle(a, b, c) <= 175:
+                            angles.append(ang)
+                        elif _angle(a, b, c) >= 185:
+                            angles.append(ang)
+                        else:
+                            continue
+                deviations = [abs(90 - i) for i in angles]
+                results_list.append(np.mean(deviations))
+
+            else:
+                results_list.append(np.nan)
 
         self.series = pd.Series(results_list, index=gdf.index)
 


Test patch:
diff --git a/tests/test_shape.py b/tests/test_shape.py
index 823051f..0a0e4fe 100644
--- a/tests/test_shape.py
+++ b/tests/test_shape.py
@@ -170,6 +170,8 @@ class TestShape:
         self.df_buildings["squ"] = mm.Squareness(self.df_buildings).series
         check = approx(3.707, rel=1e-3)
         assert self.df_buildings["squ"][0] == check
+        self.df_buildings["squ"] = mm.Squareness(self.df_buildings.exterior).series
+        assert self.df_buildings["squ"].isna().all()
 
     def test_EquivalentRectangularIndex(self):
         self.df_buildings["eri"] = mm.EquivalentRectangularIndex(