/usr/include/SurgSim/Collision/SegmentSegmentCcdMovingContact.h is in libopensurgsim-dev 0.7.0-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | // This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SURGSIM_COLLISION_SEGMENTSEGMENTCCDMOVINGCONTACT_H
#define SURGSIM_COLLISION_SEGMENTSEGMENTCCDMOVINGCONTACT_H
#include <array>
#include "SurgSim/Collision/SegmentSegmentCcdIntervalCheck.h"
#include "SurgSim/Collision/SegmentSegmentCcdStaticContact.h"
#include "SurgSim/Framework/Logger.h"
namespace SurgSim
{
namespace Math
{
class SegmentMeshShape;
};
namespace Collision
{
class CollisionPair;
/// SegmentSegmentCcdMovingContact computes the self collisions among a SegmentMesh under motion at two
/// time points parametrized over the time interval [0,1]. An initial phase uses the AABB tree to
/// select a set of potentially colliding segments from the SegmentMesh. For each of these
/// candidate segment pairs, the goal is to determine the point of earliest contact should any exist.
///
/// At the highest level the actual collision detection of candidate segment pairs is a two phase
/// algorithm. First determine if there is contact at the start of an interval and report the contact if
/// found. If no contact is found at the start, subdivide the interval, determine which of the resulting
/// candidate subintervals may have collisions, and then recursively check those promising subintervals.
/// Note that a simple algorithm based on interval arithmetic (including the Interval, LinearMotion and
/// Polynomial interval classes) allows for a quick determination of promising subintervals allowing many
/// of the subintervals to be pruned during the subdivision step without forcing the recursion to bottom out.
///
/// \sa Interval, LinearMotion, Polynomial, SegmentSegmentCcdIntervalCheck
///
class SegmentSegmentCcdMovingContact
{
public:
static const int SUB_POINTS_PARALLEL_CASE = 5;
static const int SUB_POINTS_COPLANAR_CASE = 10;
/// Constructor.
SegmentSegmentCcdMovingContact();
/// Calculate if, where, and when the segments p and q collide in the interval from t = 0 to t = 1
/// for "zero" thickness segments.
/// \param pt0Positions are the segment endpoints for the first segment at time t=0.
/// \param pt1Positions are the segment endpoints for the first segment at time t=1.
/// \param qt0Positions are the segment endpoints for the second segment at time t=0.
/// \param qt1Positions are the segment endpoints for the second segment at time t=1.
/// \param thicknessEpsilon spatial nearness criteria for declaring a contact.
/// \param timePrecisionEpsilon time nearness criteria for declaring a contact.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [out] parametric location of the collision along p in the interval [0, 1]
/// \param s [out] parametric location of the collision along q in the interval [0, 1]
/// \param pToQDir [out] direction from the contact point on p to the contact point on q
/// \return true if p and q collide in interval [0, 1]
bool collideMovingSegmentSegment(
const std::array<Math::Vector3d, 2>& pt0Positions,
const std::array<Math::Vector3d, 2>& pt1Positions,
const std::array<Math::Vector3d, 2>& qt0Positions,
const std::array<Math::Vector3d, 2>& qt1Positions,
double thicknessEpsilon,
double timePrecisionEpsilon,
double* t, double* r, double* s, Math::Vector3d* pToQDir);
/// Calculate if, where, and when the segments p and q collide in the interval from t = 0 to t = 1
/// for thick segments.
/// \param pt0Positions are the segment endpoints for the first segment at time t=0.
/// \param pt1Positions are the segment endpoints for the first segment at time t=1.
/// \param qt0Positions are the segment endpoints for the second segment at time t=0.
/// \param qt1Positions are the segment endpoints for the second segment at time t=1.
/// \param thicknessP radius of segment p.
/// \param thicknessQ radius of segment q.
/// \param timePrecisionEpsilon time nearness criteria for declaring a contact.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [out] parametric location of the collision along p in the interval [0, 1]
/// \param s [out] parametric location of the collision along q in the interval [0, 1]
/// \param pToQDir [out] direction from the contact point on p to the contact point on q at time t
/// \return true if p and q collide in interval [0, 1]
bool collideMovingSegmentSegment(
const std::array<Math::Vector3d, 2>& pt0Positions,
const std::array<Math::Vector3d, 2>& pt1Positions,
const std::array<Math::Vector3d, 2>& qt0Positions,
const std::array<Math::Vector3d, 2>& qt1Positions,
double thicknessP,
double thicknessQ,
double timePrecisionEpsilon,
double* t, double* r, double* s, Math::Vector3d* pToQDir);
protected:
/// Manage the collision of moving segments as a series of cases based on the segment
/// relationships over the moving interval.
/// \param pT0 are the segment endpoints for the first segment at time t=0.
/// \param pT1 are the segment endpoints for the first segment at time t=1.
/// \param qT0 are the segment endpoints for the second segment at time t=0.
/// \param qT1 are the segment endpoints for the second segment at time t=1.
/// \param thicknessP radius of segment p.
/// \param thicknessQ radius of segment q.
/// \param timePrecisionEpsilon time nearness criteria for declaring a contact.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [out] parametric location of the collision along p in the interval [0, 1]
/// \param s [out] parametric location of the collision along q in the interval [0, 1]
/// \return true if p and q collide in interval [0, 1]
bool collideSegmentSegmentBaseCase(
const std::array<Math::Vector3d, 2>& pT0,
const std::array<Math::Vector3d, 2>& pT1,
const std::array<Math::Vector3d, 2>& qT0,
const std::array<Math::Vector3d, 2>& qT1,
double thicknessP,
double thicknessQ,
double timePrecisionEpsilon,
double* t, double* r, double* s);
/// Manage the specific case of detecting collisions between segments p and q which are parallel throughout
/// the parametric time interval of interest [a, b].
/// \param pT0 are the segment endpoints for the first segment at time t=0.
/// \param pT1 are the segment endpoints for the first segment at time t=1.
/// \param qT0 are the segment endpoints for the second segment at time t=0.
/// \param qT1 are the segment endpoints for the second segment at time t=1.
/// \param a parametric starting point of the interval of interest.
/// \param b parametric ending point of the interval of interest.
/// \param thicknessP radius of segment p.
/// \param thicknessQ radius of segment q.
/// \param timePrecisionEpsilon time nearness criteria for declaring a contact.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [in/out] parametric location of the collision along p in the interval [0, 1]
/// \param s [in/out] parametric location of the collision along q in the interval [0, 1]
/// \param depth recursion depth.
/// \return true if p and q collide in interval [a, b]
bool collideSegmentSegmentParallelCase(
const std::array<Math::Vector3d, 2>& pT0,
const std::array<Math::Vector3d, 2>& pT1,
const std::array<Math::Vector3d, 2>& qT0,
const std::array<Math::Vector3d, 2>& qT1,
double a, double b,
double thicknessP, double thicknessQ,
double timePrecisionEpsilon,
double* t, double* r, double* s, int depth = 0);
/// Manage the specific case of detecting collisions between segments p and q which are coplanar throughout
/// the parametric time interval of interest [a, b].
/// \param pT0 are the segment endpoints for the first segment at time t=0.
/// \param pT1 are the segment endpoints for the first segment at time t=1.
/// \param qT0 are the segment endpoints for the second segment at time t=0.
/// \param qT1 are the segment endpoints for the second segment at time t=1.
/// \param a parametric starting point of the interval of interest.
/// \param b parametric ending point of the interval of interest.
/// \param thicknessP radius of segment p.
/// \param thicknessQ radius of segment q.
/// \param timePrecisionEpsilon time nearness criteria for declaring a contact.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [in/out] parametric location of the collision along p in the interval [0, 1]
/// \param s [in/out] parametric location of the collision along q in the interval [0, 1]
/// \param depth recursion depth.
/// \return true if p and q collide in interval [a, b]
bool collideSegmentSegmentCoplanarCase(
const std::array<Math::Vector3d, 2>& pT0, /* Segment 1 at t=0 */
const std::array<Math::Vector3d, 2>& pT1, /* Segment 1 at t=1 */
const std::array<Math::Vector3d, 2>& qT0, /* Segment 2 at t=0 */
const std::array<Math::Vector3d, 2>& qT1, /* Segment 2 at t=1 */
double a, double b, /* Interval boundaries */
double timePrecisionEpsilon,
double thicknessP, double thicknessQ,
double* t, double* r, double* s,
int depth = 0);
/// Manage the general case of detecting collisions between segments p and q over the parametric time
/// interval [a, b] when no special spatial relationships can be observed that improve performance.
/// \param state an encapsulation of the segment locations, movements, and detection parameters.
/// \param a parametric starting point of the interval of interest.
/// \param b parametric ending point of the interval of interest.
/// \param t [out] parametric location of the collision along the time axes in the interval [0, 1]
/// \param r [out] parametric location of the collision along p in the interval [0, 1]
/// \param s [out] parametric location of the collision along q in the interval [0, 1]
/// \param depth recursion depth.
/// \return true if p and q collide in interval [a, b]
bool collideSegmentSegmentGeneralCase(
const SegmentSegmentCcdIntervalCheck& state,
double a, double b, // Interval boundaries
double* t, double* r, double* s,
int depth = 0);
/// Safely normalize segments t0 and t1 consistently with each other. Under the assumption that they
/// both represent the same segment at two different time points. Ensure that for cases where the segment
/// is too small at one or both time points (i.e. they essentially degenerate to a point) that we make
/// an intelligent choice.
/// \param t0 segment at time 0
/// \param t1 segment at time 1
/// \param epsilon threshold for valid normalization value.
void normalizeSegmentsConsistently(Math::Vector3d* t0, Math::Vector3d* t1, double epsilon) const;
private:
/// Utility routine to perform a series of checks to determine if a collision is likely within an interval. The
/// checks seek to determine if two coplanar segments could have been out of contact at the start of an interval,
/// and then moved through a contact and back away. Among the values checked are the normals because a change in
/// normal direction of p X q indicates that p is now on the other side of q. Other checks are made for flipping
/// segments, etc.
/// \param rCurrent is the parametric location on segment p at the start of the current time interval
/// \param rNext is the parametric location on segment p at the end of the current time interval
/// \param sCurrent is the parametric location on segment q at the start of the current time interval
/// \param sNext is the parametric location on segment q at the end of the current time interval
/// \param nCurrent is the normal of p x q at the start of the current time interval
/// \param nNext is the normal of p x q at the current time point
/// \return true if the check indicates a collision may be possible for coplanar segments p and
/// q at the current time interval.
bool checkForCoplanarContactWithinInterval(double rCurrent, double rNext, double sCurrent, double sNext,
const Math::Vector3d& nCurrent, const Math::Vector3d& nNext) const;
/// Minimum distance precision epsilon used in continuous collision detection.
const double m_distanceEpsilon;
/// Utility class for testing interval boundary collisions.
Collision::SegmentSegmentCcdStaticContact m_staticTest;
/// Logger
std::shared_ptr<SurgSim::Framework::Logger> m_logger;
};
}; // namespace Collision
}; // namespace SurgSim
#endif // SURGSIM_COLLISION_SEGMENTSEGMENTCCDMOVINGCONTACT_H
|