CDT  1.3.0
C++ library for constrained Delaunay triangulation
Overview

CDT Logo

CI Builds

CDT is a C++ library for generating constraint or conforming Delaunay triangulations.

  • open-source: permissively-licensed under Mozilla Public License (MPL) 2.0
  • cross-platform: tested on Windows, Linux (Ubuntu), and macOS
  • portable: backwards-compatible with C++98
  • bloat-free: no external dependencies by default
  • flexible: can be consumed as a header-only or as a compiled library
  • performant: continuously profiled, measured, and optimized
  • numerically robust: triangulation algorithms rely on robust geometric predicates

If CDT helped you please consider adding a star to on GitHub. This means a lot to the authors 🤩

Table of Contents

What can CDT do?

CDT show-case: constrained and conforming triangulations, convex hulls, automatically removing holes

  • Constrained Delaunay Triangulations: force edges into Delaunay triangulation
  • Conforming Delaunay Triangulations: add new points into Delaunay triangulation until the edge is present in triangulation
  • Convex-hulls
  • Automatically finding and removing holes

Properly Handling the Corner-Cases

CDT supported corner cases: points on edges, overlapping edges, resolving edge intersections

Online Documentation

Latest online documentation (automatically generated with Doxygen).

Algorithm

  • Implementation closely follows incremental construction algorithm by Anglada [1].
  • During the legalization, the cases when at least one vertex belongs to super-triangle are resolved using an approach as described in Žalik et. al [2].
  • For finding a triangle that contains inserted point remembering randomized triangle walk is used [3]. To find the starting triangle for the walk the nearest point is found using a kd-tree with mid-split nodes.
  • Order in which vertices are inserted is controlled by CDT::VertexInsertionOrder:

Pre-conditions:

  • No duplicated points (use provided functions for removing duplicate points and re-mapping edges)
  • No two constraint edges intersect each other (overlapping boundaries are allowed)

Post-conditions:

  • Triangles have counter-clockwise (CCW) winding

Implementation Details

  • Supports three ways of removing outer triangles:
  • 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
  • Boost is an optional (to opt-in define CDT_USE_BOOST) dependency used for:
    • Fall back for standard library features missing in C++98 compilers.
    • Minor performance tweaks: boost::container::flat_set is used for faster triangle walking.
  • A demonstrator tool is included: requires Qt for GUI. When running demo-tool make sure that working directory contains files from 'data' folder.

Installation/Building

CDT uses modern CMake and should just work out of the box without any suprises. The are many ways to consume CDT:

  • copy headers and use as a header-only library
  • add to CMake project directly with add_subdirectory
  • pre-build and add to CMake project as a dependency with find_package
  • consume as a Conan package

CMake options

Option Default value Description
CDT_USE_BOOST OFF Use Boost as a fall-back for features missing in C++98 and performance tweaks (e.g., boost::flat_set)
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

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 -DCDT_USE_BOOST=ON ..
# build and install
cmake --build . && cmake --install .
# In consuming CMakeLists.txt
find_package(CDT REQUIRED CONFIG)

Consume as Conan package

There's a conanfile.py recipe provided. Note that it might need small adjustments like changing boost version to fit your needs.

Using

Public API is provided in two places:

  • CDT::Triangulation class is used for performing constrained Delaunay triangulations.
  • Free functions in CDT.h provide some additional functionality for removing duplicates, re-mapping edges and triangle depth-peeling

Code Examples

Delaunay triangulation without constraints (triangulated convex-hull)

Example of a triangulated convex hull

#include "CDT.h"
cdt.insertVertices(/* points */);
/* access triangles */ = cdt.triangles;
/* access vertices */ = cdt.vertices;
/* access boundary (fixed) edges */ = cdt.fixedEdges;
/* calculate all edges (on demand) */ = CDT::extractEdgesFromTriangles(cdt.triangles);
Public API.
Data structure representing a 2D constrained Delaunay triangulation.
EdgeUSet fixedEdges
triangulation's constraints (fixed edges)
V2dVec vertices
triangulation's vertices
void insertVertices(TVertexIter first, TVertexIter last, TGetVertexCoordX getX, TGetVertexCoordY getY)
Insert custom point-types specified by iterator range and X/Y-getters.
void eraseSuperTriangle()
Erase triangles adjacent to super triangle.
TriangleVec triangles
triangulation's triangles
CDT_EXPORT EdgeUSet extractEdgesFromTriangles(const TriangleVec &triangles)
Extract all edges of triangles.
Definition: CDT.hpp:74

Constrained Delaunay triangulation (auto-detected boundaries and holes)

Example of a triangulation with constrained boundaries and auto-detected holes

// ... same as above
cdt.insertVertices(/* points */);
cdt.insertEdges(/* boundary edges */);
/* access triangles */ = cdt.triangles;
/* access vertices */ = cdt.vertices;
/* access boundary (fixed) edges */ = cdt.fixedEdges;
/* calculate all edges (on demand) */ = CDT::extractEdgesFromTriangles(cdt.triangles);
void eraseOuterTrianglesAndHoles()
Erase triangles outside of constrained boundary and auto-detected holes.
void insertEdges(TEdgeIter first, TEdgeIter last, TGetEdgeVertexStart getStart, TGetEdgeVertexEnd getEnd)
Insert constraints (custom-type fixed edges) into triangulation.

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::Resolve to CDT::Triangulation constructor.

Custom point/edge type

struct CustomPoint2D
{
double data[2];
};
struct CustomEdge
{
std::pair<std::size_t, std::size_t> vertices;
};
// containers other than std::vector will work too
std::vector<CustomPoint2D> points = /*...*/;
std::vector<CustomEdge> edges = /*...*/;
points.begin(),
points.end(),
[](const CustomPoint2D& p){ return p.data[0]; },
[](const CustomPoint2D& p){ return p.data[1]; }
);
edges.begin(),
edges.end(),
[](const CustomEdge& e){ return e.vertices.first; },
[](const CustomEdge& e){ return e.vertices.second; }
);

Python bindings?

For work-in-progress on Python bindings check-out PythonCDT

Contributors

Contributing

Any feedback and contributions are welcome.

License

Mozilla Public License, v. 2.0

For attribution you can use the following template:

This software is based part on CDT (C++ library for constrained Delaunay triangulation):
Copyright © 2019 Leica Geosystems Technology AB
Copyright © The CDT Contributors
Licensed under the MPL-2.0 license.
https://github.com/artem-ogre/CDT
${INSERT_FULL_MPL_2.0_TEXT}

Example Gallery

A Bean Guitar Guitar with holes Lake Superior Sweden Overlapping boundaries

Bibliography

[1] Marc Vigo Anglada, An improved incremental algorithm for constructing restricted Delaunay triangulations, Computers & Graphics, Volume 21, Issue 2, 1997, Pages 215-223, ISSN 0097-8493.

[2] Borut Žalik and Ivana Kolingerová, An incremental construction algorithm for Delaunay triangulation using the nearest-point paradigm, International Journal of Geographical Information Science, Volume 17, Issue 2, Pages 119-138, 2003, DOI 10.1080/713811749.

[3] Olivier Devillers, Sylvvain Pion, Monique Tellaud, Walking in a triangulation, International Journal of Foundations of Computer Science, Volume 13, Issue 2, Pages 181-199, 2002

[4] Liu, Jianfei & Yan, Jinhui & Lo, S.. A new insertion sequence for incremental Delaunay triangulation. Acta Mechanica Sinica, Volume 29, 2013