Broad Phase

Broad Phase

class BroadPhase;

Inheritance diagram for ipc::BroadPhase:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "1" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase" fillcolor="#BFBFBF"] "2" [label="ipc::BruteForce" tooltip="ipc::BruteForce"] "3" [label="ipc::HashGrid" tooltip="ipc::HashGrid"] "4" [label="ipc::LBVH" tooltip="ipc::LBVH"] "5" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash"] "6" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune"] "7" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue"] "8" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH"] "2" -> "1" [dir=forward tooltip="public-inheritance"] "3" -> "1" [dir=forward tooltip="public-inheritance"] "4" -> "1" [dir=forward tooltip="public-inheritance"] "5" -> "1" [dir=forward tooltip="public-inheritance"] "6" -> "1" [dir=forward tooltip="public-inheritance"] "7" -> "1" [dir=forward tooltip="public-inheritance"] "8" -> "1" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::BroadPhase:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "1" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase" fillcolor="#BFBFBF"] "2" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" -> "2" [dir=forward tooltip="usage"] }

Base class for broad phase collision detection methods.

Subclassed by ipc::BruteForce, ipc::HashGrid, ipc::LBVH, ipc::SpatialHash, ipc::SweepAndPrune, ipc::SweepAndTiniestQueue, ipc::cuda::LBVH

Public Functions

inline virtual ~BroadPhase();
virtual std::string name() const = 0;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear();

Clear any built data.

void detect_collision_candidates(
    
Candidates& candidates, bool all_types = false) const;

Detect all collision candidates needed for a given dimensional simulation.

Parameters:
Candidates &candidates

The detected collision candidates (cleared first).

bool all_types = false

Also detect the candidate types that only ESP contact needs (vertex-vertex, edge-vertex, edge-face, and face-face in 3D).

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const
   
 = 0;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions (cleared first).

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const
   
 = 0;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions (cleared first).

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const
   
 = 0;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions (cleared first).

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const
   
 = 0;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions (cleared first).

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const
   
 = 0;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections (cleared first).

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const
   
 = 0;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions (cleared first).

Public Members

CollisionFilter can_vertices_collide;

Filter for determining if two vertices can collide.

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void compute_mesh_aabb(Eigen::Ref<Eigen::Array3d> mesh_min,
    
Eigen::Ref<Eigen::Array3d> mesh_max) const;

Compute the axis-aligned bounding box (AABB) of the mesh.

Parameters:
Eigen::Ref<Eigen::Array3d> mesh_min

[out] Minimum corner of the mesh AABB.

Eigen::Ref<Eigen::Array3d> mesh_max

[out] Maximum corner of the mesh AABB.

virtual bool can_edge_vertex_collide(size_t ei, size_t vi) const;
virtual bool can_edges_collide(size_t eai, size_t ebi) const;
virtual bool can_face_vertex_collide(size_t fi, size_t vi) const;
virtual bool can_edge_face_collide(size_t ei, size_t fi) const;
virtual bool can_faces_collide(size_t fai, size_t fbi) const;

Protected Attributes

AABBs vertex_boxes;

AABBs for the vertices.

AABBs edge_boxes;

AABBs for the edges.

AABBs face_boxes;

AABBs for the faces.

uint8_t dim = 0;

Dimension of the simulation for which the broad phase was built.

Brute Force

class BruteForce : public ipc::BroadPhase;

Inheritance diagram for ipc::BruteForce:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::BruteForce" tooltip="ipc::BruteForce" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::BruteForce:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::BruteForce" tooltip="ipc::BruteForce" fillcolor="#BFBFBF"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Brute force broad phase collision detection.

Public Functions

BruteForce() = default;
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

Private Functions

template <typename Candidate, bool triangular = false>
void detect_candidates(const AABBs& boxes0, const AABBs& boxes1,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Detect candidates for collisions between two sets of boxes.

Template Parameters:
typename Candidate

Type of the candidate.

bool triangular = false

Whether to consider (i, j) and (j, i) as the same.

Parameters:
const AABBs &boxes0

[in] First set of boxes.

const AABBs &boxes1

[in] Second set of boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Hash Grid

class HashGrid : public ipc::BroadPhase;

Inheritance diagram for ipc::HashGrid:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::HashGrid" tooltip="ipc::HashGrid" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::HashGrid:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::HashGrid" tooltip="ipc::HashGrid" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Hash grid broad phase collision detection.

Public Functions

HashGrid() = default;
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

inline virtual void clear() override;

Clear the hash grid.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

inline double cell_size() const;
inline const Eigen::Array3i& grid_size() const;
inline const Eigen::Array3d& domain_min() const;
inline const Eigen::Array3d& domain_max() const;
virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void resize(Eigen::ConstRef<Eigen::Array3d> domain_min,
    
Eigen::ConstRef<Eigen::Array3d> domain_max, double cell_size);
void insert_boxes();
void insert_boxes(
    
const AABBs& boxes, std::vector<HashItem>& items) const;
void insert_box(const AABB& aabb, const long id,
    
std::vector<HashItem>& items) const;

Add an AABB of the extents to the hash grid.

inline long hash(int x, int y, int z) const;

Create the hash of a cell location.

Protected Attributes

double m_cell_size = -1;
Eigen::Array3i m_grid_size;
Eigen::Array3d m_domain_min;
Eigen::Array3d m_domain_max;
std::vector<HashItem> vertex_items;
std::vector<HashItem> edge_items;
std::vector<HashItem> face_items;

Private Functions

template <typename Candidate>
void detect_candidates(const std::vector<HashItem>& items0,
    
const std::vector<HashItem>& items1, const AABBs& boxes0,
    
const AABBs& boxes1,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Find the candidate collisions between two sets of items.

Template Parameters:
typename Candidate

The type of collision candidate.

Parameters:
const std::vector<HashItem> &items0

[in] First set of items.

const std::vector<HashItem> &items1

[in] Second set of items.

const AABBs &boxes0

[in] First set’s boxes.

const AABBs &boxes1

[in] Second set’s boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two items can collide.

std::vector<Candidate> &candidates

[out] The candidate collisions.

template <typename Candidate>
void detect_candidates(const std::vector<HashItem>& items,
    
const AABBs& boxes,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates) const;

Find the candidate collisions among a set of items.

Template Parameters:
typename Candidate

The type of collision candidate.

Parameters:
const std::vector<HashItem> &items

[in] The set of items.

const AABBs &boxes

[in] The items’ boxes.

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two items can collide.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Spatial Hash

class SpatialHash : public ipc::BroadPhase;

Inheritance diagram for ipc::SpatialHash:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SpatialHash:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SpatialHash" tooltip="ipc::SpatialHash" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Spatial hash broad phase collision detection.

Public Functions

SpatialHash();
~SpatialHash();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

inline virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the spatial hash for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

inline virtual void build(
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the spatial hash for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

inline virtual void build(const AABBs& _vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t _dim) override;

Build the spatial hash from vertex boxes.

Parameters:
const AABBs &_vertex_boxes

AABB boxes for each vertex.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t _dim

Dimension of the simulation (2D or 3D)

void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double inflation_radius,
    
double voxel_size);

Build the spatial hash for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius

Radius of inflation around all elements.

double voxel_size

Size of the voxels used in the spatial hash.

void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double inflation_radius,
    
double voxel_size);

Build the spatial hash for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius

Radius of inflation around all elements.

double voxel_size

Size of the voxels used in the spatial hash.

void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim,
    
double voxel_size);

Build the spatial hash from vertex boxes.

Parameters:
const AABBs &vertex_boxes

AABB boxes for each vertex.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

double voxel_size

Size of the voxels used in the spatial hash.

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Private Functions

void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, double voxel_size);
int locate_voxel_index(Eigen::ConstRef<Eigen::Array3d> p) const;
Eigen::Array3i locate_voxel_axis_index(
    
Eigen::ConstRef<Eigen::Array3d> p) const;
void locate_box_voxel_axis_index(Eigen::Array3d min_corner,
    
Eigen::Array3d max_corner, Eigen::Ref<Eigen::Array3i> min_index,
    
Eigen::Ref<Eigen::Array3i> max_index,
    
const double inflation_radius = 0) const;
int voxel_axis_index_to_voxel_index(
    
Eigen::ConstRef<Eigen::Array3i> voxel_axis_index) const;
int voxel_axis_index_to_voxel_index(int ix, int iy, int iz) const;

Private Members

Eigen::Array3d left_bottom_corner;

The left bottom corner of the world bounding box.

Eigen::Array3d right_top_corner;

The right top corner of the world bounding box.

Eigen::Array3i voxel_count;

The number of voxels in each dimension.

std::unique_ptr<Impl> impl;

Pointer to the implementation details.

double one_div_voxel_size = -1;

1.0 / voxel_size

int voxel_count_0x1 = -1;

The number of voxels in the first two dimensions.

struct Impl;

Public Functions

inline void fill_voxel_to_primitives();
inline void clear();
inline bool is_vertex_index(int idx) const;

Check if primitive index refers to a vertex.

inline bool is_edge_index(int idx) const;

Check if primitive index refers to an edge.

inline bool is_triangle_index(int idx) const;

Check if primitive index refers to a triangle.

inline int to_edge_index(int idx) const;

Convert a primitive index to an edge index.

inline int to_triangle_index(int idx) const;

Convert a primitive index to a triangle index.

inline void query_point_for_points(
    
int vi, unordered_set<int>& vert_ids) const;
inline void query_point_for_edges(
    
int vi, unordered_set<int>& edge_ids) const;
inline void query_point_for_triangles(
    
int vi, unordered_set<int>& tri_ids) const;
inline void query_edge_for_edges(
    
int eai, unordered_set<int>& edge_ids) const;
inline void query_edge_for_triangles(
    
int ei, unordered_set<int>& tri_ids) const;
inline void query_triangle_for_triangles(
    
int ti, unordered_set<int>& tri_ids) const;

Public Members

unordered_map<int, std::vector<int>> voxel_to_primitives;

Map from voxel index to the primitive indices it contains.

std::vector<std::vector<int>> point_to_voxels;

Map from point index to the voxel indices it occupies.

std::vector<std::vector<int>> edge_to_voxels;

Map from edge index to the voxel indices it occupies.

std::vector<std::vector<int>> face_to_voxels;

Map from face index to the voxel indices it occupies.

int edge_start_ind = -1;

The index of the first edge in voxel_occupancies.

int tri_start_ind = -1;

The index of the first triangle in voxel_occupancies.

LBVH —

class LBVH : public ipc::BroadPhase;

Inheritance diagram for ipc::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::LBVH" tooltip="ipc::LBVH" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::LBVH" tooltip="ipc::LBVH" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Linear Bounding Volume Hierarchy (LBVH) broad phase collision detection.

Public Types

using Nodes = std::vector<Node, DefaultInitAllocator<Node>>;
using MortonCodeElements = std::vector<MortonCodeElement,
    DefaultInitAllocator<MortonCodeElement>>;
using RightmostLeaves
   
 = std::vector<int32_t, DefaultInitAllocator<int32_t>>;

For each node, the index of the rightmost leaf reachable from it.

Used to skip subtrees during triangular (self-collision) traversal.

Public Functions

LBVH();
~LBVH();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

void query_point(Eigen::ConstRef<RowVectorMax3d> q, double radius,
    
std::vector<index_t>& vertex_ids,
    
std::vector<index_t>& edge_ids,
    
std::vector<index_t>& face_ids) const;

Find the primitives whose AABB is within a radius of a point.

We test the built boxes against a box of half-width radius centered at q, so this is a broad phase only: callers still need an exact distance check. The tree is typically built with zero inflation so one build serves queries at any radius, since we apply the radius to the query box instead.

Parameters:
Eigen::ConstRef<RowVectorMax3d> q

Query point (2D or 3D, matching the mesh).

double radius

Half-width of the query box around q.

std::vector<index_t> &vertex_ids

[out] Ids of the nearby vertices.

std::vector<index_t> &edge_ids

[out] Ids of the nearby edges.

std::vector<index_t> &face_ids

[out] Ids of the nearby faces. Empty in 2D, where no face tree is built.

inline const Nodes& vertex_nodes() const;
inline const Nodes& edge_nodes() const;
inline const Nodes& face_nodes() const;
virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Public Members

Eigen::Array3d min;
Eigen::Array3d max;

Public Static Attributes

static constexpr index_t INVALID_ID = 0xFFFFFFFF;

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

void init_bvh(const AABBs& boxes, Nodes& lbvh,
    
RightmostLeaves& rightmost_leaves) const;

Initialize a LBVH from a set of boxes.

Parameters:
const AABBs &boxes

[in] Set of boxes to initialize the LBVH with.

Nodes &lbvh

[out] The LBVH to initialize.

RightmostLeaves &rightmost_leaves

[out] For each node, the rightmost leaf index reachable. Values are the leaf’s position in the Morton-sorted leaf array from [0, n) where n is the number of primitives.

inline bool has_vertices() const;
inline bool has_edges() const;
inline bool has_faces() const;
virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Protected Attributes

Nodes vertex_bvh;

BVH containing the vertices.

RightmostLeaves vertex_rightmost_leaves;

Rightmost leaf indices for vertex BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Nodes edge_bvh;

BVH containing the edges.

RightmostLeaves edge_rightmost_leaves;

Rightmost leaf indices for edge BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Nodes face_bvh;

BVH containing the faces.

RightmostLeaves face_rightmost_leaves;

Rightmost leaf indices for face BVH (used for self-collision skip).

Values are from [0, n) where n is the number of primitives. Values are the leaf’s position in the Morton-sorted leaf array.

Protected Static Functions

template <typename Candidate, bool swap_order = false,
    bool triangular = false>
static void detect_candidates(const Nodes& source,
    
const Nodes& target, const RightmostLeaves& rightmost_leaves,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates);

Detect candidate collisions between a LBVH and a sets of boxes.

Template Parameters:
typename Candidate

Type of candidate collision.

bool swap_order = false

Whether to swap the order of box id with the LBVH id when adding to the candidates.

bool triangular = false

Whether to consider (i, j) and (j, i) as the same.

Parameters:
const Nodes &source

[in] The LBVH to traverse.

const Nodes &target

[in] The LBVH to traverse.

const RightmostLeaves &rightmost_leaves

[in] The rightmost leaf indices for the target LBVH (used for self-collision skip).

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

template <typename Candidate>
static inline void detect_candidates(const Nodes& source_and_target,
    
const RightmostLeaves& rightmost_leaves,
    
const std::function<bool(size_t, size_t)>& can_collide,
    
std::vector<Candidate>& candidates);

Detect candidate collisions between a single LBVH and itself.

Template Parameters:
typename Candidate

Type of candidate collision.

Parameters:
const Nodes &source_and_target

[in] The LBVH to traverse.

const RightmostLeaves &rightmost_leaves

[in] The rightmost leaf indices for the LBVH (used for self-collision skip).

const std::function<bool(size_t, size_t)> &can_collide

[in] Function to determine if two primitives can collide given their ids.

std::vector<Candidate> &candidates

[out] The candidate collisions.

Private Types

using HostConstructionInfo = ConstructionInfo<std::atomic<int>>;
using ConstructionInfos = std::vector<HostConstructionInfo,
    DefaultInitAllocator<HostConstructionInfo>>;
using EdgeIndices = std::vector<std::array<index_t, 2>,
    DefaultInitAllocator<std::array<index_t, 2>>>;
using FaceIndices = std::vector<std::array<index_t, 3>,
    DefaultInitAllocator<std::array<index_t, 3>>>;

Private Members

EdgeIndices edge_vertex_ids;

Edge vertices in the original mesh order.

FaceIndices face_vertex_ids;

Face vertices in the original mesh order.

struct ipc::LBVH mesh_aabb;

The axis-aligned bounding box of the entire mesh.

template <typename Counter> struct ConstructionInfo;

Per-internal-node scratch for the bottom-up build.

See also

ipc::details::build_hierarchy_from_leaf

Template Parameters:
typename Counter

The visitation counter’s type: std::atomic<int> here, and a plain int for the device build in ipc::cuda::LBVH, where atomicAdd() supplies the atomicity.

Public Members

int left_range;

Left range endpoint passed up by the left child.

int right_range;

Right range endpoint passed up by the right child.

Counter visitation_count;

Number of threads that arrived at this node.

struct MortonCodeElement;

Public Members

uint64_t morton_code;

Key for sorting.

size_t box_id;

Pointer into boxes buffer.

struct Node;

Public Functions

inline bool is_inner() const;

Check if this node is an inner node.

inline bool is_leaf() const;

Check if this node is a leaf node.

inline bool is_valid() const;

Check if this node is valid.

inline bool intersects(const Node& other) const;

Check if this node’s AABB intersects with another node’s AABB.

Public Members

Eigen::Array3f aabb_min;

The min corner of the AABB.

Eigen::Array3f aabb_max;

The max corner of the AABB.

Public Static Attributes

static constexpr int32_t INVALID_POINTER = 0x0;

Sweep and Prune

class SweepAndPrune : public ipc::BroadPhase;

Inheritance diagram for ipc::SweepAndPrune:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SweepAndPrune:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SweepAndPrune" tooltip="ipc::SweepAndPrune" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Sweep and Prune broad phase collision detection.

Public Functions

SweepAndPrune();
~SweepAndPrune();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t dim) override;

Build the broad phase from precomputed AABBs.

Parameters:
const AABBs &vertex_boxes

Precomputed vertex AABBs

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Protected Functions

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Protected Attributes

std::unique_ptr<Boxes> boxes;
mutable int vv_sort_axis = 0;
mutable int ev_sort_axis = 0;
mutable int ee_sort_axis = 0;
mutable int fv_sort_axis = 0;
mutable int ef_sort_axis = 0;
mutable int ff_sort_axis = 0;
struct Boxes;

Public Functions

~Boxes() = default;

Public Members

std::vector<scalable_ccd::AABB> vertices;
std::vector<scalable_ccd::AABB> edges;
std::vector<scalable_ccd::AABB> faces;

Sweep and Tiniest Queue

Requires CUDA (IPC_TOOLKIT_WITH_CUDA).

class SweepAndTiniestQueue : public ipc::BroadPhase;

Inheritance diagram for ipc::SweepAndTiniestQueue:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::SweepAndTiniestQueue:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::SweepAndTiniestQueue" tooltip="ipc::SweepAndTiniestQueue" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Sweep and Tiniest Queue broad phase collision detection.

Public Functions

SweepAndTiniestQueue();
~SweepAndTiniestQueue();
inline virtual std::string name() const override;

Get the name of the broad phase method.

Returns:

The name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const uint8_t dim) override;

Build the broad phase from precomputed AABBs.

Parameters:
const AABBs &vertex_boxes

Precomputed vertex AABBs

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void clear() override;

Clear any built data.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions.

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions.

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions.

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions.

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections.

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for static collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0);

Build the broad phase for continuous collision detection.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertices of the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(const AABBs& vertex_boxes,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces, const uint8_t dim);

Build the broad phase for collision detection.

Parameters:
const AABBs &vertex_boxes

AABBs for the vertices.

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

const uint8_t dim

Dimension of the simulation (2D or 3D)

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces);

Build the broad phase for collision detection.

Note

Assumes the vertex_boxes have been built.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces

Private Functions

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Private Members

std::unique_ptr<Boxes> boxes;

LBVH (CUDA)

Requires CUDA (IPC_TOOLKIT_WITH_CUDA).

class LBVH : public ipc::BroadPhase;

Inheritance diagram for ipc::cuda::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "1" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH" fillcolor="#BFBFBF"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

Collaboration diagram for ipc::cuda::LBVH:

digraph { graph [bgcolor="#00000000"] node [shape=rectangle style=filled fillcolor="#FFFFFF" font=Helvetica padding=2] edge [color="#1414CE"] "2" [label="ipc::BroadPhase" tooltip="ipc::BroadPhase"] "3" [label="ipc::CollisionFilter" tooltip="ipc::CollisionFilter"] "1" [label="ipc::cuda::LBVH" tooltip="ipc::cuda::LBVH" fillcolor="#BFBFBF"] "2" -> "3" [dir=forward tooltip="usage"] "1" -> "2" [dir=forward tooltip="public-inheritance"] }

GPU Linear Bounding Volume Hierarchy (LBVH) broad phase.

A first-class GPU counterpart to ipc::LBVH: it builds the vertex/edge/face AABBs and their BVHs, and runs the traversal and mesh-connectivity filtering, entirely on the device. Construction uses Morton codes + the Apetrei [2014] single-pass bottom-up build and reuses the 32-byte ipc::LBVH::Node layout, so the device tree can be copied back to the host and validated against – or traversed by – the CPU code. The build, the scalar descent, and the shared-vertex exclusion are the same ipc::details functions ipc::LBVH runs; only the parallel launches, the sort, and the atomics are CUDA’s.

Detection runs the BVH descent (AABB overlap + triangular dedup) and the connectivity (shared-vertex) exclusion on the device. The user vertex filter (can_vertices_collide) is honored on the device only when it is the default accept-all filter; a non-trivial filter is applied on the host while materializing the device-emitted (connectivity-filtered) candidates. Either way the output matches the CPU ipc::LBVH exactly for any filter.

All device-side primitive and vertex ids are 32-bit, independent of ipc::index_t: ipc::LBVH::Node stores its primitive id as an int32_t, which already caps every LBVH at 2^31 - 1 primitives, and the connectivity and candidate buffers use the same width so a downstream kernel reads one consistent id type (see DeviceCandidateView).

The detect_*() methods are const, as the BroadPhase interface requires, but share device buffers; concurrent calls on one object are serialized by an internal mutex. Device memory is retained across clear() and build() (the candidate buffers keep their high-water-mark capacity so a per-frame call allocates nothing) and released by the destructor.

Public Functions

LBVH();
~LBVH();
LBVH(LBVH&& other) noexcept;

Move; the moved-from object is left cleared and usable.

LBVH& operator=(LBVH&& other) noexcept;

Move-assign; the moved-from object is left cleared and usable.

LBVH(const LBVH&) = delete;
LBVH& operator=(const LBVH&) = delete;
inline virtual std::string name() const override;

Get the name of the broad phase method.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the broad phase for static collision detection.

The vertex boxes and everything after them are built on the device.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices

Vertex positions (rowwise, |V| × 2 or |V| × 3).

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void build(Eigen::ConstRef<Eigen::MatrixXd> vertices_t0,
    
Eigen::ConstRef<Eigen::MatrixXd> vertices_t1,
    
Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces,
    
const double inflation_radius = 0) override;

Build the broad phase for continuous collision detection.

The vertex boxes and everything after them are built on the device.

Parameters:
Eigen::ConstRef<Eigen::MatrixXd> vertices_t0

Starting vertex positions (rowwise).

Eigen::ConstRef<Eigen::MatrixXd> vertices_t1

Ending vertex positions (rowwise).

Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

const double inflation_radius = 0

Radius of inflation around all elements.

virtual void clear() override;

Clear any built data. Device memory is retained for reuse.

virtual void detect_vertex_vertex_candidates(
    
std::vector<VertexVertexCandidate>& candidates) const override;

Find the candidate vertex-vertex collisions.

Parameters:
std::vector<VertexVertexCandidate> &candidates

[out] The candidate vertex-vertex collisions (cleared first).

virtual void detect_edge_vertex_candidates(
    
std::vector<EdgeVertexCandidate>& candidates) const override;

Find the candidate edge-vertex collisions.

Parameters:
std::vector<EdgeVertexCandidate> &candidates

[out] The candidate edge-vertex collisions (cleared first).

virtual void detect_edge_edge_candidates(
    
std::vector<EdgeEdgeCandidate>& candidates) const override;

Find the candidate edge-edge collisions.

Parameters:
std::vector<EdgeEdgeCandidate> &candidates

[out] The candidate edge-edge collisions (cleared first).

virtual void detect_face_vertex_candidates(
    
std::vector<FaceVertexCandidate>& candidates) const override;

Find the candidate face-vertex collisions.

Parameters:
std::vector<FaceVertexCandidate> &candidates

[out] The candidate face-vertex collisions (cleared first).

virtual void detect_edge_face_candidates(
    
std::vector<EdgeFaceCandidate>& candidates) const override;

Find the candidate edge-face intersections.

Parameters:
std::vector<EdgeFaceCandidate> &candidates

[out] The candidate edge-face intersections (cleared first).

virtual void detect_face_face_candidates(
    
std::vector<FaceFaceCandidate>& candidates) const override;

Find the candidate face-face collisions.

Parameters:
std::vector<FaceFaceCandidate> &candidates

[out] The candidate face-face collisions (cleared first).

DeviceCandidateView detect_vertex_vertex_candidates_device() const;
DeviceCandidateView detect_edge_vertex_candidates_device() const;
DeviceCandidateView detect_edge_edge_candidates_device() const;
DeviceCandidateView detect_face_vertex_candidates_device() const;
DeviceCandidateView detect_edge_face_candidates_device() const;
DeviceCandidateView detect_face_face_candidates_device() const;
size_t num_vertex_nodes() const;

Number of nodes in the vertex BVH (2 * n_leaves - 1, or 0).

size_t num_edge_nodes() const;

Number of nodes in the edge BVH (2 * n_leaves - 1, or 0).

size_t num_face_nodes() const;

Number of nodes in the face BVH (2 * n_leaves - 1, or 0).

void vertex_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the vertex BVH back to the host.

void edge_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the edge BVH back to the host.

void face_nodes_to_host(ipc::LBVH::Nodes& nodes,
    
ipc::LBVH::RightmostLeaves& rightmost_leaves) const;

Copy the face BVH back to the host.

Protected Functions

virtual void build(Eigen::ConstRef<Eigen::MatrixXi> edges,
    
Eigen::ConstRef<Eigen::MatrixXi> faces) override;

Build the device trees from BroadPhase::vertex_boxes.

Reached through the inherited BroadPhase::build(const AABBs&, edges,

faces, dim), which has copied the caller’s boxes into vertex_boxes. The boxes are uploaded and then, as in

ipc::LBVH, cleared from the host: the device trees make them redundant.

Parameters:
Eigen::ConstRef<Eigen::MatrixXi> edges

Collision mesh edges.

Eigen::ConstRef<Eigen::MatrixXi> faces

Collision mesh faces.

virtual bool can_edge_vertex_collide(
    
size_t ei, size_t vi) const override;
virtual bool can_edges_collide(
    
size_t eai, size_t ebi) const override;
virtual bool can_face_vertex_collide(
    
size_t fi, size_t vi) const override;
virtual bool can_edge_face_collide(
    
size_t ei, size_t fi) const override;
virtual bool can_faces_collide(
    
size_t fai, size_t fbi) const override;

Private Functions

Impl& impl() const;

The implementation, created on first use.

A moved-from object hands its Impl over and is left with none; rather than guard every method against that, this re-seeds it on demand, so a moved-from object behaves exactly like a cleared one. Allocating here instead of in the move is what lets the move be noexcept. Mutable because the const detect_*() methods, which the BroadPhase interface requires, do use (and mutate) the device buffers; see the class comment.

Private Members

mutable std::unique_ptr<Impl> m_impl;

See impl().

struct DeviceCandidateView;

Non-owning view of device-resident candidate pairs (SoA).

The pointers address device memory owned by this LBVH and stay valid until the next detect_*() or detect_*_device() call of the SAME candidate type (both variants share one buffer per type), or until clear(), build(), or destruction. The ids are int32_t, not index_t: see the class comment.

Public Members

const int32_t* a = nullptr;

Device pointer to the first ids.

const int32_t* b = nullptr;

Device pointer to the second ids.

size_t size = 0;

Number of candidate pairs.

AABB

class AABB;

Axis aligned bounding-box of some type.

Public Functions

AABB() = default;
AABB(Eigen::ConstRef<ArrayMax3d> min,
    
Eigen::ConstRef<ArrayMax3d> max);
inline AABB(const AABB& aabb1, const AABB& aabb2);
inline AABB(
    
const AABB& aabb1, const AABB& aabb2, const AABB& aabb3);
bool intersects(const AABB& other) const;

Check if another AABB intersects with this one.

Parameters:
const AABB &other

The other AABB.

Returns:

If the two AABBs intersect.

Public Members

Eigen::Array3d min;

Minimum corner of the AABB.

Eigen::Array3d max;

Maximum corner of the AABB.

std::array<index_t, 3> vertex_ids;

Vertex IDs attached to the AABB.

Public Static Functions

static AABB from_point(Eigen::ConstRef<VectorMax3d> p,
    
const double inflation_radius = 0);

Construct an AABB for a static point.

Parameters:
Eigen::ConstRef<VectorMax3d> p

The point’s position.

const double inflation_radius = 0

Radius of a sphere around the point which the AABB encloses.

Returns:

The constructed AABB.

static inline AABB from_point(Eigen::ConstRef<VectorMax3d> p_t0,
    
Eigen::ConstRef<VectorMax3d> p_t1,
    
const double inflation_radius = 0);

Construct an AABB for a moving point (i.e.

temporal edge).

Parameters:
Eigen::ConstRef<VectorMax3d> p_t0

The point’s position at time t=0.

Eigen::ConstRef<VectorMax3d> p_t1

The point’s position at time t=1.

const double inflation_radius = 0

Radius of a capsule around the temporal edge which the AABB encloses.

Returns:

The constructed AABB.

static void conservative_inflation(Eigen::Ref<ArrayMax3d> min,
    
Eigen::Ref<ArrayMax3d> max, const double inflation_radius);

Compute a conservative inflation of the AABB.

static inline double conservative_lower_bound(
    
const double v, const double inflation_radius);

Conservatively inflate one lower bound.

The single-coordinate policy behind conservative_inflation(): the bound is moved out by the radius, then nudged to the next representable double away from the box so rounding can never shrink it. Host/device so the GPU broad phases build bit-identical boxes.

Parameters:
const double v

The coordinate to bound from below.

const double inflation_radius

The radius to inflate by.

Returns:

The conservative lower bound.

static inline double conservative_upper_bound(
    
const double v, const double inflation_radius);

Conservatively inflate one upper bound.

Parameters:
const double v

The coordinate to bound from above.

const double inflation_radius

The radius to inflate by.

Returns:

The conservative upper bound.