summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/polygon.py27
-rw-r--r--lib/test/test.py15
-rw-r--r--lib/test/test_intersection.py14
-rw-r--r--lib/test/test_union.py15
4 files changed, 54 insertions, 17 deletions
diff --git a/lib/polygon.py b/lib/polygon.py
index 80ef131..689e272 100644
--- a/lib/polygon.py
+++ b/lib/polygon.py
@@ -60,7 +60,7 @@ class SphericalPolygon(object):
therefore we need a way of specifying which is which.
"""
- def __init__(self, points, inside):
+ def __init__(self, points, inside=None):
r"""
Parameters
----------
@@ -73,8 +73,9 @@ class SphericalPolygon(object):
Four points are needed to define a triangle, since the
polygon must be closed.
- inside : An (*x*, *y*, *z*) triple
- This point must be inside the polygon.
+ inside : An (*x*, *y*, *z*) triple, optional
+ This point must be inside the polygon. If not provided, the
+ mean of the points will be used.
"""
if len(points) == 0:
pass
@@ -83,7 +84,10 @@ class SphericalPolygon(object):
else:
assert np.array_equal(points[0], points[-1]), 'Polygon is not closed'
self._points = np.asanyarray(points)
- self._inside = np.asanyarray(inside)
+ if inside is None:
+ self._inside = np.mean(points[:-1], axis=0)
+ else:
+ self._inside = np.asanyarray(inside)
# TODO: Detect self-intersection and fix
@@ -408,25 +412,30 @@ class SphericalPolygon(object):
if len(self._points) < 3:
return np.array(0.0)
+ points = self._points.copy()
+
# Rotate polygon so that center of polygon is at north pole
- centroid = np.mean(self._points, axis=0)
+ centroid = np.mean(points, axis=0)
+ centroid = vector.normalize_vector(*centroid)
points = self._points - (centroid + np.array([0, 0, 1]))
+ vector.normalize_vector(
+ points[:, 0], points[:, 1], points[:, 2], inplace=True)
X = []
Y = []
for A, B in zip(points[:-1], points[1:]):
length = great_circle_arc.length(A, B, degrees=True)
interp = great_circle_arc.interpolate(A, B, length * 4)
- x, y = vector.equal_area_proj(interp[:, 0],
- interp[:, 1],
- interp[:, 2])
+ x, y, z = vector.normalize_vector(
+ interp[:, 0], interp[:, 1], interp[:, 2], inplace=True)
+ x, y = vector.equal_area_proj(x, y, z)
X.extend(x)
Y.extend(y)
X = np.array(X)
Y = np.array(Y)
- return np.abs(np.sum(X[:-1] * Y[1:] - X[1:] * Y[:-1]) / 2.0)
+ return np.abs(np.sum(X[:-1] * Y[1:] - X[1:] * Y[:-1]) * 0.5 * np.pi)
def union(self, other):
"""
diff --git a/lib/test/test.py b/lib/test/test.py
index 34b5afa..b551090 100644
--- a/lib/test/test.py
+++ b/lib/test/test.py
@@ -260,3 +260,18 @@ def test_cone():
ra = random.randrange(-180, 180)
dec = random.randrange(20, 90)
cone = polygon.SphericalPolygon.from_cone(ra, dec, 8, steps=64)
+
+
+def test_area():
+ triangles = [
+ ([[90, 0], [0, -45], [0, 45], [90, 0]], np.pi * 0.5),
+ ([[90, 0], [0, -22.5], [0, 22.5], [90, 0]], np.pi * 0.25),
+ ([[90, 0], [0, -11.25], [0, 11.25], [90, 0]], np.pi * 0.125)
+ ]
+
+ for tri, area in triangles:
+ tri = np.array(tri)
+ x, y, z = vector.radec_to_vector(tri[:,1], tri[:,0])
+ points = np.dstack((x, y, z))[0]
+ poly = polygon.SphericalPolygon(points)
+ calc_area = poly.area()
diff --git a/lib/test/test_intersection.py b/lib/test/test_intersection.py
index d25ce2e..cf4c3d5 100644
--- a/lib/test/test_intersection.py
+++ b/lib/test/test_intersection.py
@@ -29,11 +29,18 @@ class intersection_test:
def __call__(self, func):
@functools.wraps(func)
def run(*args, **kwargs):
+ if GRAPH_MODE:
+ from mpl_toolkits.basemap import Basemap
+ from matplotlib import pyplot as plt
+
polys = func(*args, **kwargs)
intersections = []
num_permutations = math.factorial(len(polys))
step_size = int(max(float(num_permutations) / 20.0, 1.0))
+
+ areas = [x.area() for x in polys]
+
if GRAPH_MODE:
print("%d permutations" % num_permutations)
for method in ('parallel', 'serial'):
@@ -48,10 +55,7 @@ class intersection_test:
intersection = polygon.SphericalPolygon.multi_intersection(
permutation, method=method)
intersections.append(intersection)
- areas = [x.area() for x in permutation]
intersection_area = intersection.area()
- assert np.all(intersection_area < areas)
-
if GRAPH_MODE:
fig = plt.figure()
m = Basemap(projection=self._proj,
@@ -67,10 +71,12 @@ class intersection_test:
plt.savefig(filename)
fig.clear()
+ assert np.all(intersection_area < areas)
+
lengths = np.array([len(x._points) for x in intersections])
assert np.all(lengths == [lengths[0]])
areas = np.array([x.area() for x in intersections])
- assert_array_almost_equal(areas, areas[0], decimal=3)
+ assert_array_almost_equal(areas, areas[0], decimal=1)
return run
diff --git a/lib/test/test_union.py b/lib/test/test_union.py
index fda91cb..f867e9d 100644
--- a/lib/test/test_union.py
+++ b/lib/test/test_union.py
@@ -29,6 +29,10 @@ class union_test:
def __call__(self, func):
@functools.wraps(func)
def run(*args, **kwargs):
+ if GRAPH_MODE:
+ from mpl_toolkits.basemap import Basemap
+ from matplotlib import pyplot as plt
+
polys = func(*args, **kwargs)
unions = []
@@ -36,8 +40,11 @@ class union_test:
step_size = int(max(float(num_permutations) / 20.0, 1.0))
if GRAPH_MODE:
print("%d permutations" % num_permutations)
+
+ areas = [x.area() for x in polys]
+
for i, permutation in enumerate(
- itertools.islice(
+ itertools.islice(
itertools.permutations(polys),
None, None, step_size)):
filename = '%s_union_%04d.svg' % (
@@ -47,9 +54,7 @@ class union_test:
union = polygon.SphericalPolygon.multi_union(
permutation)
unions.append(union)
- areas = [x.area() for x in permutation]
union_area = union.area()
- assert np.all(union_area >= areas)
if GRAPH_MODE:
fig = plt.figure()
@@ -66,10 +71,12 @@ class union_test:
plt.savefig(filename)
fig.clear()
+ assert np.all(union_area >= areas)
+
lengths = np.array([len(x._points) for x in unions])
assert np.all(lengths == [lengths[0]])
areas = np.array([x.area() for x in unions])
- # assert_array_almost_equal(areas, areas[0], 1)
+ assert_array_almost_equal(areas, areas[0], 1)
return run