Meshing

import math
from compas.colors import Color
from compas.datastructures import Mesh
from compas.geometry import Plane
from compas.geometry import Rotation
from compas.geometry import Scale
from compas_viewer import Viewer
import compas_libigl as igl
# Load and transform mesh
mesh = Mesh.from_off(igl.get_beetle())
R = Rotation.from_axis_and_angle([1, 0, 0], math.radians(90))
S = Scale.from_factors([10, 10, 10])
mesh.transform(S * R)
# Calculate signed distances to plane
plane = Plane([0, 0, 0], [0, 1, 1])
distances = [plane.normal.dot(plane.point - mesh.vertex_coordinates(v)) for v in mesh.vertices()]
# Split mesh along plane
V, F, L = igl.trimesh_remesh_along_isoline(mesh.to_vertices_and_faces(), distances, 0)
# Create meshes for parts below and above plane
below = Mesh.from_vertices_and_faces(V, [F[i] for i, l in enumerate(L) if l == 0])
above = Mesh.from_vertices_and_faces(V, [F[i] for i, l in enumerate(L) if l == 1])
# Visualize
viewer = Viewer()
viewer.scene.add(below, facecolor=Color.red(), show_lines=False)
viewer.scene.add(above, facecolor=Color.blue(), show_lines=False)
viewer.show()

import math
from compas.colors import ColorMap
from compas.datastructures import Mesh
from compas.geometry import Rotation
from compas.geometry import Scale
from compas_viewer import Viewer
import compas_libigl as igl
# Load mesh
mesh = Mesh.from_off(igl.get_beetle())
R = Rotation.from_axis_and_angle([1, 0, 0], math.radians(90))
S = Scale.from_factors([10, 10, 10])
mesh.transform(S * R)
# Get z-coordinates as scalar field
scalar_values = mesh.vertices_attribute("z")
min_val, max_val = min(scalar_values), max(scalar_values)
# Create 4 isolines
num_isolines = 4
isovalues = [min_val + i * (max_val - min_val) / num_isolines for i in range(1, num_isolines + 1)]
# Split mesh along isolines
V, F, S, G = igl.trimesh_remesh_along_isolines(mesh.to_vertices_and_faces(), scalar_values, isovalues)
# Visualize each piece in a different color
color_map = ColorMap.from_mpl("viridis")
viewer = Viewer()
# Create separate mesh for each group
for i, group_id in enumerate(set(G)):
faces = [F[j] for j in range(len(F)) if G[j] == group_id]
if faces:
piece = Mesh.from_vertices_and_faces(V, faces)
viewer.scene.add(piece, facecolor=color_map(i / (num_isolines + 1)), show_lines=False)
viewer.show()

import math
from compas.colors import ColorMap
from compas.datastructures import Mesh
from compas.geometry import Rotation
from compas.geometry import Scale
from compas_viewer import Viewer
import compas_libigl as igl
# Load mesh
mesh = Mesh.from_off(igl.get_beetle())
R = Rotation.from_axis_and_angle([1, 0, 0], math.radians(90))
S = Scale.from_factors([10, 10, 10])
mesh.transform(S * R)
scalar_values = []
frequency = 2
for v in mesh.vertices():
x, y, z = mesh.vertex_coordinates(v)
val = math.sin(frequency * x) * math.cos(frequency * y) + math.sin(frequency * z)
scalar_values.append(val)
# Get range and create isolines
min_val, max_val = min(scalar_values), max(scalar_values)
num_isolines = 7
isovalues = [min_val + i * (max_val - min_val) / num_isolines for i in range(1, num_isolines + 1)]
# Split mesh along isolines
V, F, S, G = igl.trimesh_remesh_along_isolines(mesh.to_vertices_and_faces(), scalar_values, isovalues)
# Visualize each piece in a different color
color_map = ColorMap.from_mpl("plasma")
viewer = Viewer()
# Create separate mesh for each group
for i, group_id in enumerate(set(G)):
faces = [F[j] for j in range(len(F)) if G[j] == group_id]
if faces:
piece = Mesh.from_vertices_and_faces(V, faces)
viewer.scene.add(piece, facecolor=color_map(i / (num_isolines + 1)), show_lines=False)
viewer.show()

import math
from compas.colors import ColorMap
from compas.datastructures import Mesh
from compas.geometry import Point
from compas.geometry import Rotation
from compas.geometry import Scale
from compas_viewer import Viewer
import compas_libigl as igl
# ==============================================================================
# Input geometry
# ==============================================================================
mesh = Mesh.from_off(igl.get("camelhead.off"))
R = Rotation.from_axis_and_angle([1, 0, 0], math.radians(90))
S = Scale.from_factors([10, 10, 10])
mesh.transform(S * R)
# Convert to triangle mesh
trimesh = mesh.copy()
trimesh.quads_to_triangles()
# ==============================================================================
# Compute geodesic distances from boundary
# ==============================================================================
# Get boundary vertices
boundary_vertices = list(trimesh.vertices_on_boundary())
# Calculate geodesic distances using multiple source points
distances = igl.trimesh_geodistance_multiple(trimesh.to_vertices_and_faces(), boundary_vertices, method="exact")
# ==============================================================================
# Create isolines and remesh
# ==============================================================================
# Get range and create isolines
min_dist, max_dist = min(distances), max(distances)
num_isolines = 5
isovalues = [min_dist + i * (max_dist - min_dist) / num_isolines for i in range(1, num_isolines + 1)]
# Split mesh along isolines of geodesic distance
V, F, S, G = igl.trimesh_remesh_along_isolines(trimesh.to_vertices_and_faces(), distances, isovalues)
# ==============================================================================
# Visualization
# ==============================================================================
viewer = Viewer(width=1600, height=900)
# Create separate mesh for each geodesic distance group
color_map = ColorMap.from_mpl("viridis")
for i, group_id in enumerate(sorted(set(G))):
faces = [F[j] for j in range(len(F)) if G[j] == group_id]
if faces:
piece = Mesh.from_vertices_and_faces(V, faces)
viewer.scene.add(piece, facecolor=color_map(i / (num_isolines + 1)), show_lines=False, linewidth=1, linecolor=(0.2, 0.2, 0.2))
# Highlight boundary vertices
for vertex in boundary_vertices:
point = Point(*trimesh.vertex_attributes(vertex, "xyz"))
viewer.scene.add(point, pointsize=20, pointcolor=(1, 0, 0))
viewer.show()