00001
00023 #include "llline.h"
00024 #include "llrand.h"
00025
00026 const F32 SOME_SMALL_NUMBER = 1.0e-5f;
00027 const F32 SOME_VERY_SMALL_NUMBER = 1.0e-8f;
00028
00029 LLLine::LLLine()
00030 : mPoint(0.f, 0.f, 0.f),
00031 mDirection(1.f, 0.f, 0.f)
00032 { }
00033
00034 LLLine::LLLine( const LLVector3& first_point, const LLVector3& second_point )
00035 {
00036 setPoints(first_point, second_point);
00037 }
00038
00039 void LLLine::setPoints( const LLVector3& first_point, const LLVector3& second_point )
00040 {
00041 mPoint = first_point;
00042 mDirection = second_point - first_point;
00043 mDirection.normalize();
00044 }
00045
00046 void LLLine::setPointDirection( const LLVector3& first_point, const LLVector3& second_point )
00047 {
00048 setPoints(first_point, first_point + second_point);
00049 }
00050
00051 bool LLLine::intersects( const LLVector3& point, F32 radius ) const
00052 {
00053 LLVector3 other_direction = point - mPoint;
00054 LLVector3 nearest_point = mPoint + mDirection * (other_direction * mDirection);
00055 F32 nearest_approach = (nearest_point - point).length();
00056 return (nearest_approach <= radius);
00057 }
00058
00059
00060 LLVector3 LLLine::nearestApproach( const LLVector3& some_point ) const
00061 {
00062 return (mPoint + mDirection * ((some_point - mPoint) * mDirection));
00063 }
00064
00065
00066
00067
00068
00069
00070 LLVector3 LLLine::nearestApproach( const LLLine& other_line ) const
00071 {
00072 LLVector3 between_points = other_line.mPoint - mPoint;
00073 F32 dir_dot_dir = mDirection * other_line.mDirection;
00074 F32 one_minus_dir_dot_dir = 1.0f - fabs(dir_dot_dir);
00075 if ( one_minus_dir_dot_dir < SOME_VERY_SMALL_NUMBER )
00076 {
00077 #ifdef LL_DEBUG
00078 llwarns << "LLLine::nearestApproach() was given two very "
00079 << "nearly parallel lines dir1 = " << mDirection
00080 << " dir2 = " << other_line.mDirection << " with 1-dot_product = "
00081 << one_minus_dir_dot_dir << llendl;
00082 #endif
00083
00084
00085
00086
00087
00088 return 0.5f * (mPoint + other_line.mPoint);
00089 }
00090
00091 F32 odir_dot_bp = other_line.mDirection * between_points;
00092
00093 F32 numerator = 0;
00094 F32 denominator = 0;
00095 for (S32 i=0; i<3; i++)
00096 {
00097 F32 factor = dir_dot_dir * other_line.mDirection.mV[i] - mDirection.mV[i];
00098 numerator += ( between_points.mV[i] - odir_dot_bp * other_line.mDirection.mV[i] ) * factor;
00099 denominator -= factor * factor;
00100 }
00101
00102 F32 length_to_nearest_approach = numerator / denominator;
00103
00104 return mPoint + length_to_nearest_approach * mDirection;
00105 }
00106
00107 std::ostream& operator<<( std::ostream& output_stream, const LLLine& line )
00108 {
00109 output_stream << "{point=" << line.mPoint << "," << "dir=" << line.mDirection << "}";
00110 return output_stream;
00111 }
00112
00113
00114 F32 ALMOST_PARALLEL = 0.99f;
00115 F32 TOO_SMALL_FOR_DIVISION = 0.0001f;
00116
00117
00118
00119 bool LLLine::intersectsPlane( LLVector3& result, const LLLine& plane ) const
00120 {
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 F32 dot = plane.mDirection * mDirection;
00132 if (fabs(dot) < TOO_SMALL_FOR_DIVISION)
00133 {
00134 return false;
00135 }
00136
00137 F32 plane_dot = plane.mDirection * plane.mPoint;
00138 F32 length = ( plane_dot - (plane.mDirection * mPoint) ) / dot;
00139 result = mPoint + length * mDirection;
00140 return true;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 bool LLLine::getIntersectionBetweenTwoPlanes( LLLine& result, const LLLine& first_plane, const LLLine& second_plane )
00150 {
00151
00152
00153
00154
00155 F32 dot = fabs(first_plane.mDirection * second_plane.mDirection);
00156 if (dot > ALMOST_PARALLEL)
00157 {
00158
00159 return false;
00160 }
00161
00162 LLVector3 direction = first_plane.mDirection % second_plane.mDirection;
00163 direction.normalize();
00164
00165 LLVector3 first_intersection;
00166 {
00167 LLLine intersection_line(first_plane);
00168 intersection_line.mDirection = direction % first_plane.mDirection;
00169 intersection_line.mDirection.normalize();
00170 intersection_line.intersectsPlane(first_intersection, second_plane);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 result.mPoint = first_intersection;
00184 result.mDirection = direction;
00185
00186 return true;
00187 }
00188
00189