Welcome to the ACVD (Approximated Centroidal Voronoi Diagrams) codebase. This is the single, unified master guide for AI agents (Antigravity, OpenCode, Cursor, Claude Code, GitHub Copilot, etc.) and human developers working on ACVD.
ACVD is a C++ library and suite of command-line tools for 3D triangular mesh coarsening, remeshing, and volume processing built on VTK (Visualization Toolkit).
ACVD/
├── Common/ # Core mesh topology (vtkSurfaceBase, vtkSurface) & geometry utilities
│ ├── vtkSurfaceBase.{h,cxx} # Base edge-oriented triangular mesh data structure
│ ├── vtkSurface.{h,cxx} # Extended mesh class (I/O, areas, normals, subdivision)
│ ├── vtkCurvatureMeasure.* # Discrete principal curvature calculations
│ ├── vtkQuadricTools.* # Quadric error metric calculations
│ └── vtkVolumeProperties.* # Volume computation from closed surfaces
├── DiscreteRemeshing/ # Voronoi discrete remeshing algorithms & clustering metrics
│ ├── vtkDiscreteRemeshing.h # Abstract base class for Voronoi discrete remeshing
│ ├── vtkIsotropicDiscreteRemeshing.h # Isotropic surface remesher
│ ├── vtkQIsotropicDiscreteRemeshing.h # Quadric-enhanced remesher
│ ├── vtkAnisotropicDiscreteRemeshing.h # Anisotropic metric remesher
│ ├── vtkThreadedClustering.h # OpenMP parallel clustering implementation
│ ├── vtk*MetricForClustering.h # Distance & error metrics (QEM, L21, Isotropic)
│ └── Examples/ # Remeshing executable entry points
│ ├── ACVD.cxx / ACVDP.cxx # Main linear ACVD (sequential / parallel)
│ ├── ACVDQ.cxx / ACVDQP.cxx # Quadric ACVD (sequential / parallel)
│ └── AnisotropicRemeshingQ.cxx # Anisotropic remeshing
├── VolumeProcessing/ # Label image processing & out-of-core image readers
├── docs/ # API & tool documentation (vtkSurface.md, other-programs.md)
├── scripts/ # Agent verification script (agent_verify.sh)
├── Readme.md # Main documentation & CLI parameters reference
└── test.sh # Full test execution workflow script
- CMake 3.11+
- VTK 9.0+ (
libvtk9-devon Debian/Ubuntu) - GCC 7+ / Clang 6+ with C++11 support
- OpenMP (Optional, for parallel executables)
# Out-of-source release build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
# Debug build (AddressSanitizer & symbols)
cmake -B build-debug -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address -g"
cmake --build build-debug -j$(nproc)# Run quick automated verification script
bash scripts/agent_verify.sh
# Run full repository test suite
bash test.sh-
VTK Object Memory Ownership:
- Always use VTK static factory instantiation:
vtkSurface* mesh = vtkSurface::New();and callmesh->Delete();when done, OR usevtkSmartPointer<vtkSurface> mesh = vtkSmartPointer<vtkSurface>::New();. - NEVER use standard C++
deleteon VTK objects derived fromvtkObjectBase.
- Always use VTK static factory instantiation:
-
Mesh Topology Integrity:
- When modifying mesh topology with
vtkSurfaceBase(e.g. vertex collapse, face deletion), deleted element slots are marked dirty untilCleanMemory()orSQueeze()is called. - Check edge valence (
GetValence) and boundary status (GetNumberOfBoundaries) before performing edge operations. - Enable
SetManifoldEnforcement(1)or CLI-m 1to guarantee a 2-manifold output mesh.
- When modifying mesh topology with
-
Multi-Threading Safety (OpenMP):
- Parallel classes (
ACVDP,ACVDQP,vtkThreadedClustering) use OpenMP. Do not mutate shared VTK data structures within#pragma omp parallel forsections without proper reduction or locks. - Parallel remeshing executions are non-deterministic.
- Parallel classes (
vtkSurfaceBase extends VTK's vtkPolyData by providing an explicit edge-oriented representation with constant-time
graph TD
vtkPolyData["vtkPolyData (VTK Core)"] --> vtkSurfaceBase["vtkSurfaceBase (Edge-Oriented Topology)"]
vtkSurfaceBase --> vtkSurface["vtkSurface (I/O, Subdivision, Normals, Stats)"]
-
Vertices: 3D coordinates
$(x, y, z)$ . -
Edges: Vertex pairs
$(v_1, v_2)$ and adjacent face IDs$(f_1, f_2)$ . -
Faces: Vertex triples
$(v_1, v_2, v_3)$ . -
Ring Arrays: Vertex-to-edge (
VertexNeighbourEdges) and vertex-to-face (VertexNeighbourFaces) lists.
// 1. Get vertex ring neighbours
vtkSmartPointer<vtkIdList> neighbours = vtkSmartPointer<vtkIdList>::New();
surface->GetVertexNeighbours(v1, neighbours);
// 2. Get edge vertices & adjacent faces
vtkIdType v1, v2, f1, f2;
surface->GetEdgeVertices(edgeId, v1, v2);
surface->GetEdgeFaces(edgeId, f1, f2);
// 3. Topology operations
surface->FlipEdge(edgeId); // Flip shared diagonal
surface->BisectEdge(edgeId); // Bisect edge at midpoint
surface->MergeVertices(v1, v2); // Collapse v2 into v1
surface->CleanMemory(); // Purge dirty deleted element slotsACVD performs surface remeshing by partitioning the mesh into discrete Voronoi clusters, then constructing the dual Delaunay triangulation from cluster centroids:
flowchart TD
InputMesh["Input Mesh (vtkSurface)"] --> Preprocess["Subdivision & Long Edge Splitting (-s, -l)"]
Preprocess --> SeedClusters["Cluster Seeding"]
SeedClusters --> EnergyLoop["Clustering Iteration (Item Movement)"]
EnergyLoop --> MetricCheck{"Metric Choice"}
MetricCheck -- QEM --> QuadricOpt["Position Vertices via Quadric Minimization"]
MetricCheck -- Uniform --> CentroidOpt["Position Vertices at Cluster Centroids"]
QuadricOpt --> DualMesh["Construct Dual Delaunay Mesh"]
CentroidOpt --> DualMesh
DualMesh --> OutputMesh["Output Mesh (simplification.ply)"]
vtkIsotropicMetricForClustering: Standard Euclidean metric for uniform isotropic triangles.vtkQEMetricForClustering: Quadric Error Metric (QEM) preserving sharp feature edges and corners (ACVDQ).vtkAnisotropicMetricForClustering: Tensor-based metric aligned with principal curvature directions (AnisotropicRemeshing).vtkL21MetricForClustering: Normal-variation minimization metric.
Common invocation pattern:
./build/bin/ACVD <input_mesh> <n_vertices> <curvature_weight> [options]-
<input_mesh>: Path to input 3D model (.ply,.obj,.vtk,.off,.wrl,.stl). -
<n_vertices>: Desired number of vertices in output mesh. -
<curvature_weight>: Curvature gradation weight (0.0= uniform density,1.5= dense sampling in high-curvature regions). -
-s <ratio>: Subsampling threshold ratio (default10; set-s 100for high quality). -
-l <ratio>: Edge splitting ratio (-l 3pre-splits edges longer than$3 \times \text{average_length}$ ). -
-m <0|1>: Enforce 2-manifold output topology (1= enabled,0= disabled). -
-d <0|1|2>: Visualization level (0= silent,1= final window,2= step-by-step iteration display). -
-np <num_threads>: Specify number of OpenMP threads for parallel executables (ACVDP,ACVDQP). -
-o <output_filename>: Custom output PLY filename (default issimplification.ply).
- Readme.md: Main user documentation & usage examples.
- docs/vtkSurface.md:
vtkSurface/vtkSurfaceBasedetailed API reference. - docs/other-programs.md: Auxiliary programs (
VolumeAnalysis,ManifoldSimplification, mesh converters).