Skip to content
Table of contents

ipc-toolkit: Collision queries as a library boundary

ipc-toolkit provides geometric building blocks for contact-aware simulation. This fork contains collision meshes, broad-phase candidates, continuous collision detection and contact-related energies. An external simulation still owns its time stepping and solve loop.

Library Fork Algorithm
  • Updated
  • C++ · 94.46%
  • MIT
C++CCDCMake C/C++ (CMake) Python Catch2 Upstream credited
Documented components
2Explore modules
Source documents
6Read the instructions
Repository languagesC++ 94.46%5

Shares calculated from GitHub Linguist bytes.

C++94.46%
94.46%2,400,346 bytes
CMake2.98%
2.98%75,800 bytes
Python2.1%
2.1%53,463 bytes
Cuda0.38%
0.38%9,561 bytes
Language%Bytes
C++94.46%2,400,346
CMake2.98%75,800
Python2.1%53,463
Cuda0.38%9,561
Dockerfile0.08%2,051

1. Overview

1.1. Why it exists

Friction and contact physics toolkit for robust computer graphics and finite element simulation.

1.2. Best fit

Nonlinear continuous contact mechanics in 3D physics engines.

2. Use cases

A C++ library with Python bindings for Incremental Potential Contact: contact barriers, CCD and friction for simulators.

Use-case diagram for ipc-toolkit: Build a collision mesh; Find contacts within dhat; Evaluate barrier, derivatives; Get a collision-free step size; Add anisotropic friction; Script it from Pythonipc-toolkitBuild a collision meshFind contacts within dhatEvaluate barrier, derivativesGet a collision-free step sizeAdd anisotropic frictionScript it from PythonSimulation developer«system»Host simulator
People on the left, external systems on the right; each oval is a use case backed by the files cited below.
Build a collision mesh
Simulation developer

ipc::CollisionMesh takes vertex, edge and face matrices (Eigen), as in the README quick start.

Find contacts within dhat
Simulation developerHost simulator

NormalCollisions::build() uses a broad phase (hash grid, LBVH, sweep and prune…) to collect primitive pairs closer than dhat.

Evaluate barrier, derivatives
Simulation developerHost simulator

BarrierPotential returns the energy, gradient and sparse Hessian that the host solver adds to its objective.

Get a collision-free step size
Simulation developerHost simulator

compute_collision_free_stepsize() runs continuous collision detection (Tight Inclusion by default, nonlinear and additive variants in src/ipc/ccd) between two vertex states.

Add anisotropic friction
Simulation developerHost simulator

FrictionPotential works on TangentialCollisions; smooth_mu.hpp adds elliptical anisotropic friction coefficients (commit Anisotropic friction #210).

Script it from Python
Simulation developer

pybind11 bindings under python/src expose the same API as ipctk (pip install ipctk), built when IPC_TOOLKIT_BUILD_PYTHON is ON.

2.1. Scenario: Adding contact to one implicit time step

  1. Install the bindings with pip install ipctk, or add the library to a CMake project.
  2. Create a CollisionMesh from the vertices, edges and faces of the scene.
  3. Build NormalCollisions with dhat = 1e-3 for the current positions.
  4. Add the BarrierPotential energy, gradient and Hessian to the solver's Newton system.
  5. Before accepting the Newton step, clamp it with compute_collision_free_stepsize so no surfaces cross.

Files readREADME.mdCMakeLists.txtsrc/ipc/ipc.hppsrc/ipc/collision_mesh.hppsrc/ipc/potentials/barrier_potential.hppsrc/ipc/friction/smooth_mu.hpppython/src/bindings.cpp

3. Getting started

These commands come from the repository documentation. They were not run during this review.

python/README.md · Installation
pip install ipctk
python/README.md · Installation
pip install git+https://github.com/ipc-sim/ipc-toolkit
python/README.md · Build
pip install .
python/README.md · Build
python -c "import ipctk"
python/README.md · CMake Build
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DIPC_TOOLKIT_BUILD_PYTHON=ON ..
make -j$(nproc)

4. Repository references

Excerpts from the repository’s guides, in their original language. Links open the inspected source revision.

Prerequisites and first run

4.1. Quick Start

README.md

C++ (include via CMake; see build instructions): Python (install via pip install ipctk): For more details, see the tutorials and API documentation.
Read the full instructions ↗

4.2. Installation

python/README.md

To install the latest release, you can use pip: If you wish to install the current development code, you can compile the library from scratch. Either clone the repo manually or use git+ with pip:
Read the full instructions ↗
Development and contributions

4.3. Contributing

README.md

This project is open to contributors! Contributions can come in the form of feature requests, bug fixes, documentation, tutorials, and the like. We highly recommend filing an Issue first before submitting a Pull Request. Simply fork this repository and make a Pull Request! We would appreciate:

  • Implementation of new features
  • Bug Reports
  • Documentation
  • Testing
Read the full instructions ↗

4.4. Contributing (CONTRIBUTING.md)

docs/CONTRIBUTING.md

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.
Read the full instructions ↗
Source documentation

6 documents read from 6 candidates.

5. Features and components 2

Geometry and collision queries
ipc.hpp accepts a CollisionMesh and vertex positions for intersection and collision-free-step queries. Broad-phase and narrow-phase CCD implementations are explicit parameters with defaults, separating candidate discovery from detailed tests.
Contact calculations
The source tree separates distance, barrier, friction, tangent and potential modules. These components support a caller’s objective and derivatives; they do not automatically integrate an entire physical scene.

6. Architecture

Expand a component to follow its connections, or explore the full diagram.

System components Context
Mermaid Interactive diagram

System overview of the components and connections verified in the repository.

Static architecture view for ipc-toolkit
Static preview. The interactive diagram replaces it after Mermaid loads.
flowchart LR
  n0["External simulation"]
  n1["Collision mesh and vertex motion"]
  n2["Broad-phase candidates"]
  n3["Narrow-phase CCD"]
  n4["Collision query result"]
  n0 --> n1
  n1 --> n2
  n2 --> n3
  n3 --> n4
  n4 --> n0
Text version of the diagram
  • External simulation → Collision mesh and vertex motion
  • Collision mesh and vertex motion → Broad-phase candidates
  • Broad-phase candidates → Narrow-phase CCD
  • Narrow-phase CCD → Collision query result
  • Collision query result → External simulation
Follow one path through the code

Follow is_step_collision_free from the public declaration into its implementation. Its result answers a geometric query for a proposed motion. The caller must decide how that result changes a step, line search or contact solve.

7. Technical dossier

Built from the source at commit 4d9e47e (473 files). Each item comes from a pattern match in the code, so open the linked file before relying on it.

7.1. Layers and modules

Folders are sorted into layers by name, from the user interface down to data access. Because the sorting uses names only, the diagram says nothing about calls between layers.

Mermaid Layered view
flowchart TB
  subgraph L_domain["Domain and business rules"]
    direction TB
    domain_0["ipc/geometry<br/>8 files"]
    domain_1["ipc/math<br/>5 files"]
    domain_2["python/geometry<br/>5 files"]
    domain_3["ipc/distance<br/>2 files"]
    domain_more["+3"]
  end
  subgraph L_infrastructure["Data and infrastructure"]
    direction TB
    infrastructure_0["ipc/utils<br/>2 files"]
  end
  subgraph L_core["Core source"]
    direction TB
    core_0["ipc/smooth_contact<br/>32 files"]
    core_1["ipc/collisions<br/>26 files"]
    core_2["ipc/distance<br/>22 files"]
    core_3["ipc/broad_phase<br/>21 files"]
    core_more["+29"]
  end
  subgraph L_tests["Tests"]
    direction TB
    tests_0["tests<br/>71 files"]
    tests_1["python<br/>9 files"]
  end
  subgraph L_hosting["Build, CI and hosting"]
    direction TB
    hosting_0["ipc<br/>22 files"]
    hosting_1["python<br/>18 files"]
    hosting_2[".github<br/>12 files"]
    hosting_3[".devcontainer<br/>2 files"]
    hosting_more["+2"]
  end
  L_domain ~~~ L_infrastructure
  L_infrastructure ~~~ L_core
  L_core ~~~ L_tests
  L_core ~~~ L_hosting
Modules and their main layer
ModuleLayerFilesTypesExtensions
ipc/smooth_contactCore source3227.hpp .cpp
ipc/collisionsCore source2615.hpp .cpp
ipc/distanceCore source240.cpp .hpp
ipc/broad_phaseCore source2115.hpp .cpp
ipc/candidatesCore source189.cpp .hpp
ipc/ccdCore source187.hpp .cpp
ipc/utilsCore source1813.hpp .cpp
python/collisionsCore source170.cpp .hpp
ipc/potentialsCore source147.cpp .hpp
python/distanceCore source110.cpp .hpp
python/broad_phaseCore source101.cpp .hpp
python/candidatesCore source100.cpp .hpp
python/ccdCore source103.cpp .hpp
ipc/geometryDomain and business rules80.cpp .hpp

23 smaller modules are not shown.

7.2. C4 model

From system context to code declarations. Each level reflects the available source evidence.

UML 1 · System context
1 · System context

The widest C4 view: who uses the project and which outside systems and data stores it relies on. Rendered with uml-mcp.

PlantUML source
@startuml
!include <C4/C4_Context>
LAYOUT_LEFT_RIGHT()
Person(P_cli, "CLI user")
System(SYS, "ipc-toolkit", "ipc-toolkit provides geometric building blocks for contact-aware simu…")
Rel(P_cli, SYS, "Uses")
@enduml
UML 2 · Containers
2 · Containers

One level closer: the parts that run separately inside the project, their main language and how calls flow between them. Rendered with uml-mcp.

PlantUML source
@startuml
!include <C4/C4_Container>
LAYOUT_LEFT_RIGHT()
Person(P_cli, "CLI user")
System_Boundary(SYS, "ipc-toolkit") {
  Container(APP, "ipc-toolkit", "C++")
}
Rel(P_cli, APP, "Uses")
@enduml
UML 3 · Components and layers
3 · Components and layers

Modules grouped by source-layer classification. Boundaries show organization, not runtime isolation or call relationships. Rendered with uml-mcp.

PlantUML source
@startuml
!include <C4/C4_Component>
LAYOUT_TOP_DOWN()
System_Boundary(SYS, "ipc-toolkit") {
Boundary(L0, "Presentation", "layer") {
Component(M0_0, "docs/_static", ".css, HTML", "2 files")
Component(M0_1, "docs/_templates", "HTML", "1 files")
}
Boundary(L1, "Domain and business rules", "layer") {
Component(M1_0, "ipc/geometry", "C++", "8 files")
Component(M1_1, "ipc/math", "C++", "5 files")
Component(M1_2, "python/geometry", "C++", "5 files")
Component(M1_3, "ipc/distance", "C++", "2 files")
Component(M1_4, "python/math", "C++", "2 files")
Component(M1_5, "ipc/utils", "C++", "1 files")
Component(M1_6, "python/distance", "C++", "1 files")
}
Boundary(L2, "Data and infrastructure", "layer") {
Component(M2_0, "ipc/utils", "C++", "2 files")
}
Boundary(L3, "Core source", "layer") {
Component(M3_0, "ipc/smooth_contact", "C++", "32 files")
Component(M3_1, "ipc/collisions", "C++", "26 files")
Component(M3_2, "ipc/distance", "C++", "22 files")
Component(M3_3, "ipc/broad_phase", "C++", "21 files")
Component(M3_4, "ipc/candidates", "C++", "18 files")
Component(M3_5, "ipc/ccd", "C++", "18 files")
Component(M3_6, "python/collisions", "C++", "17 files")
Component(M3_7, "ipc/utils", "C++", "15 files")
Component(M3_more, "+25 modules", "", "")
}
Boundary(L4, "Tests", "layer") {
Component(M4_0, "tests", "C++", "71 files")
Component(M4_1, "python", "Python", "9 files")
}
Boundary(L5, "Build, CI and hosting", "layer") {
Component(M5_0, "ipc", ".txt", "22 files")
Component(M5_1, "python", ".txt", "18 files")
Component(M5_2, ".github", ".yml, .md", "12 files")
Component(M5_3, ".devcontainer", "Dockerfile, .json", "2 files")
Component(M5_4, "(root)", ".txt", "1 files")
Component(M5_5, "docs", "Makefile", "1 files")
}
}
@enduml
UML 4 · Code
4 · Code

Selected declarations, fields and methods grouped by source file. No inheritance or call edges are inferred. Rendered with uml-mcp.

PlantUML source
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
top to bottom direction
hide empty members
package "ipc-toolkit" {
package "src/ipc/collision_mesh.hpp" as F0 {
class "CollisionMesh" as T0_0 {
  build_from_full_mesh()
  init_adjacencies()
  init_area_jacobians()
  num_vertices()
  num_codim_vertices()
  num_codim_edges()
}
}
package "src/ipc/math/math.hpp" as F1 {
class "Math" as T1_0 {
  sign()
  abs()
  sqr()
  cubic()
  cubic_spline()
  cubic_spline_grad()
}
}
package "src/ipc/candidates/collision_stencil.hpp" as F2 {
class "CollisionStencil" as T2_0 {
  num_vertices()
  dim()
  vertex_ids()
  vertices()
  dof()
  compute_distance()
}
}
package "src/ipc/collisions/normal/normal_collisions.hpp" as F3 {
class "NormalCollisions" as T3_0 {
  build()
  compute_minimum_distance()
  size()
  empty()
  clear()
  is_vertex_vertex()
}
}
package "src/ipc/broad_phase/lbvh.hpp" as F4 {
class "LBVH" as T4_0 {
  name()
  clear()
  detect_vertex_vertex_candidates()
  detect_edge_vertex_candidates()
  detect_edge_edge_candidates()
  detect_face_vertex_candidates()
}
class "MortonCodeElement" as T4_1 {
  morton_code
  box_id
  std
  parent
}
class "ConstructionInfo" as T4_2 {
  parent
  std
}
}
package "src/ipc/broad_phase/broad_phase.hpp" as F5 {
class "BroadPhase" as T5_0 {
  name()
  build()
  clear()
  detect_collision_candidates()
  detect_vertex_vertex_candidates()
  detect_edge_vertex_candidates()
}
}
package "src/ipc/candidates/candidates.hpp" as F6 {
class "Candidates" as T6_0 {
  build()
  size()
  empty()
  clear()
  is_step_collision_free()
  compute_collision_free_stepsize()
}
}
package "src/ipc/broad_phase/hash_grid.hpp" as F7 {
class "HashGrid" as T7_0 {
  name()
  clear()
  detect_vertex_vertex_candidates()
  detect_edge_vertex_candidates()
  detect_edge_edge_candidates()
  detect_face_vertex_candidates()
}
}
package "src/ipc/broad_phase/sweep_and_prune.hpp" as F8 {
class "SweepAndPrune" as T8_0 {
  name()
  build()
  clear()
  detect_vertex_vertex_candidates()
  detect_edge_vertex_candidates()
  detect_edge_edge_candidates()
}
}
package "src/ipc/smooth_contact/primitives/edge3.hpp" as F9 {
class "Edge3" as T9_0 {
  n_vertices()
  n_dofs()
  n_face_neighbors()
  potential()
  grad()
  hessian()
}
}
package "src/ipc/broad_phase/sweep_and_prune.cpp" as F10 {
class "Boxes" as T10_0 {
  std
  SweepAndPrune
}
}
package "src/ipc/broad_phase/broad_phase.cpp" as F11 {
class "MeshDomain" as T11_0 {
  Eigen
  tbb
}
}
package "src/ipc/smooth_contact/distance/primitive_distance.hpp" as F12 {
class "PrimitiveDistType" as T12_0 {
  PrimitiveA
  Eigen
}
}
package "src/ipc/math/interval.hpp" as F13 {
class "ScalarBinaryOpTraits" as T13_0 {
  ReturnType
}
class "formatter" as T13_1 {
  filib
}
}
package "python/src/collision_mesh.cpp" as F14 {
class "PairHash" as T14_0 {
  std
}
}
package "src/ipc/utils/default_init_allocator.hpp" as F15 {
class "rebind" as T15_0 {
  a_t
}
}
package "src/ipc/utils/autodiff_types.hpp" as F16 {
class "IsADGrad" as T16_0 {
}
class "IsADHessian" as T16_1 {
}
}
}
@enduml

7.3. Public interface

Outside code can use everything listed here. The project also declares 122 public types.

Command line 1

7.4. Private interface

These names are internal by the language’s conventions: a leading underscore, private, static or pub(crate).

anonymous namespace
25

Private modules

python/_find_ipctk.py

7.5. Entities and data model 12

Mermaid Entity class diagram
classDiagram
  direction LR
  class E0["MortonCodeElement"] {
    +uint64_t morton_code
    +size_t box_id
    +:string std
    +int parent
  }
  class E1["Boxes"] {
    +:vector std
    +:SweepAndPrune SweepAndPrune
  }
  class E2["ConstructionInfo"] {
    +int parent
    +:vector std
  }
  class E3["MeshDomain"] {
    +Constant Eigen
    +:blocked_range tbb
  }
  class E4["PrimitiveDistType"] {
    +:N_CORE_POINTS PrimitiveA
  }
  class E5["ScalarBinaryOpTraits"] {
    +typedef ReturnType
  }
  class E6["formatter"] {
    +:Interval filib
  }
  class E7["PairHash"] {
    +:size_t std
  }
  class E8["rebind"] {
    +:construct a_t
  }
  class E9["IsADGrad"] {
  }

An arrow links a field to the entity its type names.

EntityKindFirst fields
MortonCodeElementData structmorton_code, box_id, std, parent
BoxesData structstd, SweepAndPrune
ConstructionInfoData structparent, std
MeshDomainData structEigen, tbb
PrimitiveDistTypeData structPrimitiveA, Eigen
ScalarBinaryOpTraitsData structReturnType
formatterData structfilib
PairHashData structstd
Show 4 more entities
PrimitiveDistTypeData structPrimitiveA
rebindData structa_t
IsADGradData struct
IsADHessianData struct

7.6. Business logic

Once UI code and the services and entities above are set aside, these classes have the most methods.

CollisionMesh Core source, 36 methods
build_from_full_mesh, init_adjacencies, init_area_jacobians, num_vertices, num_codim_vertices, num_codim_edges
Math Domain and business rules, 19 methods
sign, abs, sqr, cubic, cubic_spline, cubic_spline_grad
CollisionStencil Core source, 19 methods
num_vertices, dim, vertex_ids, vertices, dof, compute_distance
NormalCollisions Core source, 19 methods
build, compute_minimum_distance, size, empty, clear, is_vertex_vertex
LBVH Core source, 18 methods
name, clear, detect_vertex_vertex_candidates, detect_edge_vertex_candidates, detect_edge_edge_candidates, detect_face_vertex_candidates
BroadPhase Core source, 17 methods
name, build, clear, detect_collision_candidates, detect_vertex_vertex_candidates, detect_edge_vertex_candidates
Candidates Core source, 15 methods
build, size, empty, clear, is_step_collision_free, compute_collision_free_stepsize
HashGrid Core source, 14 methods
name, clear, detect_vertex_vertex_candidates, detect_edge_vertex_candidates, detect_edge_edge_candidates, detect_face_vertex_candidates
SweepAndPrune Core source, 14 methods
name, build, clear, detect_vertex_vertex_candidates, detect_edge_vertex_candidates, detect_edge_edge_candidates
Edge3 Core source, 13 methods
n_vertices, n_dofs, n_face_neighbors, potential, grad, hessian

7.7. Stack and dependencies

C/C++ (CMake) CMakeLists.txt 1 runtime

C++17

Open the manifest

Python pyproject.toml 2 runtime

Python >=3.6

Open the manifest

External dependencies

3 declared packages (3 runtime, 0 development) in CMakeLists.txt, pyproject.toml.

Package table 3
External dependencies
PackageVersionScopePurposeRegistry
SIMD—runtime—C/C++ (CMake)
numpy—runtimeData analysispypi.org
scipy—runtimeData analysispypi.org

7.8. CI/CD pipeline

8 GitHub Actions workflows, 10 jobs. Each box is a job; double-bordered boxes publish or deploy, and arrows follow needs.

Mermaid Pipeline flow
flowchart LR
  subgraph wf0["clang-format Check"]
    direction LR
    wf0_formatting_check["Formatting Check<br/>ubuntu-latest"]
  end
  subgraph wf1["Clang-Tidy Check"]
    direction LR
    wf1_clang_tidy["Run Clang-Tidy<br/>ubuntu-latest"]
  end
  subgraph wf2["Build"]
    direction LR
    wf2_Build["Build<br/>matrix"]
  end
  subgraph wf3["Coverage"]
    direction LR
    wf3_Coverage["Code Coverage<br/>ubuntu-latest"]
  end
  subgraph wf4["CUDA"]
    direction LR
    wf4_Build["CUDA<br/>ubuntu-latest"]
  end
  subgraph wf5["Docs"]
    direction LR
    wf5_Docs[["Docs<br/>ubuntu-latest"]]
  end
  t0(["push · pull request"])
  t1(["manual run · push"])
  d0[("GitHub Pages")]
  t0 --> wf0_formatting_check
  t0 --> wf1_clang_tidy
  t0 --> wf2_Build
  t0 --> wf3_Coverage
  t0 --> wf4_Build
  t1 --> wf5_Docs
  wf5_Docs -.-> d0
Workflows, triggers, jobs and targets
WorkflowTriggersJobsPublishes to
clang-format Check
.github/workflows/clang-format-check.yml
push, pull request
  • Formatting Check ubuntu-latest
    actions/checkout · clang-format style check
—
Clang-Tidy Check
.github/workflows/clang-tidy-check.yml
push, pull request
  • Run Clang-Tidy ubuntu-latest
    Checkout code · Install dependencies · Get number of CPU cores · Configure CMake · Run Clang-Tidy
—
Build
.github/workflows/continuous.yml
push, pull request
  • Build matrix
    Checkout repository · Dependencies (Linux) · Dependencies (macOS) · Dependencies (Windows) · Install Ninja · Get number of CPU cores
—
Coverage
.github/workflows/coverage.yml
push, pull request
  • Code Coverage ubuntu-latest
    Checkout Repository · Dependencies · Get number of CPU cores · Cache Build · Prepare ccache · Configure
—
CUDA
.github/workflows/cuda.yml
push, pull request
  • CUDA ubuntu-latest
    Checkout repository · Dependencies · cuda-toolkit · Get number of CPU cores · Cache Build · Prepare ccache
—
Docs
.github/workflows/docs.yml
manual run, push
  • Docs ubuntu-latest
    Checkout repository · Set up Python · Requirements · Cache Build · Prepare Ccache · Copy release docs
GitHub Pages
PyPi Release
.github/workflows/pypi.yml
manual run
  • build_wheels matrix
    actions/checkout · Build wheels · actions/upload-artifact
  • Build source distribution ubuntu-latest
    actions/checkout · Build sdist · actions/upload-artifact
  • Upload to PyPI ← build_wheels, build_sdist ubuntu-latest
    Download wheels · Download source distribution · pypa/gh-action-pypi-publish
PyPI
Python
.github/workflows/python.yml
push, pull request
  • Build matrix
    Checkout Repository · Install Ccache (Linux) · Install Ccache (macOS) · Install Ccache (Windows) · Cache Build · Prepare Ccache
—

7.9. Deployment

Mermaid Deployment diagram
flowchart LR
  repo[("GitHub repository")]
  ci[["GitHub Actions<br/>8 workflows"]]
  image["Docker image"]
  pub_GitHub_Pages[("GitHub Pages")]
  pub_PyPI[("PyPI")]
  repo -->|"push or pull request"| ci
  ci -->|"docker build"| image
  ci -->|"publishes"| pub_GitHub_Pages
  ci -->|"publishes"| pub_PyPI
UML Deployment
Deployment

The outer node is where the code runs. Each base image points to what it builds, solid arrows lead to databases and dashed ones to outside services. Rendered with uml-mcp.

PlantUML source
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
node "Docker image" as H {
  artifact "ipc-toolkit" as APP
}
artifact "FROM ubuntu:22.04" as IMG0
IMG0 ..> APP : builds
@enduml

Where it runs

Published to

Docker base images

ubuntu:22.04

7.10. Monitoring

What the code logs, measures and exposes to tell whether it is working.

7.11. Security

Supply chain

Environment variables 4

The page lists names without their values and underlines the ones that look like secrets.

ARCHFLAGS CMAKE_ARGS CMAKE_GENERATOR DEBUG

7.12. Testing

Test files
80
Source files
324
Test cases, about
275
Unit tests
76
Benchmark tests
4

Code coverage

No measured coverage report in the analyzed sources.

Where the tests are

tests/src/tests/ccd 11 tests/src/tests/distance 10 python/tests 9 tests/src/tests 9 tests/src/tests/broad_phase 9 tests/src/tests/friction 7

Continuous integration

Build
ctest
UML CI pipeline
CI pipeline

The main GitHub Actions workflow runs these steps. Jobs that run in parallel sit side by side. Rendered with uml-mcp.

PlantUML source
@startuml
skinparam backgroundColor transparent
skinparam shadowing false
skinparam roundCorner 10
skinparam defaultFontName Arial
skinparam defaultFontSize 13
skinparam ArrowColor #4e6070
skinparam ArrowFontColor #3d4f5f
skinparam titleFontSize 14
skinparam actorBorderColor #006a62
skinparam actorBackgroundColor #e9f3f4
skinparam usecaseBorderColor #006a62
skinparam usecaseBackgroundColor #e9f3f4
skinparam componentBorderColor #006a62
skinparam componentBackgroundColor #e9f3f4
skinparam interfaceBorderColor #006a62
skinparam interfaceBackgroundColor #ffffff
skinparam nodeBorderColor #4e6070
skinparam nodeBackgroundColor #f4f8fb
skinparam databaseBorderColor #006a62
skinparam databaseBackgroundColor #ffffff
skinparam cloudBorderColor #4e6070
skinparam cloudBackgroundColor #f0f5fa
skinparam artifactBorderColor #006a62
skinparam artifactBackgroundColor #ffffff
skinparam rectangleBorderColor #b0c2d3
skinparam activityBorderColor #006a62
skinparam activityBackgroundColor #e9f3f4
skinparam partitionBorderColor #b0c2d3
skinparam stereotypeCBackgroundColor #ffffff
title Build
start
partition "Build" {
  :Checkout repository;
  :Dependencies (Linux);
  :Dependencies (macOS);
  :Dependencies (Windows);
  :Install Ninja;
  :Get number of CPU cores;
  :Cache Build;
  :Prepare ccache;
}
stop
@enduml

Nothing found for: Services, Database, External integrations.

8. Algorithm

8.1. Problem

Decide whether a CollisionMesh at given vertex positions intersects, or whether a proposed vertex displacement stays collision-free, so a contact-aware simulator can query geometry without owning the full time-step loop.

8.2. Inputs

A CollisionMesh plus current (and optionally proposed) vertex positions; broad-phase and narrow-phase CCD strategies are explicit parameters with defaults.

8.3. Outputs

Intersection or collision-free-step answers, plus contact-related quantities (distances, barriers, friction helpers) consumed by the caller’s objective — not a full scene solve.

8.4. Pseudocode (source-backed)

given mesh M, positions x, optional next positions x'
if has_intersections(M, x): report contact candidates
if not is_step_collision_free(M, x, x'): reject or shorten step
else: assemble contact energies/derivatives for the caller’s solver
  1. 1. Build or accept a collision mesh

    The library expects a CollisionMesh that separates geometry from the caller’s simulation state.

  2. 2. Broad-phase candidates

    Candidate pairs are discovered with an explicit broad-phase strategy before expensive narrow tests.

  3. 3. Narrow-phase CCD / intersection

    ipc.hpp entry points test intersections at a configuration or whether a displacement remains collision-free.

  4. 4. Contact quantities for the solver

    Distance, barrier, friction and related modules supply values and derivatives; the external simulation still owns time stepping.

No asymptotic complexity claim is published in this fork’s inspected headers; cost depends on mesh size, broad-phase choice and CCD settings used by the caller.

Inspected implementation

9. Types and file structure

140 declared types, with 12 in the base-relationship overview.

Type diagram
classDiagram
direction TB
class ta4ad2d054a1a["CXXFunctionGenerator"] {
  __init__()
  signature()
  __call__()
}
class t0935cb7a441b["CXXGradientGenerator"] {
  __init__()
}
class t1aec9e647746["CXXJacobianGenerator"] {
  __init__()
}
class t6c43b7865a81["CXXHessianGenerator"] {
  __init__()
}
class t05fe515aed0d["Inertia"] {
  __init__()
  __call__()
  gradient()
  hessian()
}
class tcb5b8ab75455["PyBarrier"] {
  first_derivative()
  second_derivative()
  units()
}
class te947d03a9485["PyBroadPhase"] {
  name()
  build()
  clear()
  detect_vertex_vertex_candidates()
}
class ta8c42662e683["PyNarrowPhaseCCD"] {
  point_point_ccd()
  point_edge_ccd()
  point_triangle_ccd()
  edge_edge_ccd()
}
class tb0adabdf7fe2["PyNonlinearTrajectory"] {
  max_distance_from_linear()
}
class tc83b025ce434["PyIntervalNonlinearTrajectory"] {
  max_distance_from_linear()
}
class t9ee9c14a4b05["PairHash"] {
  <<struct>>
}
class t5a3d1613cb4b["SparseCanCollide"] {
  SparseCanCollide()
}
ta4ad2d054a1a <|-- t0935cb7a441b
ta4ad2d054a1a <|-- t1aec9e647746
t1aec9e647746 <|-- t6c43b7865a81
class b7bd3eedf5849["Barrier"] {
  <<unresolved_base>>
}
b7bd3eedf5849 <|-- tcb5b8ab75455
class b80b43ba1bca8["BroadPhase"] {
  <<unresolved_base>>
}
b80b43ba1bca8 <|-- te947d03a9485
class b1ced31ba20e0["NarrowPhaseCCD"] {
  <<unresolved_base>>
}
b1ced31ba20e0 <|-- ta8c42662e683
class b9fe354f68d01["NonlinearTrajectory"] {
  <<unresolved_base>>
}
b9fe354f68d01 <|-- tb0adabdf7fe2
class b28bdf016fc91["IntervalNonlinearTrajectory"] {
  <<unresolved_base>>
}
b28bdf016fc91 <|-- tc83b025ce434

Unresolved bases remain labelled; full signatures are not reconstructed.

10. Reference

463 / 463 eligible files read (646 in the tree); 0 oversized, 0 failed reads and 74 syntax diagnostics.

What the scan covers

Known dependency/build folders, credential files and binaries are excluded. The scan covers READMEs, recognized manifests and parser-supported source files.

Linguist statistics cover the whole repository and may include other languages.

12. Files to read 3

13. Glossary

Repository

The versioned source files, configuration, and history of a project.

README

The repository’s entry document, usually covering its purpose and initial setup.

Dependency

A library, tool, or service that another component needs to build or run.

Container

An isolated process environment created from an image. Persistent data needs storage outside the container’s disposable filesystem.

Published port

A host port mapped to a service’s container port. Publishing a port can expose that service beyond its container network.

Build

The steps that turn source files and dependencies into a runnable program or distributable artifact.

Continuous integration

Automated checks that run when source changes, such as building, testing, and linting. Passing checks cover only what those checks exercise.

GPU

A processor designed for parallel workloads, including graphics rendering and many numerical operations.

Mesh

A surface represented by vertices and connected elements, often triangles. Its geometry is distinct from its material or texture.

Continuous collision detection

A test for contact during the motion between two states, rather than only at the sampled endpoints.

Fork

A separate repository derived from another project. A change in a fork is not automatically a change in the upstream project.

14. References

  1. antoinebou12. (2026, November 5). ipc-toolkit. [Software repository] github.com.
  2. antoinebou12. (2026, November 5). ipc-toolkit: README. [Repository documentation] github.com.
  3. antoinebou12. (2026, November 5). src/ipc/ipc.hpp. [Source file] github.com.
  4. antoinebou12. (2026, November 5). src/ipc/ipc.cpp. [Source file] github.com.
  5. antoinebou12. (2026, November 5). CMakeLists.txt. [Source file] github.com.
  6. Boucher, A. (2026, October 24). IPC Toolkit: collision and friction inside a simulation. [Project article] antoineboucher.info.
  7. Boucher, A. (2026, October 23). ipc-toolkit: Collision queries as a library boundary. [Project article] antoineboucher.info.

Sources without a publication date show the date they were last checked, November 5, 2026. File links retain the inspected revision where available.

Related article: IPC Toolkit: the contact library behind a simulation.