|
| 1 | +import compas |
| 2 | +import numpy as np |
| 3 | +import compas_libigl as igl |
| 4 | +from compas.colors import Color |
| 5 | +from compas.colors.colormap import ColorMap |
| 6 | +from compas.datastructures import Mesh |
| 7 | +from compas.geometry import Point, Line, Vector |
| 8 | +from compas_viewer import Viewer |
| 9 | +from compas_viewer.scene import BufferGeometry |
| 10 | + |
| 11 | +# ============================================================================== |
| 12 | +# Input geometry |
| 13 | +# ============================================================================== |
| 14 | + |
| 15 | +mesh = Mesh.from_obj(compas.get("tubemesh.obj")) |
| 16 | +trimesh = mesh.copy() |
| 17 | +trimesh.quads_to_triangles() |
| 18 | + |
| 19 | +# ============================================================================== |
| 20 | +# Gaussian Curvature |
| 21 | +# ============================================================================== |
| 22 | + |
| 23 | +vertices, faces = trimesh.to_vertices_and_faces() |
| 24 | +gaussian_curvature = igl.trimesh_gaussian_curvature((vertices, faces)) |
| 25 | + |
| 26 | +# Get non-boundary vertex indices |
| 27 | +non_boundary_vertices = [i for i in range(len(vertices)) if not trimesh.is_vertex_on_boundary(i)] |
| 28 | + |
| 29 | +# Prepare vertex colors based on Gaussian curvature (excluding boundary vertices) |
| 30 | +min_gaussian = min(gaussian_curvature[i] for i in non_boundary_vertices) |
| 31 | +max_gaussian = max(gaussian_curvature[i] for i in non_boundary_vertices) |
| 32 | +print(f"Gaussian curvature range: {min_gaussian:.3f} to {max_gaussian:.3f}") |
| 33 | + |
| 34 | +# Scale factor for normal vectors |
| 35 | +normal_scale = -10 |
| 36 | + |
| 37 | +# Create two-color maps for negative and positive curvature |
| 38 | +cmap_negative = ColorMap.from_two_colors(Color.blue(), Color.yellow()) |
| 39 | +cmap_positive = ColorMap.from_two_colors(Color.yellow(), Color.magenta()) |
| 40 | + |
| 41 | +# Convert mesh to numpy arrays for BufferGeometry |
| 42 | +vertices = np.array(vertices, dtype=np.float32) |
| 43 | +faces = np.array(faces, dtype=np.float32) |
| 44 | + |
| 45 | +# Create vertex colors array (Nx4 for RGBA) |
| 46 | +vertex_colors = np.zeros((len(vertices), 4), dtype=np.float32) |
| 47 | +for i, k in enumerate(gaussian_curvature): |
| 48 | + if trimesh.is_vertex_on_boundary(i): |
| 49 | + # Set boundary vertices to a neutral color |
| 50 | + vertex_colors[i] = [0, 0, 0, 1.0] |
| 51 | + else: |
| 52 | + if k < 0: |
| 53 | + color = cmap_negative(k, minval=min_gaussian, maxval=0) |
| 54 | + else: |
| 55 | + color = cmap_positive(k, minval=0, maxval=max_gaussian) |
| 56 | + vertex_colors[i] = (color[0], color[1], color[2], 1.0) |
| 57 | + |
| 58 | +# Create geometry for the mesh with vertex colors |
| 59 | +faces_for_buffer = np.array([vertices[f] for f in faces.astype(int)]).reshape(-1, 3) |
| 60 | +vertex_colors_for_buffer = np.array([vertex_colors[i] for i in faces.astype(int)]).reshape(-1, 4) |
| 61 | + |
| 62 | +geometry = BufferGeometry( |
| 63 | + faces=faces_for_buffer, |
| 64 | + facecolor=vertex_colors_for_buffer |
| 65 | +) |
| 66 | + |
| 67 | +# ============================================================================== |
| 68 | +# Visualization |
| 69 | +# ============================================================================== |
| 70 | + |
| 71 | +viewer = Viewer() |
| 72 | +viewer.scene.add(geometry) |
| 73 | + |
| 74 | +# Add normal vectors colored by Gaussian curvature |
| 75 | +for vertex_idx, point in enumerate(vertices): |
| 76 | + if not trimesh.is_vertex_on_boundary(vertex_idx): |
| 77 | + point = Point(*point) |
| 78 | + normal = Vector(*trimesh.vertex_normal(vertex_idx)) |
| 79 | + k = gaussian_curvature[vertex_idx] |
| 80 | + |
| 81 | + # Scale normal by absolute curvature value |
| 82 | + scaled_normal = normal.scaled(normal_scale * k) |
| 83 | + |
| 84 | + viewer.scene.add( |
| 85 | + Line(point, point + scaled_normal), |
| 86 | + linecolor=Color.black(), |
| 87 | + linewidth=2 |
| 88 | + ) |
| 89 | +viewer.show() |
0 commit comments