[enhancement] Signed Area - Shoelace Formula
CristianoPizzamiglio opened this issue · 4 comments
Hi! Wonderful library! Thanks!
Before starting a new PR, I would like to know if it could be of interest or not the addition of a method for the computation of the signed area of a simple polygon whose vertices are described by their 2D cartesian coordinates by means of the shoelace formula.
I was thinking to add this method to the Points
class, but maybe it could be a little off-topic there. Perhaps, it could be just a function in the public measurement
module.
For a particular project, I am using your library and very often I also need to compute the signed area given 2D points and I thought that maybe it could an interesting addition to this library.
I would implement the code in the following way (let's suppose we are within the measurement
module):
def area_signed(points: array_like) -> float:
"""
Compute the signed area of a simple polygon whose vertices are described
by their 2D cartesian coordinates.
Parameters
----------
points : array_like
Input 2D points.
Returns
-------
area_signed : float
The signed area of the polygon.
Raises
------
ValueError
If the points are not 2D.
If there are fewer than three points.
References
----------
https://en.wikipedia.org/wiki/Shoelace_formula
https://alexkritchevsky.com/2018/08/06/oriented-area.html#solution
https://rosettacode.org/wiki/Shoelace_formula_for_polygonal_area#Python
"""
points = Points(points)
if points.dimension != 2:
raise ValueError("The points must be 2D.")
if points.shape[0] < 3:
raise ValueError("There must be at least 3 points.")
x = points[:, 0]
y = points[:, 1]
return sum(x[i-1]*y[i] - x[i]*y[i-1] for i in range(len(points))) / 2
I believe it should be just the user's responsibility to check if the order of the points does not result in a self-overlapping polygon.
The implementation of the shoelace algorithm follows the approach suggested here. It's an elegant and I think also clear one-liner. But maybe the Numpy approach could be faster for a large amount of points (I haven't had the opportunity to compare the performance yet).
No worries if this feature is not of interest.
Have a nice weekend!
Hi Christiano, thank you!
I wasn't planning on adding more features to this library, but if this is something you'd like to add, then go for it! I'll try it out and review the PR when you make it.
Good! So, in the next days I will open a new PR. I will add the function to the measurement
module.
If I have understood correctly, you haven't planned to add more features because the library has now reached its maximum extension but nonetheless you are open to add new useful functionalities, right?
Yes, I hadn't planned on adding more features because I think the library has enough (and I don't have the free time I had when I wrote most of this), but I'm open to adding some more if others would like to contribute!
It makes a lot of sense. Thanks for your valuable work! I am really happy to contribute to this library!