Constrained Delaunay Triangulation (C++)
CDT is a C++ library for generating constraint or conforming Delaunay triangulations.
x64 and arm64If CDT helped you please consider adding a star on GitHub. This means a lot to the authors
CDT::IntersectingConstraintEdges::TryResolve)Latest online documentation (automatically generated with Doxygen).
CDT::VertexInsertionOrder: CDT::VertexInsertionOrder::Auto uses breadth-first traversal of a Kd-tree for initial bulk-load [4] and randomized insertion order for the subsequent calls of CDT::Triangulation::insertVertices. Randomization improves performance and avoid worst-case scenarios. Generally vertex insertion with CDT::VertexInsertionOrder::Auto is faster.CDT::VertexInsertionOrder::AsProvided when constructing a triangulation.Pre-conditions:
Post-conditions:
Supports three ways of removing outer triangles:
CDT::Triangulation::eraseSuperTriangle: produce a convex-hullCDT::Triangulation::eraseOuterTriangles: remove all outer triangles until a boundary defined by constraint edgesCDT::Triangulation::eraseOuterTrianglesAndHoles: remove outer triangles and automatically detected holes. Starts from super-triangle and traverses triangles until outer boundary. Triangles outside outer boundary will be removed. Then traversal continues until next boundary. Triangles between two boundaries will be kept. Traversal to next boundary continues (this time removing triangles). Stops when all triangles are traversed.Supports overlapping boundaries
Removing duplicate points and re-mapping constraint edges can be done using functions: CDT::RemoveDuplicatesAndRemapEdges, CDT::RemoveDuplicates, CDT::RemapEdges
Uses William C. Lenthe's implementation of robust orientation and in-circle geometric predicates: github.com/wlenthe/GeometricPredicates
On old compilers without C++11 support Boost is used as a fall back for missing C++11 standard library features.
A demonstrator tool is included: requires Qt for GUI. When running demo-tool make sure that working directory contains files from 'data' folder.
CDT port is available in Microsoft's vcpkg.
CDT is not in the conan-center but there's a conanfile.py recipe provided (in this repo).
Note that it might need small adjustments like changing boost version to fit your needs.
A recipe for CDT is available in spack.
CDT uses modern CMake and should just work out of the box without any surprises. The are many ways to consume CDT:
add_subdirectoryfind_packageCMake options
| Option | Default value | Description |
|---|---|---|
CDT_USE_64_BIT_INDEX_TYPE |
OFF |
Use 64bits to store vertex/triangle index types. Otherwise 32bits are used (up to 4.2bn items) |
CDT_USE_AS_COMPILED_LIBRARY |
OFF |
Instantiate templates for float and double and compiled into a library |
CDT_DISABLE_EXCEPTIONS |
OFF |
Disables exceptions: instead of throwing the library will call std::terminate |
CDT_ENABLE_CALLBACK_HANDLER |
OFF |
If enabled it is possible to provide a callback handler to the triangulation |
CDT_ENSURE_PRECISE_MATH_IN_CONSTRUCTIONS |
OFF |
Disables fast-math and floating-point contraction in constructions too, not only in predicates. See Floating-point compiler options |
Floating-point compiler options
CDT uses exact adaptive predicates (orientation, in-circle tests) which require strict IEEE-754 math.
Options like -ffast-math, /fp:fast or -ffp-contract=fast can break them.
Fast-math and floating-point contraction are therefore always disabled in the predicates.
Another way inexact math can affect topology is by changing positions of constructed newly inserted vertices (e.g., at edges intersection).
Opt-into exact math with CDT_ENSURE_PRECISE_MATH_IN_CONSTRUCTIONS, this will also ensure that 'golden' file-based tests pass.
Adding to CMake project directly
Can be done with add_subdirectory command (e.g., see CDT visualizer's CMakeLists.txt).
# add CDT as subdirectory to CMake project
add_subdirectory(../CDT CDT)
Adding to non-CMake project directly
To use as header-only copy headers from CDT/include
To use as a compiled library define CDT_USE_AS_COMPILED_LIBRARY and compile CDT.cpp
Consume pre-build CDT in CMake project with find_package
CDT provides package config files that can be included by other projects to find and use it.
# from CDT folder
mkdir build && cd build
# configure with desired CMake flags
cmake -DCDT_USE_AS_COMPILED_LIBRARY=ON ..
# build and install
cmake --build . && cmake --install .
# In consuming CMakeLists.txt
find_package(CDT REQUIRED CONFIG)
Public API is provided in two places:
CDT::Triangulation class is used for performing constrained Delaunay triangulations.CDT.h provide some additional functionality for removing duplicates, re-mapping edges and triangle depth-peelingℹ️ For more up-to-date code examples please see CDT tests in cdt.test.cpp.
Delaunay triangulation without constraints (triangulated convex-hull)
#include "CDT.h"
CDT::Triangulation<double> cdt;
cdt.insertVertices(/* points */);
cdt.eraseSuperTriangle();
/* access triangles */ = cdt.triangles;
/* access vertices */ = cdt.vertices;
/* access boundary (fixed) edges */ = cdt.fixedEdges;
/* calculate all edges (on demand) */ = CDT::extractEdgesFromTriangles(cdt.triangles);
Constrained Delaunay triangulation (auto-detected boundaries and holes)
// ... same as above
cdt.insertVertices(/* points */);
cdt.insertEdges(/* boundary edges */);
cdt.eraseOuterTrianglesAndHoles();
/* access triangles */ = cdt.triangles;
/* access vertices */ = cdt.vertices;
/* access boundary (fixed) edges */ = cdt.fixedEdges;
/* calculate all edges (on demand) */ = CDT::extractEdgesFromTriangles(cdt.triangles);
Conforming Delaunay triangulation
Use CDT::Triangulation::conformToEdges instead of CDT::Triangulation::insertEdges
Resolve edge intersections by adding new points and splitting edges
Pass CDT::IntersectingConstraintEdges::TryResolve to CDT::Triangulation constructor.
Resolving is not always possible for nearly-degenerate intersections (e.g. an intersection right next to an edge's endpoint): in such cases CDT::InvalidEdgeSplitVertex is thrown.
Custom point/edge type
…
Callbacks
For advanced usage and deep integration with custom algorithms CDT allows to register user callbacks for important events. For example it is possible to do progress reporting or abort triangulation.
⚠️ Callbacks need to be enabled with CDT_ENABLE_CALLBACK_HANDLER.
User needs to implement callback handler by deriving from CDT::ICallbackHandler and register it with CDT::Triangulation::setCallbackHandler.
See cdt.test.cpp for usage examples.
CDT reports errors by throwing exceptions. All of them derive from CDT::Error (itself a std::runtime_error) and carry a message and the source location they were thrown from.
| Exception | Thrown by | When
No open issues yet, or sync has not completed.