From b94b4df44cfe2fe718aa0207936b33a8f43d5c6d Mon Sep 17 00:00:00 2001 From: Fleup Date: Wed, 30 Nov 2016 16:12:49 +0100 Subject: [PATCH 1/5] Added area computation for polygon --- python_geometry/polygon_utilities.py | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 python_geometry/polygon_utilities.py diff --git a/python_geometry/polygon_utilities.py b/python_geometry/polygon_utilities.py new file mode 100644 index 0000000..f354036 --- /dev/null +++ b/python_geometry/polygon_utilities.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""docstring""" +import numpy as np + + +def area_of_polygon(polygon, *args): + """ + The Area is positive for counter clockwise ordering otherwise negative see http://paulbourke.net/geometry/polygonmesh/ + + Parameters + ---------- + polygon: + np.ndarray, list + The polygon as a list of consecutive points. + + Returns + ------- + float + Area of the polygon. Note that the area is negativ for clockwise ordering + """ + + if args: + poly = [polygon] + + for pt in args: + if pt.shape != (2,): + for sp in pt: + poly.append(sp) + else: + poly.append(pt) + + polygon = np.array(poly) + + area = 0. + for i in range(len(polygon) - 1): + area += (polygon[i][0] * polygon[i + 1][1] - polygon[i + 1][0] * polygon[i][1]) + area += ( + polygon[-1][0] * polygon[0][1] - polygon[-1][1] * polygon[0][0]) # close the loop with the last crossproduct + area /= 2. + if area == 0: + raise ValueError('Calculated Area is 0!') + return area From 16dfaea1f6d2307e288195d3d178f096eed1ea11 Mon Sep 17 00:00:00 2001 From: Fleup Date: Wed, 30 Nov 2016 16:28:06 +0100 Subject: [PATCH 2/5] added tests for simple rectangles and triangles for area of polygon --- python_geometry/polygon_utilities.py | 9 ++++----- tests/test_polygon_utilities.py | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 tests/test_polygon_utilities.py diff --git a/python_geometry/polygon_utilities.py b/python_geometry/polygon_utilities.py index f354036..b23405e 100644 --- a/python_geometry/polygon_utilities.py +++ b/python_geometry/polygon_utilities.py @@ -5,15 +5,15 @@ import numpy as np -def area_of_polygon(polygon, *args): +def area_of_polygon_2D(polygon, *args): """ - The Area is positive for counter clockwise ordering otherwise negative see http://paulbourke.net/geometry/polygonmesh/ - + Computes the signed area of an arbitrary convex polygon as described in http://paulbourke.net/geometry/polygonmesh/. + The signed area is positive for counter clockwise ordering otherwise negative Parameters ---------- polygon: np.ndarray, list - The polygon as a list of consecutive points. + The polygon as a list of consecutive 2D points. Returns ------- @@ -30,7 +30,6 @@ def area_of_polygon(polygon, *args): poly.append(sp) else: poly.append(pt) - polygon = np.array(poly) area = 0. diff --git a/tests/test_polygon_utilities.py b/tests/test_polygon_utilities.py new file mode 100644 index 0000000..fb32730 --- /dev/null +++ b/tests/test_polygon_utilities.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""docstring""" +from unittest import TestCase +from numpy.testing import assert_almost_equal, assert_equal + +from python_geometry.polygon_utilities import area_of_polygon_2D + + +class TestArea_of_polygon2D(TestCase): + def test_quads(self): + quad1 = ([0, 0], [1, 0], [1, 1], [0, 1]) + quad2 = ([0, 0], [0, 1], [1, 1], [1, 0]) + assert_equal(area_of_polygon_2D(quad1), 1) + assert_equal(area_of_polygon_2D(quad2), -1) + + def test_triangles(self): + tria1 = ([0, 0], [1, 0], [1, 1]) + tria2 = ([0, 0], [1, 1], [1, 0]) + assert_equal(area_of_polygon_2D(tria1), 0.5) + assert_equal(area_of_polygon_2D(tria2), -0.5) From 208e38ce81d0dcbf957fb0e5bf6cc71f4c76fc14 Mon Sep 17 00:00:00 2001 From: Fleup Date: Wed, 30 Nov 2016 16:31:31 +0100 Subject: [PATCH 3/5] more tests, --- tests/test_polygon_utilities.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/test_polygon_utilities.py b/tests/test_polygon_utilities.py index fb32730..4a30645 100644 --- a/tests/test_polygon_utilities.py +++ b/tests/test_polygon_utilities.py @@ -9,14 +9,21 @@ class TestArea_of_polygon2D(TestCase): - def test_quads(self): + def test_rectangles(self): + ## square quad1 = ([0, 0], [1, 0], [1, 1], [0, 1]) quad2 = ([0, 0], [0, 1], [1, 1], [1, 0]) assert_equal(area_of_polygon_2D(quad1), 1) assert_equal(area_of_polygon_2D(quad2), -1) + # rectangles + quad3 = ([0, 0], [5, 0], [5, 1], [0, 1]) + assert_equal(area_of_polygon_2D(quad3), 5) + def test_triangles(self): tria1 = ([0, 0], [1, 0], [1, 1]) tria2 = ([0, 0], [1, 1], [1, 0]) + tria3 = ([0, 0], [5, 10], [2, 5]) assert_equal(area_of_polygon_2D(tria1), 0.5) assert_equal(area_of_polygon_2D(tria2), -0.5) + assert_equal(area_of_polygon_2D(tria3), 2.5) From 5771c687db409197e4ddefe0cf77f10b63e4a39d Mon Sep 17 00:00:00 2001 From: Fleup Date: Wed, 30 Nov 2016 16:35:14 +0100 Subject: [PATCH 4/5] additional tests for numpy arrays --- tests/test_polygon_utilities.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_polygon_utilities.py b/tests/test_polygon_utilities.py index 4a30645..7df762d 100644 --- a/tests/test_polygon_utilities.py +++ b/tests/test_polygon_utilities.py @@ -3,7 +3,8 @@ """docstring""" from unittest import TestCase -from numpy.testing import assert_almost_equal, assert_equal +from numpy.testing import assert_equal +from numpy import array from python_geometry.polygon_utilities import area_of_polygon_2D @@ -13,8 +14,14 @@ def test_rectangles(self): ## square quad1 = ([0, 0], [1, 0], [1, 1], [0, 1]) quad2 = ([0, 0], [0, 1], [1, 1], [1, 0]) + quad1_np = array([[0, 0], [1, 0], [1, 1], [0, 1]]) + quad2_np = array([[0, 0], [0, 1], [1, 1], [1, 0]]) + assert_equal(area_of_polygon_2D(quad1), 1) assert_equal(area_of_polygon_2D(quad2), -1) + assert_equal(area_of_polygon_2D(quad1_np), 1) + assert_equal(area_of_polygon_2D(quad2_np), -1) + # rectangles quad3 = ([0, 0], [5, 0], [5, 1], [0, 1]) @@ -22,8 +29,10 @@ def test_rectangles(self): def test_triangles(self): tria1 = ([0, 0], [1, 0], [1, 1]) + tria1_np = array([[0, 0], [1, 0], [1, 1]]) tria2 = ([0, 0], [1, 1], [1, 0]) tria3 = ([0, 0], [5, 10], [2, 5]) assert_equal(area_of_polygon_2D(tria1), 0.5) + assert_equal(area_of_polygon_2D(tria1_np), 0.5) assert_equal(area_of_polygon_2D(tria2), -0.5) assert_equal(area_of_polygon_2D(tria3), 2.5) From 4663064056a2eee158072021b5ea3201a014e3f5 Mon Sep 17 00:00:00 2001 From: Fleup Date: Thu, 1 Dec 2016 10:00:38 +0100 Subject: [PATCH 5/5] fixed codestyle --- python_geometry/polygon_utilities.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/python_geometry/polygon_utilities.py b/python_geometry/polygon_utilities.py index b23405e..ef2c8b1 100644 --- a/python_geometry/polygon_utilities.py +++ b/python_geometry/polygon_utilities.py @@ -7,8 +7,11 @@ def area_of_polygon_2D(polygon, *args): """ - Computes the signed area of an arbitrary convex polygon as described in http://paulbourke.net/geometry/polygonmesh/. - The signed area is positive for counter clockwise ordering otherwise negative + Computes the signed area of an arbitrary convex polygon as described in + http://paulbourke.net/geometry/polygonmesh/. + The signed area is positive for counter clockwise ordering otherwise + negative. + Parameters ---------- polygon: @@ -18,7 +21,7 @@ def area_of_polygon_2D(polygon, *args): Returns ------- float - Area of the polygon. Note that the area is negativ for clockwise ordering + Area of the polygon. The area is negativ for clockwise point ordering """ if args: @@ -34,9 +37,12 @@ def area_of_polygon_2D(polygon, *args): area = 0. for i in range(len(polygon) - 1): - area += (polygon[i][0] * polygon[i + 1][1] - polygon[i + 1][0] * polygon[i][1]) - area += ( - polygon[-1][0] * polygon[0][1] - polygon[-1][1] * polygon[0][0]) # close the loop with the last crossproduct + area += (polygon[i][0] * polygon[i + 1][1] + - polygon[i + 1][0] * polygon[i][1]) + + # close the loop with the last crossproduct + area += (polygon[-1][0] * polygon[0][1] - polygon[-1][1] * polygon[0][0]) + area /= 2. if area == 0: raise ValueError('Calculated Area is 0!')