TriangleTriangleContactCalculation-inl.h
Go to the documentation of this file.
1 // This file is a part of the OpenSurgSim project.
2 // Copyright 2013, SimQuest Solutions Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef SURGSIM_MATH_TRIANGLETRIANGLECONTACTCALCULATION_INL_H
17 #define SURGSIM_MATH_TRIANGLETRIANGLECONTACTCALCULATION_INL_H
18 
19 namespace SurgSim
20 {
21 
22 namespace Math
23 {
24 
33 template <class T, int MOpt>
35 {
36  static const size_t CAPACITY = 10;
37  typedef Eigen::Matrix<T, 3, 1, MOpt> Vector3;
38  typedef boost::container::static_vector<Vector3, CAPACITY> Vertices;
39 
40 public:
44  TriangleHelper(const Vector3& v0, const Vector3& v1, const Vector3& v2, const Vector3& n)
46  {
47  m_vertices[0] = &v0;
48  m_vertices[1] = &v1;
49  m_vertices[2] = &v2;
50  m_planeD = -m_vertices[0]->dot(m_normal);
51  }
52 
58  void findDeepestPenetrationWithTriangle(const TriangleHelper& triangle, T* penetrationDepth,
59  Vector3* penetrationPoint0, Vector3* penetrationPoint1)
60  {
61  m_clippedVerticesBuffer[0].push_back(*m_vertices[0]);
62  m_clippedVerticesBuffer[0].push_back(*m_vertices[1]);
63  m_clippedVerticesBuffer[0].push_back(*m_vertices[2]);
65 
66  Vector3 clipPlaneNormal;
67  T clipPlaneD;
68 
69  for (size_t i = 0; i < 3; ++i)
70  {
71  triangle.getPrismPlane(i, &clipPlaneNormal, &clipPlaneD);
72  clipAgainstPlane(clipPlaneNormal, clipPlaneD);
73  }
74 
75  findDeepestVertexUnderPlane(triangle.m_normal, triangle.m_planeD, penetrationDepth, penetrationPoint0);
76 
77  SURGSIM_ASSERT(*penetrationDepth <= T(0))
78  << "The distance from triangle is calculated as " << *penetrationDepth << ". At this point in the"
79  << " algorithm, the depth is expected to be negative.";
80 
81  *penetrationPoint1 = *penetrationPoint0 - (triangle.m_normal * (*penetrationDepth));
82  *penetrationDepth = -(*penetrationDepth);
83  }
84 
85 private:
91  void getPrismPlane(size_t index, Vector3* planeNormal, T* planeD) const
92  {
93  *planeNormal = *m_vertices[(index + 1) % 3] - *m_vertices[index];
94  *planeNormal = planeNormal->cross(m_normal);
95  planeNormal->normalize();
96  *planeD = -m_vertices[index]->dot(*planeNormal);
97  }
98 
103  void clipAgainstPlane(const Vector3& planeN, T planeD)
104  {
105  // Loop through the edges starting from (m_vertices[0]->m_vertices[1]) to
106  // (m_vertices[m_numVertices - 1]->m_vertices[0]).
107  // The start vertex and end vertex can be either under/on/over the clipping plane.
108  // start | end | action
109  // ----------------------------------------------
110  // under | under | add start to clipped vertices
111  // under | on | add start to clipped vertices
112  // under | over | add start to clipped vertices, clip the edge to the plane (creating a vertex)
113  // on | under | add start to clipped vertices
114  // on | on | add start to clipped vertices
115  // on | over | add start to clipped vertices
116  // over | under | clip the edge to the plane (creating a vertex)