You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
6.7 KiB
Python
167 lines
6.7 KiB
Python
from __future__ import print_function
|
|
import numpy as np
|
|
import itertools
|
|
from numpy.testing import (assert_equal,
|
|
assert_almost_equal,
|
|
assert_array_equal,
|
|
assert_array_almost_equal)
|
|
from pytest import raises as assert_raises
|
|
from scipy.spatial import SphericalVoronoi, distance
|
|
from scipy.spatial import _spherical_voronoi as spherical_voronoi
|
|
|
|
|
|
class TestCircumcenters(object):
|
|
|
|
def test_circumcenters(self):
|
|
tetrahedrons = np.array([
|
|
[[1, 2, 3],
|
|
[-1.1, -2.1, -3.1],
|
|
[-1.2, 2.2, 3.2],
|
|
[-1.3, -2.3, 3.3]],
|
|
[[10, 20, 30],
|
|
[-10.1, -20.1, -30.1],
|
|
[-10.2, 20.2, 30.2],
|
|
[-10.3, -20.3, 30.3]]
|
|
])
|
|
|
|
result = spherical_voronoi.calc_circumcenters(tetrahedrons)
|
|
|
|
expected = [
|
|
[-0.5680861153262529, -0.133279590288315, 0.1843323216995444],
|
|
[-0.5965330784014926, -0.1480377040397778, 0.1981967854886021]
|
|
]
|
|
|
|
assert_array_almost_equal(result, expected)
|
|
|
|
|
|
class TestProjectToSphere(object):
|
|
|
|
def test_unit_sphere(self):
|
|
points = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
|
center = np.array([0, 0, 0])
|
|
radius = 1
|
|
projected = spherical_voronoi.project_to_sphere(points, center, radius)
|
|
assert_array_almost_equal(points, projected)
|
|
|
|
def test_scaled_points(self):
|
|
points = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
|
center = np.array([0, 0, 0])
|
|
radius = 1
|
|
scaled = points * 2
|
|
projected = spherical_voronoi.project_to_sphere(scaled, center, radius)
|
|
assert_array_almost_equal(points, projected)
|
|
|
|
def test_translated_sphere(self):
|
|
points = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
|
|
center = np.array([1, 2, 3])
|
|
translated = points + center
|
|
radius = 1
|
|
projected = spherical_voronoi.project_to_sphere(translated, center,
|
|
radius)
|
|
assert_array_almost_equal(translated, projected)
|
|
|
|
|
|
class TestSphericalVoronoi(object):
|
|
|
|
def setup_method(self):
|
|
self.points = np.array([
|
|
[-0.78928481, -0.16341094, 0.59188373],
|
|
[-0.66839141, 0.73309634, 0.12578818],
|
|
[0.32535778, -0.92476944, -0.19734181],
|
|
[-0.90177102, -0.03785291, -0.43055335],
|
|
[0.71781344, 0.68428936, 0.12842096],
|
|
[-0.96064876, 0.23492353, -0.14820556],
|
|
[0.73181537, -0.22025898, -0.6449281],
|
|
[0.79979205, 0.54555747, 0.25039913]]
|
|
)
|
|
|
|
def test_constructor(self):
|
|
center = np.array([1, 2, 3])
|
|
radius = 2
|
|
s1 = SphericalVoronoi(self.points)
|
|
# user input checks in SphericalVoronoi now require
|
|
# the radius / center to match the generators so adjust
|
|
# accordingly here
|
|
s2 = SphericalVoronoi(self.points * radius, radius)
|
|
s3 = SphericalVoronoi(self.points + center, None, center)
|
|
s4 = SphericalVoronoi(self.points * radius + center, radius, center)
|
|
assert_array_equal(s1.center, np.array([0, 0, 0]))
|
|
assert_equal(s1.radius, 1)
|
|
assert_array_equal(s2.center, np.array([0, 0, 0]))
|
|
assert_equal(s2.radius, 2)
|
|
assert_array_equal(s3.center, center)
|
|
assert_equal(s3.radius, 1)
|
|
assert_array_equal(s4.center, center)
|
|
assert_equal(s4.radius, radius)
|
|
|
|
def test_vertices_regions_translation_invariance(self):
|
|
sv_origin = SphericalVoronoi(self.points)
|
|
center = np.array([1, 1, 1])
|
|
sv_translated = SphericalVoronoi(self.points + center, None, center)
|
|
assert_array_equal(sv_origin.regions, sv_translated.regions)
|
|
assert_array_almost_equal(sv_origin.vertices + center,
|
|
sv_translated.vertices)
|
|
|
|
def test_vertices_regions_scaling_invariance(self):
|
|
sv_unit = SphericalVoronoi(self.points)
|
|
sv_scaled = SphericalVoronoi(self.points * 2, 2)
|
|
assert_array_equal(sv_unit.regions, sv_scaled.regions)
|
|
assert_array_almost_equal(sv_unit.vertices * 2,
|
|
sv_scaled.vertices)
|
|
|
|
def test_sort_vertices_of_regions(self):
|
|
sv = SphericalVoronoi(self.points)
|
|
unsorted_regions = sv.regions
|
|
sv.sort_vertices_of_regions()
|
|
assert_array_equal(sorted(sv.regions), sorted(unsorted_regions))
|
|
|
|
def test_sort_vertices_of_regions_flattened(self):
|
|
expected = sorted([[0, 6, 5, 2, 3], [2, 3, 10, 11, 8, 7], [0, 6, 4, 1], [4, 8,
|
|
7, 5, 6], [9, 11, 10], [2, 7, 5], [1, 4, 8, 11, 9], [0, 3, 10, 9,
|
|
1]])
|
|
expected = list(itertools.chain(*sorted(expected)))
|
|
sv = SphericalVoronoi(self.points)
|
|
sv.sort_vertices_of_regions()
|
|
actual = list(itertools.chain(*sorted(sv.regions)))
|
|
assert_array_equal(actual, expected)
|
|
|
|
def test_num_vertices(self):
|
|
# for any n >= 3, a spherical Voronoi diagram has 2n - 4
|
|
# vertices; this is a direct consequence of Euler's formula
|
|
# as explained by Dinis and Mamede (2010) Proceedings of the
|
|
# 2010 International Symposium on Voronoi Diagrams in Science
|
|
# and Engineering
|
|
sv = SphericalVoronoi(self.points)
|
|
expected = self.points.shape[0] * 2 - 4
|
|
actual = sv.vertices.shape[0]
|
|
assert_equal(actual, expected)
|
|
|
|
def test_voronoi_circles(self):
|
|
sv = spherical_voronoi.SphericalVoronoi(self.points)
|
|
for vertex in sv.vertices:
|
|
distances = distance.cdist(sv.points,np.array([vertex]))
|
|
closest = np.array(sorted(distances)[0:3])
|
|
assert_almost_equal(closest[0], closest[1], 7, str(vertex))
|
|
assert_almost_equal(closest[0], closest[2], 7, str(vertex))
|
|
|
|
def test_duplicate_point_handling(self):
|
|
# an exception should be raised for degenerate generators
|
|
# related to Issue# 7046
|
|
self.degenerate = np.concatenate((self.points, self.points))
|
|
with assert_raises(ValueError):
|
|
sv = spherical_voronoi.SphericalVoronoi(self.degenerate)
|
|
|
|
def test_incorrect_radius_handling(self):
|
|
# an exception should be raised if the radius provided
|
|
# cannot possibly match the input generators
|
|
with assert_raises(ValueError):
|
|
sv = spherical_voronoi.SphericalVoronoi(self.points,
|
|
radius=0.98)
|
|
|
|
def test_incorrect_center_handling(self):
|
|
# an exception should be raised if the center provided
|
|
# cannot possibly match the input generators
|
|
with assert_raises(ValueError):
|
|
sv = spherical_voronoi.SphericalVoronoi(self.points,
|
|
center=[0.1,0,0])
|