def volume_curvature_normal_smooth(triangles, vertices, nb_iter=1, diffusion_step=1.0, area_weighted=False, backward_step=False, flow_file=None): if isinstance(diffusion_step, (int, float)): diffusion_step = diffusion_step * np.ones(len(vertices)) if flow_file is not None: mem_map = np.memmap(flow_file, dtype=G_DTYPE, mode='w+', shape=(nb_iter, vertices.shape[0], vertices.shape[1])) for i in range(nb_iter): stdout.write("\r step %d on %d done" % (i, nb_iter)) stdout.flush() if flow_file is not None: mem_map[i] = vertices # get curvature_normal_matrix # todo not optimal, because operation done twice etc curvature_normal_mtx = mean_curvature_normal_matrix( triangles, vertices, area_weighted=area_weighted) # do the first step next_vertices = euler_step(curvature_normal_mtx, csc_matrix( vertices), diffusion_step, backward_step).toarray() # test if direction is positive direction = next_vertices - vertices normal_dir = vertices_cotan_normal(triangles, vertices, normalize=True) dotv = dot(normalize_vectors(direction), normal_dir, keepdims=True) vertices += direction * np.maximum(0.0, -dotv) stdout.write("\r step %d on %d done \n" % (nb_iter, nb_iter)) return vertices
def positive_curvature_normal_smooth(triangles, vertices, nb_iter=1, diffusion_step=1.0, area_weighted=False, backward_step=False, flow_file=None): if flow_file is not None: mem_map = np.memmap(flow_file, dtype=G_DTYPE, mode='w+', shape=(nb_iter, vertices.shape[0], vertices.shape[1])) if isinstance(diffusion_step, (int, float)): diffusion_step = diffusion_step * np.ones(len(vertices)) curvature_normal_mtx = mean_curvature_normal_matrix( triangles, vertices, area_weighted=area_weighted) for i in range(nb_iter): stdout.write("\r step %d on %d done" % (i, nb_iter)) stdout.flush() if flow_file is not None: mem_map[i] = vertices # do the first step next_vertices = euler_step(curvature_normal_mtx, csc_matrix( vertices), diffusion_step, backward_step).toarray() # test if direction is positive direction = next_vertices - vertices normal_dir = vertices_normal(triangles, next_vertices, normalize=False) pos_curv = dot(direction, normal_dir, keepdims=True) < 0 vertices += direction * pos_curv stdout.write("\r step %d on %d done \n" % (nb_iter, nb_iter)) return vertices
def positive_curvature_normal_matrix(triangles, vertices, area_weighted=False): from trimeshpy.math.normal import vertices_normal curvature_normal_mtx = mean_curvature_normal_matrix( triangles, vertices, area_weighted) # get flow vector and normal vector direction = curvature_normal_mtx.dot(vertices) normal_dir = vertices_normal(triangles, vertices, normalize=False) # positive curvature goes opposite to the normal pos_curv = (dot(direction, normal_dir, axis=1) < 0).astype(G_DTYPE) curvature_normal_mtx = diags(pos_curv, 0).dot(curvature_normal_mtx) return curvature_normal_mtx
def vertices_cotan_curvature(triangles, vertices, area_weighted=True): from trimeshpy.math.normal import vertices_normal vts_dir = vertices_cotan_direction(triangles, vertices, normalize=False, area_weighted=area_weighted) vts_normal = vertices_normal(triangles, vertices, normalize=False, area_weighted=area_weighted) curvature_sign = -np.sign(dot(vts_dir, vts_normal)) curvature = length(vts_dir) return curvature * curvature_sign
def vertices_cotan_normal(triangles, vertices, normalize=True, area_weighted=True): from trimeshpy.math.curvature import vertices_cotan_direction if scipy.sparse.__name__ in type(vertices).__module__: vertices = vertices.toarray() cotan_normal = vertices_cotan_direction(triangles, vertices, normalize=False, area_weighted=area_weighted) vts_normal = vertices_normal(triangles, vertices, normalize=False, area_weighted=area_weighted) # inverse inverted cotan_normal direction cotan_normal = np.sign(dot(cotan_normal, vts_normal, keepdims=True)) * cotan_normal if normalize: return normalize_vectors(cotan_normal) return cotan_normal