Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions python/src/barrier/adaptive_stiffness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void define_adaptive_stiffness(py::module_& m)
static_cast<Eigen::VectorXd (*)(
const CollisionMesh&, Eigen::ConstRef<Eigen::MatrixXd>,
const NormalCollisions&, Eigen::ConstRef<Eigen::VectorXd>,
const Eigen::SparseMatrix<double>&, const double)>(
const Eigen::SparseMatrix<double>&, const std::optional<double>)>(
&semi_implicit_stiffness),
R"ipc_Qu8mg5v7(
Compute the semi-implicit stiffness's for all collisions.
Expand All @@ -108,20 +108,20 @@ void define_adaptive_stiffness(py::module_& m)
collisions: Normal collisions.
vertex_masses: Lumped vertex masses.
hess: Hessian of the elasticity energy function.
dmin: Minimum distance between elements.
dmin: Deprecated minimum distance between elements. If given, it overrides each stencil's own (a collision's dmin, or a candidate's thickness).

Returns:
The semi-implicit stiffness's.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices"_a, "collisions"_a, "vertex_masses"_a, "hess"_a,
"dmin"_a);
"dmin"_a = py::none());

m.def(
"semi_implicit_stiffness",
static_cast<Eigen::VectorXd (*)(
const CollisionMesh&, Eigen::ConstRef<Eigen::MatrixXd>,
const Candidates&, Eigen::ConstRef<Eigen::VectorXd>,
const Eigen::SparseMatrix<double>&, const double)>(
const Eigen::SparseMatrix<double>&, const std::optional<double>)>(
&semi_implicit_stiffness),
R"ipc_Qu8mg5v7(
Compute the semi-implicit stiffness's for all collisions.
Expand All @@ -134,11 +134,11 @@ void define_adaptive_stiffness(py::module_& m)
collisions: Collisions candidates.
vertex_masses: Lumped vertex masses.
hess: Hessian of the elasticity energy function.
dmin: Minimum distance between elements.
dmin: Deprecated minimum distance between elements. If given, it overrides each stencil's own (a collision's dmin, or a candidate's thickness).

Returns:
The semi-implicit stiffness's.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices"_a, "collisions"_a, "vertex_masses"_a, "hess"_a,
"dmin"_a);
"dmin"_a = py::none());
}
18 changes: 10 additions & 8 deletions python/src/candidates/candidates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,14 @@ void define_candidates(py::module_& m)
mesh: The collision mesh.
vertices_t0: Surface vertex starting positions (rowwise).
vertices_t1: Surface vertex ending positions (rowwise).
min_distance: The minimum distance allowable between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
True if <b>any</b> collisions occur.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a, "min_distance"_a = 0.0,
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a,
"min_distance"_a = py::none(),
"narrow_phase_ccd"_a = DEFAULT_NARROW_PHASE_CCD)
.def(
"compute_collision_free_stepsize",
Expand All @@ -97,13 +98,14 @@ void define_candidates(py::module_& m)
mesh: The collision mesh.
vertices_t0: Surface vertex starting positions (rowwise). Assumed to be intersection free.
vertices_t1: Surface vertex ending positions (rowwise).
min_distance: The minimum distance allowable between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
A step-size :math:`\in [0, 1]` that is collision free. A value of 1.0 if a full step and 0.0 is no step.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a, "min_distance"_a = 0.0,
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a,
"min_distance"_a = py::none(),
"narrow_phase_ccd"_a = DEFAULT_NARROW_PHASE_CCD)
.def(
"compute_noncandidate_conservative_stepsize",
Expand All @@ -130,15 +132,15 @@ void define_candidates(py::module_& m)
vertices_t0: Surface vertex starting positions (rowwise).
vertices_t1: Surface vertex ending positions (rowwise).
dhat: Barrier activation distance.
min_distance: Minimum distance allowable between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).
broad_phase: Broad phase algorithm to use.
narrow_phase_ccd: Narrow phase CCD algorithm to use.

Returns:
A step-size :math:`\in [0, 1]` that is collision free.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a, "dhat"_a,
"min_distance"_a = 0.0, "broad_phase"_a = nullptr,
"min_distance"_a = py::none(), "broad_phase"_a = nullptr,
"narrow_phase_ccd"_a = DEFAULT_NARROW_PHASE_CCD)
.def(
"compute_per_vertex_safe_distances",
Expand All @@ -153,13 +155,13 @@ void define_candidates(py::module_& m)
mesh: The collision mesh.
vertices: Collision mesh vertex positions (rowwise).
inflation_radius: The inflation radius used to build the candidates.
min_distance: The minimum allowable distance between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).

Returns:
A vector of minimum distances, one for each vertex.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices"_a, "inflation_radius"_a,
"min_distance"_a = 0.0)
"min_distance"_a = py::none())
.def(
"edge_vertex_to_vertex_vertex",
[](const Candidates& C, const CollisionMesh& mesh,
Expand Down
45 changes: 45 additions & 0 deletions python/src/candidates/stencil_methods.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,14 @@
#include <common.hpp>

#include <ipc/candidates/collision_stencil.hpp>
#include <ipc/candidates/edge_edge.hpp>
#include <ipc/candidates/edge_vertex.hpp>
#include <ipc/candidates/face_vertex.hpp>
#include <ipc/candidates/plane_vertex.hpp>
#include <ipc/candidates/vertex_vertex.hpp>

#include <iostream>
#include <type_traits>
#include <tuple>

namespace ipc {
Expand Down Expand Up @@ -55,6 +61,45 @@ template <class C, class PyClass> void define_stencil_methods(PyClass& cls)
},
"Select this stencil's DOF from the full matrix of DOF.", "X"_a,
"edges"_a, "faces"_a)
.def(
"thickness",
[](const C& self, Eigen::ConstRef<Eigen::VectorXd> vertex_thickness,
Eigen::ConstRef<Eigen::VectorXd> edge_thickness,
Eigen::ConstRef<Eigen::VectorXd> face_thickness) {
// C++ indexes the vectors unchecked, so an empty or short one
// (e.g., a mesh without a thickness) must not reach it.
const auto check = [](Eigen::ConstRef<Eigen::VectorXd> t,
const index_t i, const char* name) {
if (i < 0 || i >= t.size()) {
throw py::index_error(
fmt::format(
"{} has no entry {} (size {})", name, i,
t.size()));
}
};
if constexpr (std::is_same_v<C, VertexVertexCandidate>) {
check(
vertex_thickness, self.vertex0_id, "vertex_thickness");
check(
vertex_thickness, self.vertex1_id, "vertex_thickness");
} else if constexpr (std::is_same_v<C, EdgeVertexCandidate>) {
check(edge_thickness, self.edge_id, "edge_thickness");
check(vertex_thickness, self.vertex_id, "vertex_thickness");
} else if constexpr (std::is_same_v<C, EdgeEdgeCandidate>) {
check(edge_thickness, self.edge0_id, "edge_thickness");
check(edge_thickness, self.edge1_id, "edge_thickness");
} else if constexpr (std::is_same_v<C, FaceVertexCandidate>) {
check(face_thickness, self.face_id, "face_thickness");
check(vertex_thickness, self.vertex_id, "vertex_thickness");
} else {
static_assert(std::is_same_v<C, PlaneVertexCandidate>);
check(vertex_thickness, self.vertex_id, "vertex_thickness");
}
return self.thickness(
vertex_thickness, edge_thickness, face_thickness);
},
"Get the sum of the two primitives' thicknesses (see CollisionMesh.set_thickness).",
"vertex_thickness"_a, "edge_thickness"_a, "face_thickness"_a)
// -- distance ------------------------------------------------------
.def(
"compute_distance",
Expand Down
63 changes: 63 additions & 0 deletions python/src/collision_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,69 @@ void define_collision_mesh(py::module_& m)
"are_area_jacobians_initialized",
&CollisionMesh::are_area_jacobians_initialized,
"Determine if the area Jacobians have been initialized by calling init_area_jacobians().")
.def(
"has_thickness", &CollisionMesh::has_thickness,
"Determine if the primitives have a thickness (see set_thickness).")
.def(
"vertex_thickness", &CollisionMesh::vertex_thickness,
"Get the thickness of a vertex (zero without a thickness).", "vi"_a)
.def(
"edge_thickness", &CollisionMesh::edge_thickness,
"Get the thickness of an edge (zero without a thickness).", "ei"_a)
.def(
"face_thickness", &CollisionMesh::face_thickness,
"Get the thickness of a face (zero without a thickness).", "fi"_a)
.def_property_readonly(
"vertex_thicknesses", &CollisionMesh::vertex_thicknesses,
"The thickness of the vertices (empty without a thickness).")
.def_property_readonly(
"edge_thicknesses", &CollisionMesh::edge_thicknesses,
"The thickness of the edges (empty without a thickness).")
.def_property_readonly(
"face_thicknesses", &CollisionMesh::face_thicknesses,
"The thickness of the faces (empty without a thickness).")
.def_property_readonly(
"max_thickness", &CollisionMesh::max_thickness,
"The largest thickness of any primitive (zero without a thickness).")
.def(
"set_thickness", &CollisionMesh::set_thickness,
R"ipc_Qu8mg5v7(
Give every vertex, edge, and face a thickness.

Each primitive is offset outward by its thickness, so two primitives touch when they are the sum of their thicknesses apart. Collisions built from this mesh add that sum to their minimum distance (NormalCollision.dmin), the broad phase inflates each primitive's box by its thickness, and CCD stops each pair at that sum plus the minimum distance. A sheet of total thickness h, for example, gives each of its primitives h / 2.

Parameters:
vertex_thickness: Thickness of each vertex (size num_vertices).
edge_thickness: Thickness of each edge (size num_edges).
face_thickness: Thickness of each face (size num_faces).
)ipc_Qu8mg5v7",
"vertex_thickness"_a, "edge_thickness"_a, "face_thickness"_a)
.def(
"set_vertex_thickness", &CollisionMesh::set_vertex_thickness,
R"ipc_Qu8mg5v7(
Give each vertex a thickness, which its edges and faces inherit.

An edge or face takes the largest thickness of its vertices.

Parameters:
vertex_thickness: Thickness of each vertex (size num_vertices).
)ipc_Qu8mg5v7",
"vertex_thickness"_a)
.def(
"set_face_thickness", &CollisionMesh::set_face_thickness,
R"ipc_Qu8mg5v7(
Give each face a thickness, which its edges and vertices inherit.

An edge or vertex takes the largest thickness of the faces it bounds. An edge on no face takes the larger thickness of its two vertices.

Parameters:
face_thickness: Thickness of each face (size num_faces).
vertex_thickness: Least thickness of each vertex (size num_vertices), or empty for zero. It is the whole thickness of a vertex on no face.
)ipc_Qu8mg5v7",
"face_thickness"_a, "vertex_thickness"_a = Eigen::VectorXd())
.def(
"clear_thickness", &CollisionMesh::clear_thickness,
"Remove the primitives' thickness.")
.def_static(
"construct_is_on_surface", &CollisionMesh::construct_is_on_surface,
R"ipc_Qu8mg5v7(
Expand Down
15 changes: 8 additions & 7 deletions python/src/collisions/normal/normal_collisions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ void define_normal_collisions(py::module_& m)
"build",
py::overload_cast<
const CollisionMesh&, Eigen::ConstRef<Eigen::MatrixXd>,
const double, const double, BroadPhase*>(
const double, const std::optional<double>, BroadPhase*>(
&NormalCollisions::build),
R"ipc_Qu8mg5v7(
Initialize the set of collisions used to compute the barrier potential.
Expand All @@ -175,17 +175,17 @@ void define_normal_collisions(py::module_& m)
mesh: The collision mesh.
vertices: Vertices of the collision mesh.
dhat: The activation distance of the barrier.
dmin: Minimum distance.
dmin: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every collision keeps this minimum distance and the mesh's thickness is ignored; otherwise each keeps its two primitives' thicknesses.
broad_phase: Broad-phase to use.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices"_a, "dhat"_a, "dmin"_a = 0,
"mesh"_a, "vertices"_a, "dhat"_a, "dmin"_a = py::none(),
"broad_phase"_a = nullptr)
.def(
"build",
py::overload_cast<
const Candidates&, const CollisionMesh&,
Eigen::ConstRef<Eigen::MatrixXd>, const double, const double>(
&NormalCollisions::build),
Eigen::ConstRef<Eigen::MatrixXd>, const double,
const std::optional<double>>(&NormalCollisions::build),
R"ipc_Qu8mg5v7(
Initialize the set of collisions used to compute the barrier potential.

Expand All @@ -194,12 +194,13 @@ void define_normal_collisions(py::module_& m)
mesh: The collision mesh.
vertices: Vertices of the collision mesh.
dhat: The activation distance of the barrier.
dmin: Minimum distance.
dmin: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every collision keeps this minimum distance and the mesh's thickness is ignored; otherwise each keeps its two primitives' thicknesses.

Raises:
ValueError: In 3D, if the candidates were built with all_types=True.
)ipc_Qu8mg5v7",
"candidates"_a, "mesh"_a, "vertices"_a, "dhat"_a, "dmin"_a = 0)
"candidates"_a, "mesh"_a, "vertices"_a, "dhat"_a,
"dmin"_a = py::none())
.def(
"compute_minimum_distance",
&NormalCollisions::compute_minimum_distance,
Expand Down
3 changes: 3 additions & 0 deletions python/src/collisions/tangential/tangential_collision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ void define_tangential_collision(py::module_& m)
"normal_force_magnitude",
&TangentialCollision::normal_force_magnitude,
"Normal force magnitude")
.def_readwrite(
"dmin", &TangentialCollision::dmin,
"Minimum distance of the normal collision this was built from")
.def_readwrite(
"mu_s", &TangentialCollision::mu_s,
"Ratio between normal and static tangential forces (e.g., friction coefficient)")
Expand Down
12 changes: 6 additions & 6 deletions python/src/ipc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ void define_ipc(py::module_& m)
mesh: The collision mesh.
vertices_t0: Surface vertex vertices at start as rows of a matrix.
vertices_t1: Surface vertex vertices at end as rows of a matrix.
min_distance: The minimum distance allowable between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).
broad_phase: Broad phase to use.
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
True if <b>any</b> collisions occur.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a, "min_distance"_a = 0.0,
"broad_phase"_a = nullptr,
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a,
"min_distance"_a = py::none(), "broad_phase"_a = nullptr,
py::arg_v(
"narrow_phase_ccd", DEFAULT_NARROW_PHASE_CCD,
"TightInclusionCCD()"));
Expand All @@ -51,15 +51,15 @@ void define_ipc(py::module_& m)
mesh: The collision mesh.
vertices_t0: Vertex vertices at start as rows of a matrix. Assumes vertices_t0 is intersection free.
vertices_t1: Surface vertex vertices at end as rows of a matrix.
min_distance: The minimum distance allowable between any two elements.
min_distance: Deprecated: give the mesh a thickness (CollisionMesh.set_thickness) instead. If given, every pair keeps this distance and the mesh's thickness is ignored; otherwise each pair keeps its two primitives' thicknesses (zero without a thickness).
broad_phase: Broad phase to use.
narrow_phase_ccd: The narrow phase CCD algorithm to use.

Returns:
A step-size :math:`\in [0, 1]` that is collision free. A value of 1.0 if a full step and 0.0 is no step.
)ipc_Qu8mg5v7",
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a, "min_distance"_a = 0.0,
"broad_phase"_a = nullptr,
"mesh"_a, "vertices_t0"_a, "vertices_t1"_a,
"min_distance"_a = py::none(), "broad_phase"_a = nullptr,
py::arg_v(
"narrow_phase_ccd", DEFAULT_NARROW_PHASE_CCD,
"TightInclusionCCD()"));
Expand Down
Loading
Loading