00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_SEGMENT_3D_RAY_3D_H
00044 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_LINE_SEGMENT_3D_RAY_3D_H
00045
00046 #include "prim_common.h"
00047 #include "line_segment_3d.h"
00048 #include "ray_3d.h"
00049
00050 namespace lass
00051 {
00052 namespace prim
00053 {
00054
00055
00056 template<typename T, class PP1, class NP2, class PP2>
00057 T distance(
00058 const LineSegment3D<T, PP1>& lineSegment, const Ray3D<T, NP2, PP2>& ray,
00059 const T& tMin = T())
00060 {
00061 return num::sqrt(squaredDistance(lineSegment, ray, tMin));
00062 }
00063
00064 template<typename T, class PP1, class NP2, class PP2>
00065 T squaredDistance(
00066 const LineSegment3D<T, PP1>& lineSegment, const Ray3D<T, NP2, PP2>& ray,
00067 const T& tMin = T())
00068 {
00069 typedef typename LineSegment3D<T, PP1>::TValue TValue;
00070 typedef Point3D<TValue> TPoint;
00071 typedef Vector3D<TValue> TVector;
00072
00073 const TPoint S1 = ray.support();
00074 const TVector D = ray.direction();
00075 const TPoint R = lineSegment.tail();
00076 const TVector E = lineSegment.vector();
00077
00078 TVector SR = R - S1;
00079 const TVector N = cross(D,E);
00080 if(N.squaredNorm() == 0)
00081 return squaredDistance(ray.project(R), R);
00082 const TPoint S = S1 + N.project(SR);
00083 SR = R - S;
00084
00085 TValue tRay, tSeg;
00086
00087
00088 if(num::abs(N.z) > num::abs(N.x) &&
00089 num::abs(N.z) > num::abs(N.y))
00090 {
00091 tRay = (SR.x * E.y - SR.y * E.x) / N.z;
00092 tSeg = (SR.x * D.y - SR.y * D.x) / N.z;
00093 }
00094 else if(num::abs(N.x) > num::abs(N.y))
00095 {
00096 tRay = (SR.y * E.z - SR.z * E.y) / N.x;
00097 tSeg = (SR.y * D.z - SR.z * D.y) / N.x;
00098 }else
00099 {
00100 tRay = (SR.z * E.x - SR.x * E.z) / N.y;
00101 tSeg = (SR.z * D.x - SR.x * D.z) / N.y;
00102 }
00103
00104 if(tSeg > 1)
00105 {
00106 TValue tHead = ray.t(lineSegment.head());
00107 if(tHead > tMin)
00108 return squaredDistance(ray.point(tHead), lineSegment.head());
00109 else
00110 {
00111 tSeg = lineSegment.t(S1);
00112 if(tSeg < 0)
00113 return squaredDistance(S1, lineSegment.tail());
00114 if(tSeg > 1)
00115 return squaredDistance(S1, lineSegment.head());
00116 return squaredDistance(S1, lineSegment.point(tSeg));
00117 }
00118 }
00119 if(tSeg < 0)
00120 {
00121 TValue tTail = ray.t(R);
00122 if(tTail > tMin)
00123 return squaredDistance(ray.point(tTail), R);
00124 else
00125 {
00126 tSeg = lineSegment.t(S1);
00127 if(tSeg < 0)
00128 return squaredDistance(S1, lineSegment.tail());
00129 if(tSeg > 1)
00130 return squaredDistance(S1, lineSegment.head());
00131 return squaredDistance(S1, lineSegment.point(tSeg));
00132 }
00133 }
00134
00135 if(tRay > tMin)
00136 return squaredDistance(ray.point(tRay), lineSegment.point(tSeg));
00137
00138 return lineSegment.squaredDistance(S1);
00139 }
00140
00141 template<typename T, class PP1, class NP2, class PP2>
00142 T closestsPoints(
00143 const LineSegment3D<T, PP1>& lineSegment, const Ray3D<T, NP2, PP2>& ray,
00144 T &tSeg, T &tRay, const T& tMin = T())
00145 {
00146 typedef typename LineSegment3D<T, PP1>::TValue TValue;
00147 typedef Point3D<TValue> TPoint;
00148 typedef Vector3D<TValue> TVector;
00149
00150 const TPoint S1 = ray.support();
00151 const TVector D = ray.direction();
00152 const TPoint R = lineSegment.tail();
00153 const TVector E = lineSegment.vector();
00154
00155 TVector SR = R - S1;
00156 const TVector N = cross(D,E);
00157 if(N.squaredNorm() == 0)
00158 return squaredDistance(ray.project(R), R);
00159 const TPoint S = S1 + N.project(SR);
00160 SR = R - S;
00161
00162
00163 if(num::abs(N.z) > num::abs(N.x) &&
00164 num::abs(N.z) > num::abs(N.y))
00165 {
00166 tRay = (SR.x * E.y - SR.y * E.x) / N.z;
00167 tSeg = (SR.x * D.y - SR.y * D.x) / N.z;
00168 }
00169 else if(num::abs(N.x) > num::abs(N.y))
00170 {
00171 tRay = (SR.y * E.z - SR.z * E.y) / N.x;
00172 tSeg = (SR.y * D.z - SR.z * D.y) / N.x;
00173 }else
00174 {
00175 tRay = (SR.z * E.x - SR.x * E.z) / N.y;
00176 tSeg = (SR.z * D.x - SR.x * D.z) / N.y;
00177 }
00178
00179 if(tSeg > 1)
00180 {
00181 TValue tHead = ray.t(lineSegment.head());
00182 if(tHead > tMin)
00183 {
00184 tRay = tHead;
00185 tSeg = 1.0;
00186 return squaredDistance(ray.point(tHead), lineSegment.head());
00187 }
00188 else
00189 {
00190 tSeg = lineSegment.t(S1);
00191 tRay = 0.0;
00192 if(tSeg < 0)
00193 {
00194 tSeg = 0.0;
00195 return squaredDistance(S1, lineSegment.tail());
00196 }
00197 if(tSeg > 1)
00198 {
00199 tSeg = 1.0;
00200 return squaredDistance(S1, lineSegment.head());
00201 }
00202 return squaredDistance(S1, lineSegment.point(tSeg));
00203 }
00204 }
00205 if(tSeg < 0)
00206 {
00207 TValue tTail = ray.t(R);
00208 if(tTail > tMin)
00209 {
00210 tRay = tTail;
00211 return squaredDistance(ray.point(tTail), R);
00212 }
00213 else
00214 {
00215 tSeg = lineSegment.t(S1);
00216 tRay = 0.0;
00217 if(tSeg < 0)
00218 {
00219 tSeg = 0.0;
00220 return squaredDistance(S1, lineSegment.tail());
00221 }
00222 if(tSeg > 1)
00223 {
00224 tSeg = 1.0;
00225 return squaredDistance(S1, lineSegment.head());
00226 }
00227 return squaredDistance(S1, lineSegment.point(tSeg));
00228 }
00229 }
00230
00231 if(tRay > tMin)
00232 return squaredDistance(ray.point(tRay), lineSegment.point(tSeg));
00233
00234 tRay = 0.0;
00235 return lineSegment.closestsPoint(S1, tSeg);
00236 }
00237
00238 }
00239 }
00240
00241 #endif
00242
00243