Beispiel #1
0
def single_face_delaunay(face_verts,
                         add_verts,
                         epsilon=1e-6,
                         exclude_boundary=True):
    n = len(face_verts)
    face = list(range(n))
    edges = [(i, i + 1) for i in range(n - 1)] + [(n - 1, 0)]
    plane = linear_approximation(face_verts).most_similar_plane()
    face_verts_2d = [plane.point_uv_projection(v) for v in face_verts]
    if exclude_boundary:
        add_verts = [
            v for v in add_verts
            if not is_on_face_edge(v, face_verts, epsilon)
        ]
    add_verts_2d = [plane.point_uv_projection(v) for v in add_verts]
    TRIANGLES = 1
    res = delaunay_2d_cdt(face_verts_2d + add_verts_2d, edges, [face],
                          TRIANGLES, epsilon)
    new_verts_2d = res[0]
    new_edges = res[1]
    new_faces = res[2]
    new_add_verts = [
        tuple(plane.evaluate(p[0], p[1], normalize=True))
        for p in new_verts_2d[n:]
    ]
    return face_verts + new_add_verts, new_edges, new_faces
def delaunay_triangulate(context, obj, output_type, epsilon):
    depsgraph = context.evaluated_depsgraph_get()
    obj_eval = obj.evaluated_get(depsgraph)
    mesh_eval = obj_eval.to_mesh()

    vert_coords = [vtx.co.to_2d() for vtx in mesh_eval.vertices]
    edges = [edge.vertices for edge in mesh_eval.edges]
    faces = [[mesh_eval.loops[loop_index].vertex_index for loop_index in face.loop_indices] for face in mesh_eval.polygons]

    (out_coords, out_edges, out_faces, orig_verts, orig_edges, orig_faces) = delaunay_2d_cdt(vert_coords, edges, faces, output_type, epsilon)

    obj_eval.to_mesh_clear()
    #bpy.data.meshes.remove(mesh_eval)

    return ([co.to_3d() for co in out_coords], out_edges, out_faces)
Beispiel #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
    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
    def execute(self, context):
        w = context.window
        w.cursor_set('WAIT')
        t0 = perf_clock()
        #Get selected obj
        objs = context.selected_objects
        if len(objs) == 0 or len(objs) > 1:
            self.report({'INFO'},
                        "Selection is empty or too much object selected")
            return {'CANCELLED'}
        obj = objs[0]
        if obj.type != 'MESH':
            self.report({'INFO'}, "Selection isn't a mesh")
            return {'CANCELLED'}
        #Get points coodinates
        #bpy.ops.object.transform_apply(rotation=True, scale=True)
        r = obj.rotation_euler
        s = obj.scale
        mesh = obj.data

        if NATIVE:
            '''
			Use native Delaunay triangulation function : delaunay_2d_cdt(verts, edges, faces, output_type, epsilon) >> [verts, edges, faces, orig_verts, orig_edges, orig_faces]
			The three returned orig lists give, for each of verts, edges, and faces, the list of input element indices corresponding to the positionally same output element. For edges, the orig indices start with the input edges and then continue with the edges implied by each of the faces (n of them for an n-gon).
			Output type :
			# 0 => triangles with convex hull.
			# 1 => triangles inside constraints.
			# 2 => the input constraints, intersected.
			# 3 => like 2 but with extra edges to make valid BMesh faces.
			'''
            log.info("Triangulate {} points...".format(len(mesh.vertices)))
            verts, edges, faces, overts, oedges, ofaces = delaunay_2d_cdt(
                [v.co.to_2d() for v in mesh.vertices], [], [], 0, 0.1)
            verts = [(v.x, v.y, mesh.vertices[overts[i][0]].co.z)
                     for i, v in enumerate(verts)]  #retrieve z values
            log.info("Getting {} triangles".format(len(faces)))
            log.info("Create mesh...")
            tinMesh = bpy.data.meshes.new("TIN")
            tinMesh.from_pydata(verts, edges, faces)
            tinMesh.update()
        else:
            vertsPts = [vertex.co for vertex in mesh.vertices]
            #Remove duplicate
            verts = [[vert.x, vert.y, vert.z] for vert in vertsPts]
            nDupli, nZcolinear = unique(verts)
            nVerts = len(verts)
            log.info("{} duplicates points ignored".format(nDupli))
            log.info("{} z colinear points excluded".format(nZcolinear))
            if nVerts < 3:
                self.report({'ERROR'}, "Not enough points")
                return {'CANCELLED'}
            #Check colinear
            xValues = [pt[0] for pt in verts]
            yValues = [pt[1] for pt in verts]
            if checkEqual(xValues) or checkEqual(yValues):
                self.report({'ERROR'}, "Points are colinear")
                return {'CANCELLED'}
            #Triangulate
            log.info("Triangulate {} points...".format(nVerts))
            vertsPts = [Point(vert[0], vert[1], vert[2]) for vert in verts]
            faces = computeDelaunayTriangulation(vertsPts)
            faces = [
                tuple(reversed(tri)) for tri in faces
            ]  #reverse point order --> if all triangles are specified anticlockwise then all faces up
            log.info("Getting {} triangles".format(len(faces)))
            #Create new mesh structure
            log.info("Create mesh...")
            tinMesh = bpy.data.meshes.new("TIN")  #create a new mesh
            tinMesh.from_pydata(verts, [],
                                faces)  #Fill the mesh with triangles
            tinMesh.update(calc_edges=True)  #Update mesh with new data

        #Create an object with that mesh
        tinObj = bpy.data.objects.new("TIN", tinMesh)
        #Place object
        tinObj.location = obj.location.copy()
        tinObj.rotation_euler = r
        tinObj.scale = s
        #Update scene
        context.scene.collection.objects.link(tinObj)  #Link object to scene
        context.view_layer.objects.active = tinObj
        tinObj.select_set(True)
        obj.select_set(False)
        #Report
        t = round(perf_clock() - t0, 2)
        msg = "{} triangles created in {} seconds".format(len(faces), t)
        self.report({'INFO'}, msg)
        #log.info(msg) #duplicate log
        return {'FINISHED'}