Map per-vertex per-face attribute from mesh1 to mesh2 based on closest points. Args: mesh1 (:class:`Mesh`): Source mesh, where the attribute is defined. mesh2 (:class:`Mesh`): Target mesh, where the attribute is mapped to. attr_name (``string``): Attribute name.
(mesh1, mesh2, attr_name, bvh=None)
| 80 | mesh2.set_attribute(attr_name, target_val) |
| 81 | |
| 82 | def map_corner_attribute(mesh1, mesh2, attr_name, bvh=None): |
| 83 | """ Map per-vertex per-face attribute from mesh1 to mesh2 based on closest points. |
| 84 | |
| 85 | Args: |
| 86 | mesh1 (:class:`Mesh`): Source mesh, where the attribute is defined. |
| 87 | mesh2 (:class:`Mesh`): Target mesh, where the attribute is mapped to. |
| 88 | attr_name (``string``): Attribute name. |
| 89 | bvh (:class:`BVH`): Pre-computed Bounded volume hierarchy if available. |
| 90 | |
| 91 | A new attribute with name ``attr_name`` is added to ``mesh2``. |
| 92 | """ |
| 93 | |
| 94 | assert(mesh1.dim == mesh2.dim) |
| 95 | assert(mesh1.vertex_per_face == 3) |
| 96 | assert(mesh2.vertex_per_face == 3) |
| 97 | assert(mesh1.has_attribute(attr_name)) |
| 98 | values = mesh1.get_attribute(attr_name).reshape( |
| 99 | (mesh1.num_faces, mesh1.vertex_per_face, -1)) |
| 100 | |
| 101 | if not mesh2.has_attribute("face_centroid"): |
| 102 | mesh2.add_attribute("face_centroid") |
| 103 | centroids = mesh2.get_face_attribute("face_centroid") |
| 104 | |
| 105 | if bvh is None: |
| 106 | bvh = BVH(dim=mesh1.dim) |
| 107 | bvh.load_mesh(mesh1) |
| 108 | |
| 109 | v_dists, v_closest_faces, v_p = bvh.lookup(mesh2.vertices) |
| 110 | f_dists, f_closest_faces, f_p = bvh.lookup(centroids) |
| 111 | |
| 112 | p0 = v_p[mesh2.faces[:,0], :] |
| 113 | p1 = v_p[mesh2.faces[:,1], :] |
| 114 | p2 = v_p[mesh2.faces[:,2], :] |
| 115 | |
| 116 | vertices = mesh1.vertices |
| 117 | faces = mesh1.faces |
| 118 | v0 = vertices[faces[f_closest_faces,0],:] |
| 119 | v1 = vertices[faces[f_closest_faces,1],:] |
| 120 | v2 = vertices[faces[f_closest_faces,2],:] |
| 121 | |
| 122 | p0_a01 = np.linalg.norm(np.cross(v0-p0, v1-p0), axis=1).reshape((-1,1)) |
| 123 | p0_a12 = np.linalg.norm(np.cross(v1-p0, v2-p0), axis=1).reshape((-1,1)) |
| 124 | p0_a20 = np.linalg.norm(np.cross(v2-p0, v0-p0), axis=1).reshape((-1,1)) |
| 125 | p1_a01 = np.linalg.norm(np.cross(v0-p1, v1-p1), axis=1).reshape((-1,1)) |
| 126 | p1_a12 = np.linalg.norm(np.cross(v1-p1, v2-p1), axis=1).reshape((-1,1)) |
| 127 | p1_a20 = np.linalg.norm(np.cross(v2-p1, v0-p1), axis=1).reshape((-1,1)) |
| 128 | p2_a01 = np.linalg.norm(np.cross(v0-p2, v1-p2), axis=1).reshape((-1,1)) |
| 129 | p2_a12 = np.linalg.norm(np.cross(v1-p2, v2-p2), axis=1).reshape((-1,1)) |
| 130 | p2_a20 = np.linalg.norm(np.cross(v2-p2, v0-p2), axis=1).reshape((-1,1)) |
| 131 | |
| 132 | a = p0_a01 + p0_a12 + p0_a20 |
| 133 | |
| 134 | val_p0 = (values[f_closest_faces, 0, :] * p0_a12 +\ |
| 135 | values[f_closest_faces, 1, :] * p0_a20 +\ |
| 136 | values[f_closest_faces, 2, :] * p0_a01) / a |
| 137 | val_p1 = (values[f_closest_faces, 0, :] * p1_a12 +\ |
| 138 | values[f_closest_faces, 1, :] * p1_a20 +\ |
| 139 | values[f_closest_faces, 2, :] * p1_a01) / a |
nothing calls this directly
no test coverage detected