SurfaceCollisions.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2016 Imperial College London
5  * Copyright 2013-2016 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_SurfaceCollisions_H
21 #define MIRTK_SurfaceCollisions_H
22 
23 #include "mirtk/SurfaceFilter.h"
24 
25 #include "mirtk/Math.h"
26 #include "mirtk/Array.h"
27 #include "mirtk/OrderedSet.h"
28 #include "mirtk/Memory.h"
29 #include "mirtk/PointSetExport.h"
30 
31 #include "vtkSmartPointer.h"
32 
33 class vtkPolyData;
34 class vtkDataArray;
35 
36 
37 namespace mirtk {
38 
39 
40 /**
41  * Auxiliary class used to find self-collisions of a triangulated surface mesh
42  *
43  * Instances of this class detect different types of self-collisions such as
44  * in particular self-intersections between non-adjacent as well as adjacent
45  * triangular faces and a list of non-adjacent faces which are about to collide,
46  * i.e., very close to each other. They are used to impose either hard or soft
47  * non-self-intersection constraints on a deformable surface.
48  */
50 {
51  mirtkObjectMacro(SurfaceCollisions);
52 
53  // ---------------------------------------------------------------------------
54  // Types
55 public:
56 
57  /// Type of self-collision
59  {
60  NoCollision, ///< No collision with another triangle within search range
61  Collision, ///< Unknown or mixed collision types
62  FrontfaceCollision, ///< Second triangle is within minimum distance towards the front of first triangle
63  BackfaceCollision, ///< Second triangle is within minimum distance towards the back of first triangle
64  Intersection, ///< Unknown or mixed intersection types
65  SelfIntersection, ///< Non-adjacent triangles intersect each other
66  AdjacentIntersection, ///< Adjacent triangles intersect each other
67  Ambiguous ///< Both collisions and self-intersections found
68  };
69 
70  // Names of data arrays
71  MIRTK_PointSet_EXPORT static const char * const BOUNDING_SPHERE_CENTER;
72  MIRTK_PointSet_EXPORT static const char * const BOUNDING_SPHERE_RADIUS;
73  MIRTK_PointSet_EXPORT static const char * const COLLISION_TYPE;
74 
75  /// Whether a given collision type indicates a near miss collision
76  static bool IsCollision(CollisionType);
77 
78  /// Whether a given collision type indicates a self-intersection
79  static bool IsIntersection(CollisionType);
80 
81  /// Structure storing information about detected self-intersection
83  {
84  int _CellId; ///< ID of other triangle
85  bool _Adjacent; ///< Whether triangles are adjacent
86 
87  IntersectionInfo(int cellId = -1, bool adj = false)
88  :
89  _CellId(cellId), _Adjacent(adj)
90  {}
91 
93  :
94  _CellId(other._CellId), _Adjacent(other._Adjacent)
95  {}
96 
97  IntersectionInfo &operator =(const IntersectionInfo &other)
98  {
99  _CellId = other._CellId;
100  _Adjacent = other._Adjacent;
101  return *this;
102  }
103 
104  bool operator <(const IntersectionInfo &rhs) const
105  {
106  return _CellId < rhs._CellId;
107  }
108  };
109 
110  /// Structure storing information about detected collision
112  {
113  int _CellId; ///< ID of other triangle
114  double _Point1[3]; ///< Point in this triangle which is closest
115  double _Point2[3]; ///< Point in other triangle which is closest
116  double _Distance; ///< Distance between closest points
117  CollisionType _Type; ///< Type of collision
118 
119  CollisionInfo(int cellId = -1)
120  :
121  _CellId(cellId),
122  _Distance(numeric_limits<double>::quiet_NaN()),
123  _Type(Collision)
124  {
125  memset(_Point1, 0, 3 * sizeof(double));
126  memset(_Point2, 0, 3 * sizeof(double));
127  }
128 
129  CollisionInfo(int cellId, const double p1[3], const double p2[3], CollisionType type = Collision)
130  :
131  _CellId(cellId),
132  _Type(type)
133  {
134  memcpy(_Point1, p1, 3 * sizeof(double));
135  memcpy(_Point2, p2, 3 * sizeof(double));
136  const double a = _Point2[0] - _Point1[0];
137  const double b = _Point2[1] - _Point1[1];
138  const double c = _Point2[2] - _Point1[2];
139  _Distance = sqrt(a * a + b * b + c * c);
140  }
141 
142  CollisionInfo(int cellId, const double p1[3], const double p2[3], double dist, CollisionType type = Collision)
143  :
144  _CellId(cellId),
145  _Distance(dist),
146  _Type(type)
147  {
148  memcpy(_Point1, p1, 3 * sizeof(double));
149  memcpy(_Point2, p2, 3 * sizeof(double));
150  }
151 
152  CollisionInfo(const CollisionInfo &other)
153  :
154  _CellId(other._CellId),
155  _Distance(other._Distance),
156  _Type(other._Type)
157  {
158  memcpy(_Point1, other._Point1, 3 * sizeof(double));
159  memcpy(_Point2, other._Point2, 3 * sizeof(double));
160  }
161 
162  CollisionInfo &operator =(const CollisionInfo &other)
163  {
164  _CellId = other._CellId;
165  _Distance = other._Distance;
166  _Type = other._Type;
167  memcpy(_Point1, other._Point1, 3 * sizeof(double));
168  memcpy(_Point2, other._Point2, 3 * sizeof(double));
169  return *this;
170  }
171 
172  bool operator <(const CollisionInfo &rhs) const
173  {
174  return _CellId < rhs._CellId;
175  }
176  };
177 
178  typedef OrderedSet<IntersectionInfo> IntersectionsSet;
179  typedef IntersectionsSet::const_iterator IntersectionsIterator;
180  typedef Array<IntersectionsSet> IntersectionsArray;
181 
182  typedef OrderedSet<CollisionInfo> CollisionsSet;
183  typedef CollisionsSet::const_iterator CollisionsIterator;
184  typedef Array<CollisionsSet> CollisionsArray;
185 
186  // ---------------------------------------------------------------------------
187  // Attributes
188 private:
189 
190  /// Optional mask of input triangles to check
191  mirtkPublicAttributeMacro(vtkSmartPointer<vtkDataArray>, Mask);
192 
193  /// Use BoundingSphereCenter and BoundingSphereRadius cell data arrays of input
194  mirtkPublicAttributeMacro(bool, UseInputBoundingSpheres);
195 
196  /// Minimum search radius around triangle center used to determine the set
197  /// of nearby triangles to be tested for collisions with this triangle
198  mirtkPublicAttributeMacro(double, MinSearchRadius);
199 
200  /// Maximum search radius around triangle center used to determine the set
201  /// of nearby triangles to be tested for collisions with this triangle
202  mirtkPublicAttributeMacro(double, MaxSearchRadius);
203 
204  /// Minimum required distance between non-adjacent triangular faces
205  ///
206  /// This distance threshold applies when the center point of the other
207  /// face is in front of the current triangle whose collisions with other
208  /// triangles is being determined (cf. CollisionType::FrontfaceCollision).
209  mirtkPublicAttributeMacro(double, MinFrontfaceDistance);
210 
211  /// Minimum required distance between non-adjacent triangular faces
212  ///
213  /// This distance threshold applies when the center point of the other
214  /// face is at the backside of the current triangle whose collisions with other
215  /// triangles is being determined (cf. CollisionType::BackfaceCollision).
216  mirtkPublicAttributeMacro(double, MinBackfaceDistance);
217 
218  /// Maximum angle between face normal and center to center point vector
219  /// required for collision to be detected
220  mirtkPublicAttributeMacro(double, MaxAngle);
221 
222  /// Whether to perform intersection tests between adjacent triangles
223  mirtkPublicAttributeMacro(bool, AdjacentIntersectionTest);
224 
225  /// Whether to perform intersection tests between non-adjacent triangles
226  mirtkPublicAttributeMacro(bool, NonAdjacentIntersectionTest);
227 
228  /// Whether to detect collisions with the front of a face
229  mirtkPublicAttributeMacro(bool, FrontfaceCollisionTest);
230 
231  /// Whether to detect collisions with the back of a face
232  mirtkPublicAttributeMacro(bool, BackfaceCollisionTest);
233 
234  /// Whether to use fast, approximate collision test
235  mirtkPublicAttributeMacro(bool, FastCollisionTest);
236 
237  /// Whether to store detailed information about found self-intersections
238  mirtkPublicAttributeMacro(bool, StoreIntersectionDetails);
239 
240  /// Whether to store detailed information about found collisions
241  mirtkPublicAttributeMacro(bool, StoreCollisionDetails);
242 
243  /// Whether to clear collision type for unchecked triangles (cf. _Mask)
244  mirtkPublicAttributeMacro(bool, ResetCollisionType);
245 
246  /// Found self-intersections per face
247  /// \note Only non-empty after Run when _StoreIntersectionDetails is \c true.
248  mirtkReadOnlyAttributeMacro(IntersectionsArray, Intersections);
249 
250  /// Found collisions per face
251  /// \note Only non-empty after Run when _StoreCollisionDetails is \c true.
252  mirtkReadOnlyAttributeMacro(CollisionsArray, Collisions);
253 
254  /// Copy attributes of this class from another instance
255  void CopyAttributes(const SurfaceCollisions &);
256 
257  // ---------------------------------------------------------------------------
258  // Construction/destruction
259 public:
260 
261  /// Constructor
263 
264  /// Copy constructor
266 
267  /// Assignment operator
268  SurfaceCollisions &operator =(const SurfaceCollisions &);
269 
270  /// Destructor
271  virtual ~SurfaceCollisions();
272 
273  // ---------------------------------------------------------------------------
274  // Execution
275 protected:
276 
277  /// Initialize filter after input and parameters are set
278  virtual void Initialize();
279 
280  /// Execute filter
281  virtual void Execute();
282 
283  // ---------------------------------------------------------------------------
284  // Output
285 public:
286 
287  /// Get cell data array storing radii of bounding spheres
288  vtkDataArray *GetRadiusArray() const;
289 
290  /// Get cell data array storing center points of bounding spheres
291  vtkDataArray *GetCenterArray() const;
292 
293  /// Get cell data array storing type of cell collision
294  vtkDataArray *GetCollisionTypeArray() const;
295 
296  /// Get type of cell collision
297  CollisionType GetCollisionType(int) const;
298 
299  /// Get type of cell collision
300  CollisionType GetCollisionType(vtkIdType) const;
301 
302  /// Set of intersections of other faces with the specified cell
303  /// \note Use only when intersection tests enabled.
304  const IntersectionsSet &Intersections(int) const;
305 
306  /// Set of collisions of other faces with the specified cell
307  /// \note Use only when collision tests enabled.
308  const CollisionsSet &Collisions(int) const;
309 
310  /// Whether at least one intersection was found
311  bool FoundIntersections() const;
312 
313  /// Whether at least one collision was found
314  bool FoundCollisions() const;
315 
316  /// Number of self-intersections with specified cell
317  ///
318  /// \note Use only when both intersection tests and storage of intersection
319  /// details are enabled.
320  int NumberOfIntersections(int) const;
321 
322  /// Number of collisions with specified cell
323  ///
324  /// \note Use only when both collision tests and storage of collision details
325  /// are enabled.
326  int NumberOfCollisions(int) const;
327 
328  /// Enable/disable intersection test for adjacent triangles
329  mirtkOnOffMacro(AdjacentIntersectionTest);
330 
331  /// Enable/disable intersection test for non-adjacent triangles
332  mirtkOnOffMacro(NonAdjacentIntersectionTest);
333 
334  /// Enable/disable near miss collision test for front-facing triangles
335  mirtkOnOffMacro(FrontfaceCollisionTest);
336 
337  /// Enable/disable near miss collision test for back-facing triangles
338  mirtkOnOffMacro(BackfaceCollisionTest);
339 
340  /// Enable/disable fast, approximate collision test
341  mirtkOnOffMacro(FastCollisionTest);
342 
343  /// Enable/disable storage of details about found intersections
344  mirtkOnOffMacro(StoreIntersectionDetails);
345 
346  /// Enable/disable storage of details about found intersections
347  mirtkOnOffMacro(StoreCollisionDetails);
348 
349  /// Enable/disable resetting of optional input collision type array
350  mirtkOnOffMacro(ResetCollisionType);
351 
352 };
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 // Inline definitions
356 ////////////////////////////////////////////////////////////////////////////////
357 
358 // -----------------------------------------------------------------------------
360 {
361  return (Collision <= type && type < Intersection) || (type == Ambiguous);
362 }
363 
364 // -----------------------------------------------------------------------------
366 {
367  return Intersection <= type && type <= Ambiguous;
368 }
369 
370 // -----------------------------------------------------------------------------
371 inline const SurfaceCollisions::IntersectionsSet &
373 {
374  return _Intersections[cellId];
375 }
376 
377 // -----------------------------------------------------------------------------
378 inline const SurfaceCollisions::CollisionsSet &
380 {
381  return _Collisions[cellId];
382 }
383 
384 // -----------------------------------------------------------------------------
385 inline int SurfaceCollisions::NumberOfIntersections(int cellId) const
386 {
387  return static_cast<int>(Intersections(cellId).size());
388 }
389 
390 // -----------------------------------------------------------------------------
391 inline int SurfaceCollisions::NumberOfCollisions(int cellId) const
392 {
393  return static_cast<int>(Collisions(cellId).size());
394 }
395 
396 
397 } // namespace mirtk
398 
399 #endif // MIRKT_SurfaceCollisions_H
vtkDataArray * GetCenterArray() const
Get cell data array storing center points of bounding spheres.
Non-adjacent triangles intersect each other.
const CollisionsSet & Collisions(int) const
vtkDataArray * GetCollisionTypeArray() const
Get cell data array storing type of cell collision.
int NumberOfCollisions(int) const
static bool IsCollision(CollisionType)
Whether a given collision type indicates a near miss collision.
Adjacent triangles intersect each other.
Structure storing information about detected self-intersection.
Second triangle is within minimum distance towards the back of first triangle.
vtkDataArray * GetRadiusArray() const
Get cell data array storing radii of bounding spheres.
virtual void Initialize()
Initialize filter after input and parameters are set.
int NumberOfIntersections(int) const
double _Distance
Distance between closest points.
Unknown or mixed collision types.
Definition: IOConfig.h:41
static bool IsIntersection(CollisionType)
Whether a given collision type indicates a self-intersection.
bool FoundCollisions() const
Whether at least one collision was found.
No collision with another triangle within search range.
bool _Adjacent
Whether triangles are adjacent.
virtual ~SurfaceCollisions()
Destructor.
Unknown or mixed intersection types.
Both collisions and self-intersections found.
bool FoundIntersections() const
Whether at least one intersection was found.
double _Point2[3]
Point in other triangle which is closest.
Structure storing information about detected collision.
Second triangle is within minimum distance towards the front of first triangle.
double _Point1[3]
Point in this triangle which is closest.
const IntersectionsSet & Intersections(int) const
CollisionType _Type
Type of collision.
virtual void Execute()
Execute filter.
CollisionType GetCollisionType(int) const
Get type of cell collision.
CollisionType
Type of self-collision.
SurfaceCollisions()
Constructor.
mirtkOnOffMacro(AdjacentIntersectionTest)
Enable/disable intersection test for adjacent triangles.