Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/byteface/domonic into master
Browse files Browse the repository at this point in the history
  • Loading branch information
byteface committed Feb 17, 2022
2 parents 92cdbef + 2e3aa63 commit 5c91c81
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 70 deletions.
12 changes: 10 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,24 @@ The readme contains some tips on running tests.

For dev you will need to install the requirements-dev.txt file.

clone the repo an cd into it.
Clone the repo an cd into it.

setup a virtual environment
Setup a virtual environment:

**BASH**
```bash
python3 -m venv venv
. venv/bin/activate
pip install -r requirements-dev.txt
```

**PowerShell**
```powershell
python3 -m venv winvenv
. .\winvenv\Scripts\activate
pip install -r requirements-dev.txt
```

and you should be good to go.

The Makefile can be used to run all tests.
Expand Down
86 changes: 23 additions & 63 deletions domonic/d3/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def polygonCentroid(polygon):
k *= 3
return [x / k, y / k]


def cross(a, b, c):
"""[Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
the 3D cross product in a quadrant I Cartesian coordinate system (+x is
Expand All @@ -61,73 +60,34 @@ def cross(a, b, c):
"""
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])


def lexicographicOrder(a, b, *args):
return a[0] - b[0] or a[1] - b[1]


def computeUpperHullIndexes(points):
"""[Computes the upper convex hull per the monotone chain algorithm.
Assumes points.length >= 3, is sorted by x, unique in y.
Returns an array of indices into points in left-to-right order.]
Args:
points ([type]): [description]
"""
n = len(points)
indexes = [0, 1]
size = 2
for i in range(2, n):
while (size > 1 and cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0):
size -= 1
size += 1
indexes[size] = i

return Array(indexes).slice(0, size) # remove popped points


def polygonHull(points):

n = len(points)
if n < 3:
return None

sortedPoints = []
flippedPoints = []

print(points)

for i in range(0, n):
print( points[i][0], points[i][1], i)
sortedPoints.append([points[i][0], points[i][1], i])

print(sortedPoints)

sortedPoints = Array(sortedPoints).sort(lexicographicOrder)

for i in range(0, n):
flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]

upperIndexes = computeUpperHullIndexes(sortedPoints)
lowerIndexes = computeUpperHullIndexes(flippedPoints)

# Construct the hull polygon, removing possible duplicate endpoints.
skipLeft = lowerIndexes[0] == upperIndexes[0]
skipRight = lowerIndexes[len(lowerIndexes) - 1] == upperIndexes[len(upperIndexes) - 1]
hull = []

# Add upper hull in right-to-l order.
# Then add lower hull in left-to-right order.
i = len(upperIndexes)
while i >= 0:
hull.append(points[sortedPoints[upperIndexes[i]][2]])
i -= 1

i = skipLeft
while i < len(lowerIndexes) - skipRight:
hull.append(points[sortedPoints[lowerIndexes[i]][2]])
i += 1

# Convert list to tuples and remove duplicates
points = [t for t in (set(tuple(i) for i in points))]

# Sort lexicographically
points = sorted(points)

# Build hulls according to Andrew's monotone chain algorithm
lowerHull = []
for p in points:
while len(lowerHull) >= 2 and cross(lowerHull[-2], lowerHull[-1], p) <=0 :
lowerHull.pop()
lowerHull.append(p)

upperHull = []
for p in reversed(points):
while len(upperHull) >= 2 and cross(upperHull[-2], upperHull[-1], p) <= 0:
upperHull.pop()
upperHull.append(p)

# Build polygon hull from upper/lower hulls and return to list form
hull = sorted([list(i) for i in lowerHull[:-1] + upperHull[:-1]])

return hull


Expand Down Expand Up @@ -171,4 +131,4 @@ def polygonLength(polygon):
ya -= yb
perimeter += Math.hypot(xa, ya)
i += 1
return perimeter
return perimeter
26 changes: 21 additions & 5 deletions tests/test_d3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1541,13 +1541,29 @@ def test_polygonArea(self):
self.assertEqual(polygonArea(square), 16)
self.assertEqual(polygonArea(triangle), 12)

# def test_polygonCentroid():
# def test_cross():
# def test_lexicographicOrder():
# def test_polygonHull():
def test_polygonCentroid(self):
irreg = [[-4,0],[8,12],[4,8],[-4,-4],[0,0]] # centroid: [0, 4]
square = [[0,4],[4,4],[4,0],[0,0]] # centroid: [2, 2]
triangle = [[-4,0],[0,4],[4,2]] # centroid: [0, 2]

self.assertEqual(polygonCentroid(irreg), [0, 4])
self.assertEqual(polygonCentroid(square), [2, 2])
self.assertEqual(polygonCentroid(triangle), [0, 2])

def test_polygonHull(self):
points_0 = [[0,6],[12,8],[23,-5],[-5,-3],[5,11],[12,4],[7,7],[6,1]]
points_1 = [[-4,0],[8,12],[4,8],[-4,-4],[0,0],[-6,12],[23,2],[19,-8],[-7,-6]]

hull_0 = [[-5,-3],[0,6],[5,11],[12,8],[23,-5]]
hull_1 = [[-7,-6],[-6,12],[8,12],[19,-8],[23,2]]

self.assertEqual(polygonHull(points_0), hull_0)
self.assertEqual(polygonHull(points_1), hull_1)


# def test_polygonContains():
# def test_polygonLength():


if __name__ == '__main__':
unittest.main()
unittest.main()

0 comments on commit 5c91c81

Please sign in to comment.