fw4spl
LineFunctions.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2015.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwMath/LineFunctions.hpp"
8 #include "fwMath/VectorFunctions.hpp"
9 #include "fwMath/PlaneFunctions.hpp"
10 
11 #include <glm/glm.hpp>
12 #include <glm/gtc/type_ptr.hpp>
13 
14 #include <limits>
15 
16 namespace fwMath
17 {
18 
19 //------------------------------------------------------------------------------
20 
21 bool getClosestPoints( const fwLine& _ray1, const fwLine& _ray2, fwVec3d& _pointOnThis, fwVec3d& _pointOnfwLine)
22 {
23  const ::glm::dvec3 pos1 = ::glm::make_vec3<double>(_ray1.first.data());
24  const ::glm::dvec3 dir1 = ::glm::make_vec3<double>(_ray1.second.data());
25 
26  const ::glm::dvec3 pos2 = ::glm::make_vec3<double>(_ray2.first.data());
27  const ::glm::dvec3 dir2 = ::glm::make_vec3<double>(_ray2.second.data());
28 
29  double dd = ::glm::dot(dir1, dir2);
30  double delta = 1.0 - dd * dd;
31 
32  if(delta < std::numeric_limits<double>::epsilon())
33  {
34  return false;
35  }
36 
37  double t2 = ( ::glm::dot(dir2, pos1 - pos2) - ::glm::dot(dir1, pos1-pos2) * dd)/delta;
38  double t1 = ( -::glm::dot(dir1, pos1 - pos2) + ::glm::dot(dir2, pos1-pos2) * dd)/delta;
39 
40  const ::glm::dvec3 pointOnThis = pos1 + t1 * dir1;
41  const ::glm::dvec3 pointOnfwLine = pos2 + t2 * dir2;
42 
43  _pointOnThis[0] = pointOnThis[0];
44  _pointOnThis[1] = pointOnThis[1];
45  _pointOnThis[2] = pointOnThis[2];
46 
47  _pointOnfwLine[0] = pointOnfwLine[0];
48  _pointOnfwLine[1] = pointOnfwLine[1];
49  _pointOnfwLine[2] = pointOnfwLine[2];
50 
51  return true;
52 }
53 
54 //------------------------------------------------------------------------------
55 
56 fwVec3d getClosestPoint( const fwLine& _ray, const fwVec3d& _point)
57 {
58  const ::glm::dvec3 pos = ::glm::make_vec3<double>(_ray.first.data());
59  const ::glm::dvec3 dir = ::glm::make_vec3<double>(_ray.second.data());
60  const ::glm::dvec3 point = ::glm::make_vec3<double>(_point.data());
61 
62  double t = ::glm::dot(point - pos, dir);
63  const ::glm::dvec3 pt = (pos + t * dir);
64 
65  fwVec3d res;
66  res[0] = pt[0];
67  res[1] = pt[1];
68  res[2] = pt[2];
69 
70  return res;
71 }
72 
73 //------------------------------------------------------------------------------
74 
75 bool intersect(const fwLine& _ray, double _radius, const fwVec3d& _point)
76 {
77  fwVec3d point = getClosestPoint(_ray, _point);
78  const ::glm::dvec3 pt1 = ::glm::make_vec3<double>(_point.data());
79  const ::glm::dvec3 pt2 = ::glm::make_vec3<double>(point.data());
80  ::glm::dvec3 tmp = pt1-pt2;
81  double length = ::glm::length(tmp);
82  return (length <= _radius);
83 }
84 
85 //------------------------------------------------------------------------------
86 
87 bool intersect(const fwLine& _ray, double _radius, const fwVec3d& _origin, const fwVec3d& _direction, fwVec3d& _point)
88 {
89  fwLine line = std::pair<fwVec3d, fwVec3d>(_origin, _direction);
90  fwVec3d pThis;
91  if(getClosestPoints(_ray, line, pThis, _point) == false)
92  {
93  return false;
94  }
95 
96  const ::glm::dvec3 pt1 = ::glm::make_vec3<double>(_point.data());
97  const ::glm::dvec3 pt2 = ::glm::make_vec3<double>(pThis.data());
98  ::glm::dvec3 tmp = pt1-pt2;
99  double length = ::glm::length(tmp);
100 
101  return (length <= _radius);
102 }
103 
104 //------------------------------------------------------------------------------
105 
106 bool intersect( const fwLine& _line, const fwVec3d& _v1, const fwVec3d& _v2, const fwVec3d& _v3, fwVec3d& _point,
107  fwVec3d& _barycentric, bool& _front)
108 {
109  _barycentric = (_v1 + _v2 + _v3)/3.;
110  const fwVec3d v01 = _v2 - _v1;
111  const fwVec3d v12 = _v3 - _v2;
112  const fwVec3d v20 = _v1 - _v3;
113 
114  const fwPlane plane = getPlane(_v1, _v2, _v3);
115 
116  fwVec3d v;
117  v[0] = 0.0F;
118  v[1] = 0.0F;
119  v[2] = 1.0F;
120 
121  const fwVec3d& normal = getNormal(plane);
122  _front = ((dot(normal,v )) >= 0.0);
123 
124  bool isIntersect = true;
125  if(intersect(plane, _line, _point) == false)
126  {
127  isIntersect = false;
128  }
129  else if((dot(normal, cross(v01, _point-_v1))) < 0.0)
130  {
131  isIntersect = false;
132  }
133  else if((dot(normal, cross(v12, _point-_v2))) < 0.0)
134  {
135  isIntersect = false;
136  }
137  else if((dot(normal, cross(v20, _point-_v3))) < 0.0)
138  {
139  isIntersect = false;
140  }
141 
142  return isIntersect;
143 }
144 
145 } //namespace fwMath
FWMATH_API fwVec3d cross(const fwVec3d &v1, const fwVec3d &v2)
Compute the Cross product between two vectors.
FWMATH_API fwVec3d getClosestPoint(const fwLine &_ray, const fwVec3d &_point)
Compute the projection of a point in a given direction.
The namespace fwMath contains classes which provide the implementation of several mathematic function...
Definition: Compare.hpp:12
FWMATH_API bool getClosestPoints(const fwLine &_ray1, const fwLine &_ray2, fwVec3d &_pointOnThis, fwVec3d &_pointOnfwLine)
Compute the closest points between two rays.
FWMATH_API double dot(const fwVec3d &v1, const fwVec3d &v2)
Compute the Dot product between two vectors.
FWMATH_API fwVec3d getNormal(const fwPlane &_plane)
Return the normal of the given plane _plane.
FWMATH_API bool intersect(const fwLine &_ray, double _radius, const fwVec3d &_point)
Compute the projection of a point in a given direction and test if this intersection is inside a give...