Initializing 3D Canvas...

Isotropic Remeshing

2 min read1 page

Isotropic Remeshing (Botsch & Kobbelt) iteratively transforms irregular, stretched triangles into nearly equilateral triangles of uniform target edge length $L$.

Split & Collapse Criteria:

1. Split Long Edges: Any edge with length $> \frac43 L$ is bisected at its midpoint. 2. Collapse Short Edges: Any edge with length $< \frac45 L$ is collapsed to an endpoint. 3. Target Uniformity: Prevents needle triangles and extreme area variations.
python
1def isotropic_remesh_pass(mesh, target_length):
2 high_threshold = (4.0 / 3.0) * target_length
3 low_threshold = (4.0 / 5.0) * target_length
4
5 # 1. Split edges longer than high_threshold
6 for edge in mesh.edges():
7 if edge.length() > high_threshold:
8 mesh.split_edge(edge)
9
10 # 2. Collapse edges shorter than low_threshold
11 for edge in mesh.edges():
12 if edge.length() < low_threshold:
13 mesh.collapse_edge(edge)
Target Length (L)
2.50
3 min read1 page

Valence Optimization flips non-delaunay or irregular diagonal edges so that every interior vertex approaches the ideal valence of 6 (the optimal hexagonal packing topology).

Valence Flip Criterion:

1. Target Valence 6: Regular triangulations have 6 equilateral neighbors per vertex. 2. Cost Metric: Minimizes sum of squared valence errors (valence - 6)^2 before and after an edge swap. 3. Geometric Invariant: Flips are rejected if the resulting flipped triangles invert or fold.
python
1def flip_edges_for_valence(mesh):
2 """Flip edges if doing so brings vertex valences closer to target 6."""
3 target_valence = 6
4
5 for edge in mesh.interior_edges():
6 v1, v2 = edge.vertices
7 v3, v4 = edge.opposite_vertices()
8
9 # Calculate current squared deviation from valence 6
10 current_cost = (
11 (v1.valence - target_valence)**2 +
12 (v2.valence - target_valence)**2 +
13 (v3.valence - target_valence)**2 +
14 (v4.valence - target_valence)**2
15 )
16
17 # After flipping: v1 and v2 lose 1 edge; v3 and v4 gain 1 edge
18 flipped_cost = (
19 (v1.valence - 1 - target_valence)**2 +
20 (v2.valence - 1 - target_valence)**2 +
21 (v3.valence + 1 - target_valence)**2 +
22 (v4.valence + 1 - target_valence)**2
23 )
24
25 if flipped_cost < current_cost:
26 mesh.flip_edge(edge)
Flip Diagonal Edge