예제 #1
0
class SphericalVorAreas(Benchmark):
    params = [10, 100, 1000, 5000, 10000]
    param_names = ['num_points']

    def setup(self, num_points):
        self.points = generate_spherical_points(num_points)
        self.sv = SphericalVoronoi(self.points, radius=1, center=np.zeros(3))

    def time_spherical_polygon_area_calculation(self, num_points):
        """Time the area calculation in the Spherical Voronoi code."""
        self.sv.calculate_areas()
예제 #2
0
 def test_area_reconstitution(self, radius, center):
     for points in [self.points, self.hemisphere_points,
                    self.hemisphere_points2]:
         sv = SphericalVoronoi(radius * points + center,
                               radius=radius,
                               center=center)
         areas = sv.calculate_areas()
         assert_almost_equal(areas.sum(), 4 * np.pi * radius**2)
예제 #3
0
    def test_area_reconstitution_large_input(self, radius):
        np.random.seed(0)
        n = 1000
        points = np.random.uniform(-1, 1, (n, 3))
        points /= np.linalg.norm(points, axis=1).reshape((n, 1))

        sv = SphericalVoronoi(radius * points, radius=radius)
        areas = sv.calculate_areas()
        assert_almost_equal(areas.sum(), 4 * np.pi * radius**2)
예제 #4
0
 def test_ultra_close_gens(self):
     # use geometric_slerp to produce generators that
     # are close together, to push the limits
     # of the area (angle) calculations
     # also, limit generators to a single hemisphere
     path = geometric_slerp([0, 0, 1], [1, 0, 0], t=np.linspace(0, 1, 1000))
     sv = SphericalVoronoi(path)
     areas = sv.calculate_areas()
     assert_almost_equal(areas.sum(), 4 * np.pi)
예제 #5
0
    def test_area_reconstitution(self, n, dim, radius, shift,
                                 single_hemisphere):
        points = _sample_sphere(n, dim, seed=0)

        # move all points to one side of the sphere for single-hemisphere test
        if single_hemisphere:
            points[:, 0] = np.abs(points[:, 0])

        center = (np.arange(dim) + 1) * shift
        points = radius * points + center

        sv = SphericalVoronoi(points, radius=radius, center=center)
        areas = sv.calculate_areas()
        assert_almost_equal(areas.sum(), _hypersphere_area(dim, radius))
예제 #6
0
 def test_area_unsupported_dimension(self):
     dim = 4
     points = np.concatenate((-np.eye(dim), np.eye(dim)))
     sv = SphericalVoronoi(points)
     with pytest.raises(TypeError, match="Only supported"):
         sv.calculate_areas()
예제 #7
0
 def test_equal_area_reconstitution(self, poly):
     points = _generate_polytope(poly)
     n, dim = points.shape
     sv = SphericalVoronoi(points)
     areas = sv.calculate_areas()
     assert_almost_equal(areas, _hypersphere_area(dim, 1) / n)
예제 #8
0
 def test_equal_area_regions(self, poly):
     points = _generate_polyhedron(poly)
     sv = SphericalVoronoi(points)
     areas = sv.calculate_areas()
     assert_almost_equal(areas, 4 * np.pi / len(points))
def createGraph(planet, planetGenerator):
    #the sphere is spanned into regions of closer points to the seeds with a spherical Voronoi mapping.
    sv = SphericalVoronoi(planet.meshPoints)
    sv.sort_vertices_of_regions()

    #ensure that the polygon is clockwise oriented and correct it if not.
    #For plotting, all the polygons must have the same orientation.
    for i, region in enumerate(sv.regions):
        if (np.dot(np.cross(sv.points[i], sv.vertices[region[0]]),
                   sv.vertices[region[1]]) > 0):
            sv.regions[i].reverse()

    #the graph of regions centers is created. This is useful for checking travel between regions.
    #At this point it is not yet possible to set the connections between regions.
    centers = Graph(directed=False)
    centers.add_vertex(len(sv.regions))

    #for each cell, register the corners points index delimiting it.
    centers.vertex_properties["corners"] = centers.new_vertex_property(
        "vector<int>")
    for v, corners in zip(centers.vertices(), sv.regions):
        centers.vp.corners[v] = corners

    #for each cell, set its center point.
    centers.vertex_properties["center"] = centers.new_vertex_property(
        "vector<float>")
    for v, center in zip(centers.vertices(), sv.points):
        centers.vp.center[v] = center

    #for each cell, set its area in km^2. This is often used as a weight for the cell.
    centers.vertex_properties["area"] = centers.new_vertex_property("float")
    for v, area in zip(centers.vertices(), sv.calculate_areas()):
        centers.vp.area[v] = area * planet.parameters.radius**2

    #create the graph of corners points. It is the dual of the graph centers.
    #this graph is useful to plot the borders and check touching regions.
    corners = Graph(directed=False)
    corners.add_vertex(len(sv.vertices))

    #for each corner, register its position.
    corners.vertex_properties["position"] = corners.new_vertex_property(
        "vector<float>")
    for v, position in zip(corners.vertices(), sv.vertices):
        corners.vp.position[v] = position

    #set the edges between corners
    cornerLinks = []
    for region in sv.regions:
        cornerLinks += [(min(i, j), max(i, j))
                        for (i, j) in pairwiseRoll(region)]
    #the edges are converted to dictionnary and back to a list to remove the doublons
    corners.add_edge_list(list(dict.fromkeys(cornerLinks)))

    #set the polygons that each corner touches
    corners.vertex_properties["touches"] = corners.new_vertex_property(
        "vector<int>")
    for i, cornerList in enumerate(centers.vp.corners):
        for corner in cornerList:
            corners.vp.touches[corner].append(i)

    #compute length of each border in km
    corners.edge_properties["length"] = corners.new_edge_property("float")
    edges = corners.get_edges()
    positions = np.array(list(corners.vp.position))[edges]
    lengths = np.arccos(np.sum(positions[:, 0] * positions[:, 1],
                               axis=-1)) * planet.parameters.radius
    for i, e in enumerate(corners.edges()):
        corners.ep.length[e] = lengths[i]
    corners.edge_properties["separates"] = corners.new_edge_property(
        "vector<int>")
    for e in corners.edges():
        corners.ep.separates[e] = list(
            set(corners.vp.touches[e.source()]).intersection(
                corners.vp.touches[e.target()]))

    #add links between regions
    centerLinks = []
    for c in corners.vertices():
        l = corners.vp.touches[c]
        centerLinks += [(min(i, j), max(i, j)) for (i, j) in pairwiseRoll(l)]
    centers.add_edge_list(list(dict.fromkeys(centerLinks)))

    #compute distance between regions in km
    centers.edge_properties["length"] = centers.new_edge_property("float")
    edges = centers.get_edges()
    positions = np.array(list(centers.vp.center))[edges]
    lengths = np.arccos(np.sum(positions[:, 0] * positions[:, 1],
                               axis=-1)) * planet.parameters.radius
    for i, e in enumerate(centers.edges()):
        centers.ep.length[e] = lengths[i]

    planet.meshCenters = centers
    planet.meshCorners = corners

    def plotTilesBorders(self, ax, *args, **kwargs):
        edges = self.meshCorners.get_edges()
        segments = np.array(list(self.meshCorners.vp.position))[edges]
        (x, y, z) = np.shape(segments)
        segments = np.reshape(segments, (x * y, z))
        lat, long = Projection().toLatLong(segments)
        lat = np.reshape(lat, (x, y))
        long = np.reshape(long, (x, y))
        lines = [[(slong[0], slat[0]), (slong[1], slat[1])]
                 for slat, slong in zip(lat, long)]
        ax.add_collection(
            mc.LineCollection(lines,
                              *args,
                              transform=ccrs.Geodetic(),
                              **kwargs))

    planet.plotTilesBorders = types.MethodType(plotTilesBorders, planet)

    def plotTilesJunctions(self, ax, *args, **kwargs):
        edges = self.meshCenters.get_edges()
        segments = np.array(list(self.meshCenters.vp.center))[edges]
        (x, y, z) = np.shape(segments)
        segments = np.reshape(segments, (x * y, z))
        lat, long = Projection().toLatLong(segments)
        lat = np.reshape(lat, (x, y))
        long = np.reshape(long, (x, y))
        lines = [[(slong[0], slat[0]), (slong[1], slat[1])]
                 for slat, slong in zip(lat, long)]
        ax.add_collection(
            mc.LineCollection(lines,
                              *args,
                              transform=ccrs.Geodetic(),
                              **kwargs))

    planet.plotTilesJunctions = types.MethodType(plotTilesJunctions, planet)