예제 #1
0
    def process(self):

        if not self.inputs['Vertices'].is_linked:
            return

        if not self.outputs['Vertices'].is_linked:
            return

        points_in = self.inputs['Vertices'].sv_get()

        pts_out = []
        # polys_out = []
        edges_out = []
        for obj in points_in:
            pt_list = []
            x_max = obj[0][0]
            x_min = obj[0][0]
            y_min = obj[0][1]
            y_max = obj[0][1]
            # creates points in format for voronoi library, throwing away z
            for pt in obj:
                x, y = pt[0], pt[1]
                x_max = max(x, x_max)
                x_min = min(x, x_min)
                y_max = max(y, y_max)
                y_min = min(x, x_min)
                pt_list.append(Site(pt[0], pt[1]))

            res = computeVoronoiDiagram(pt_list)

            edges = res[2]
            delta = self.clip
            x_max = x_max + delta
            y_max = y_max + delta

            x_min = x_min - delta
            y_min = y_min - delta

            # clipping box to bounding box.
            pts_tmp = []
            for pt in res[0]:
                x, y = pt[0], pt[1]
                if x < x_min:
                    x = x_min
                if x > x_max:
                    x = x_max

                if y < y_min:
                    y = y_min
                if y > y_max:
                    y = y_max
                pts_tmp.append((x, y, 0))

            pts_out.append(pts_tmp)
            edges_out.append([(edge[1], edge[2]) for edge in edges
                              if -1 not in edge])

        # outputs
        self.outputs['Vertices'].sv_set(pts_out)
        self.outputs['Edges'].sv_set(edges_out)
예제 #2
0
def get_delaunay_triangulation(verts_in):
    pt_list = [Site(pt[0], pt[1]) for pt in verts_in]
    res = computeDelaunayTriangulation(pt_list)
    polys_in = [tri for tri in res if -1 not in tri]
    #all faces hase normals -Z, should be reversed
    polys_in = [pol[::-1] for pol in polys_in]
    edges_in = pols_edges([polys_in], unique_edges=True)[0]
    return edges_in, polys_in
예제 #3
0
def delaunay_triangulatrion(samples_u, samples_v, us_list, vs_list, u_coeff,
                            v_coeff, epsilon):
    #if delaunay_2d_cdt is None:
    # Pure-python implementation
    points_uv = [
        Site(u * u_coeff, v * v_coeff) for u, v in zip(us_list, vs_list)
    ]
    faces = computeDelaunayTriangulation(points_uv)
    return faces
예제 #4
0
    def process(self):

        if not self.inputs['Vertices'].is_linked:
            return
        if not self.outputs['Polygons'].is_linked:
            return

        tris_out = []
        points_in = []
        points_in = self.inputs['Vertices'].sv_get()

        for obj in points_in:
            pt_list = [Site(pt[0], pt[1]) for pt in obj]
            res = computeDelaunayTriangulation(pt_list)
            tris_out.append([tri for tri in res if -1 not in tri])

        self.outputs['Polygons'].sv_set(tris_out)
예제 #5
0
    def process(self):
        points_in = []
        if not ('Polygons' in self.outputs
                and self.outputs['Polygons'].is_linked):
            return
        if 'Vertices' in self.inputs and self.inputs['Vertices'].is_linked:
            points_in = SvGetSocketAnyType(self, self.inputs['Vertices'])
        tris_out = []

        for obj in points_in:

            pt_list = [Site(pt[0], pt[1]) for pt in obj]
            res = computeDelaunayTriangulation(pt_list)
            tris_out.append([tri for tri in res if -1 not in tri])

        if 'Polygons' in self.outputs and self.outputs['Polygons'].is_linked:
            SvSetSocketAnyType(self, 'Polygons', tris_out)
예제 #6
0
def delaunay_triangulatrion(samples_u, samples_v, us_list, vs_list, u_coeff,
                            v_coeff, epsilon):
    if delaunay_2d_cdt is None:
        # Pure-python implementation
        points_uv = [
            Site(u * u_coeff, v * v_coeff) for u, v in zip(us_list, vs_list)
        ]
        faces = computeDelaunayTriangulation(points_uv)
        return faces
    else:
        points_scaled = [(u * u_coeff, v * v_coeff)
                         for u, v in zip(us_list, vs_list)]
        INNER = 1
        # delaunay_2d_cdt function wont' work if we do not provide neither edges nor faces.
        # So let's just construct the outer faces of the rectangular grid
        # (indices in `edges' depend on the fact that in `adaptive_subdivide` we
        # add randomly generated points to the end of us_list/vs_list).
        edges = make_outer_edges(samples_v, samples_u)
        vert_coords, edges, faces, orig_verts, orig_edges, orig_faces = delaunay_2d_cdt(
            points_scaled, edges, [], INNER, epsilon)
        return faces
예제 #7
0
    def process(self):

        if not self.inputs['Vertices'].is_linked:
            return

        if not self.outputs['Vertices'].is_linked:
            return

        points_in = self.inputs['Vertices'].sv_get()

        pts_out = []
        # polys_out = []
        edges_out = []
        for obj in points_in:
            bounds = Bounds.new(self.bound_mode)
            source_sites = []
            bounds.x_max = -BIG_FLOAT
            bounds.x_min = BIG_FLOAT
            bounds.y_min = BIG_FLOAT
            bounds.y_max = -BIG_FLOAT
            x0, y0, z0 = center(obj)
            bounds.center = (x0, y0)
            # creates points in format for voronoi library, throwing away z
            for x, y, z in obj:
                r = sqrt((x - x0)**2 + (y - y0)**2)
                bounds.r_max = max(r, bounds.r_max)
                bounds.x_max = max(x, bounds.x_max)
                bounds.x_min = min(x, bounds.x_min)
                bounds.y_max = max(y, bounds.y_max)
                bounds.y_min = min(y, bounds.y_min)
                source_sites.append(Site(x, y))

            delta = self.clip
            bounds.x_max = bounds.x_max + delta
            bounds.y_max = bounds.y_max + delta

            bounds.x_min = bounds.x_min - delta
            bounds.y_min = bounds.y_min - delta

            bounds.r_max = bounds.r_max + delta

            voronoi_data = computeVoronoiDiagram(source_sites)
            verts = voronoi_data.vertices
            lines = voronoi_data.lines
            all_edges = voronoi_data.edges

            finite_edges = [(edge[1], edge[2]) for edge in all_edges
                            if -1 not in edge]
            bm = Mesh2D.from_pydata(verts, finite_edges)

            # clipping box to bounding box.
            verts_to_remove = set()
            edges_to_remove = set()
            bounding_verts = []

            # For each diagram vertex that is outside of the bounds,
            # cut each edge connected with that vertex by bounding line.
            # Remove such vertices, remove such edges, and instead add
            # vertices lying on the bounding line and corresponding edges.
            for vert_idx, vert in enumerate(bm.verts[:]):
                x, y = tuple(vert)
                if not bounds.contains((x, y)):
                    verts_to_remove.add(vert_idx)
                    for other_vert_idx in list(bm.linked_verts[vert_idx]):
                        edges_to_remove.add((vert_idx, other_vert_idx))
                        if self.draw_hangs or self.draw_bounds:
                            other_vert = bm.verts[other_vert_idx]
                            if other_vert is not None:
                                x2, y2 = tuple(other_vert)
                                intersection = bounds.segment_intersection(
                                    (x, y), (x2, y2))
                                if intersection is not None:
                                    intersection = tuple(intersection)
                                    new_vert_idx = bm.new_vert(intersection)
                                    bounding_verts.append(new_vert_idx)
                                    #info("CLIP: Added point: %s => %s", (x_i, y_i), new_vert_idx)
                                    bm.new_edge(other_vert_idx, new_vert_idx)

            # Diagram lines that go infinitely from one side of diagram to another
            infinite_lines = []
            # Lines that start at the one vertex of the diagram and go to infinity
            rays = defaultdict(list)
            if self.draw_hangs or self.draw_bounds:
                sites_by_line = defaultdict(list)

                for site_idx in voronoi_data.polygons.keys():
                    for line_index, i1, i2 in voronoi_data.polygons[site_idx]:
                        if i1 == -1 or i2 == -1:
                            site = source_sites[site_idx]
                            sites_by_line[line_index].append((site.x, site.y))

                for line_index, i1, i2 in all_edges:
                    if i1 == -1 or i2 == -1:
                        line = lines[line_index]
                        a, b, c = line
                        eqn = LineEquation2D(a, b, -c)
                        if i1 == -1 and i2 != -1:
                            eqn.sites = sites_by_line[line_index]
                            rays[i2].append(eqn)
                        elif i2 == -1 and i1 != -1:
                            eqn.sites = sites_by_line[line_index]
                            rays[i1].append(eqn)
                        elif i1 == -1 and i2 == -1:
                            infinite_lines.append(eqn)

                # For each (half-infinite) ray, calculate it's intersection
                # with the bounding line and draw an edge from ray's beginning to
                # the bounding line.
                # NB: The data returned from voronoi.py for such lines
                # is a vertex and a line equation. The line obviously intersects
                # the bounding line in two points; which one should we choose?
                # Let's choose that one which is closer to site points which the
                # line is dividing.
                for vert_index in rays.keys():
                    x, y = bm.verts[vert_index]
                    vert = Vector((x, y))
                    if vert_index not in verts_to_remove:
                        for line in rays[vert_index]:
                            intersection = bounds.ray_intersection(vert, line)
                            intersection = tuple(intersection)
                            new_vert_idx = bm.new_vert(intersection)
                            bounding_verts.append(new_vert_idx)
                            #info("INF: Added point: %s: %s => %s", (x,y), (x_i, y_i), new_vert_idx)
                            bm.new_edge(vert_index, new_vert_idx)

                # For each infinite (in two directions) line,
                # calculate two it's intersections with the bounding
                # line and connect them by an edge.
                for eqn in infinite_lines:
                    intersections = bounds.line_intersection(eqn)
                    if len(intersections) == 2:
                        v1, v2 = intersections
                        new_vert_1_idx = bm.new_vert(tuple(v1))
                        new_vert_2_idx = bm.new_vert(tuple(v2))
                        bounding_verts.append(new_vert_1_idx)
                        bounding_verts.append(new_vert_2_idx)
                        bm.new_edge(new_vert_1_idx, new_vert_2_idx)
                    else:
                        self.error(
                            "unexpected number of intersections of infinite line %s with area bounds: %s",
                            eqn, intersections)

                # TODO: there could be (finite) edges, which have both ends
                # outside of the bounding line. We could detect such edges and
                # process similarly to infinite lines - calculate two intersections
                # with the bounding line and connect them by an edge.
                # Currently I consider such cases as rare, so this is a low priority issue.
                # Btw, such edges do not fall under definition of either "bounding edge"
                # or "hanging edge"; so should we add a separate checkbox for such edges?...

            if self.draw_bounds and bounding_verts:
                bounding_verts.sort(
                    key=lambda idx: atan2(bm.verts[idx][1], bm.verts[idx][0]))
                for i, j in zip(bounding_verts, bounding_verts[1:]):
                    bm.new_edge(i, j)
                bm.new_edge(bounding_verts[-1], bounding_verts[0])

            for i, j in edges_to_remove:
                bm.remove_edge(i, j)
            for vert_idx in verts_to_remove:
                bm.verts[vert_idx] = None

            verts, edges = bm.to_pydata()

            verts3d = [(vert[0], vert[1], 0) for vert in verts]
            pts_out.append(verts3d)
            edges_out.append(edges)
            #edges_out.append(finite_edges)

        # outputs
        self.outputs['Vertices'].sv_set(pts_out)
        self.outputs['Edges'].sv_set(edges_out)