1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __IRR_LINE_3D_H_INCLUDED__
6 #define __IRR_LINE_3D_H_INCLUDED__
7 
8 #include "irrTypes.h"
9 #include "vector3d.h"
10 
11 namespace irr
12 {
13 namespace core
14 {
15 
16 //! 3D line between two points with intersection methods.
17 template <class T>
18 class line3d
19 {
20 	public:
21 
22 		//! Default constructor
23 		/** line from (0,0,0) to (1,1,1) */
line3d()24 		line3d() : start(0,0,0), end(1,1,1) {}
25 		//! Constructor with two points
line3d(T xa,T ya,T za,T xb,T yb,T zb)26 		line3d(T xa, T ya, T za, T xb, T yb, T zb) : start(xa, ya, za), end(xb, yb, zb) {}
27 		//! Constructor with two points as vectors
line3d(const vector3d<T> & start,const vector3d<T> & end)28 		line3d(const vector3d<T>& start, const vector3d<T>& end) : start(start), end(end) {}
29 
30 		// operators
31 
32 		line3d<T> operator+(const vector3d<T>& point) const { return line3d<T>(start + point, end + point); }
33 		line3d<T>& operator+=(const vector3d<T>& point) { start += point; end += point; return *this; }
34 
35 		line3d<T> operator-(const vector3d<T>& point) const { return line3d<T>(start - point, end - point); }
36 		line3d<T>& operator-=(const vector3d<T>& point) { start -= point; end -= point; return *this; }
37 
38 		bool operator==(const line3d<T>& other) const
39 		{ return (start==other.start && end==other.end) || (end==other.start && start==other.end);}
40 		bool operator!=(const line3d<T>& other) const
41 		{ return !(start==other.start && end==other.end) || (end==other.start && start==other.end);}
42 
43 		// functions
44 		//! Set this line to a new line going through the two points.
setLine(const T & xa,const T & ya,const T & za,const T & xb,const T & yb,const T & zb)45 		void setLine(const T& xa, const T& ya, const T& za, const T& xb, const T& yb, const T& zb)
46 		{start.set(xa, ya, za); end.set(xb, yb, zb);}
47 		//! Set this line to a new line going through the two points.
setLine(const vector3d<T> & nstart,const vector3d<T> & nend)48 		void setLine(const vector3d<T>& nstart, const vector3d<T>& nend)
49 		{start.set(nstart); end.set(nend);}
50 		//! Set this line to new line given as parameter.
setLine(const line3d<T> & line)51 		void setLine(const line3d<T>& line)
52 		{start.set(line.start); end.set(line.end);}
53 
54 		//! Get length of line
55 		/** \return Length of line. */
getLength()56 		T getLength() const { return start.getDistanceFrom(end); }
57 
58 		//! Get squared length of line
59 		/** \return Squared length of line. */
getLengthSQ()60 		T getLengthSQ() const { return start.getDistanceFromSQ(end); }
61 
62 		//! Get middle of line
63 		/** \return Center of line. */
getMiddle()64 		vector3d<T> getMiddle() const
65 		{
66 			return (start + end)/(T)2;
67 		}
68 
69 		//! Get vector of line
70 		/** \return vector of line. */
getVector()71 		vector3d<T> getVector() const
72 		{
73 			return end - start;
74 		}
75 
76 		//! Check if the given point is between start and end of the line.
77 		/** Assumes that the point is already somewhere on the line.
78 		\param point The point to test.
79 		\return True if point is on the line between start and end, else false.
80 		*/
isPointBetweenStartAndEnd(const vector3d<T> & point)81 		bool isPointBetweenStartAndEnd(const vector3d<T>& point) const
82 		{
83 			return point.isBetweenPoints(start, end);
84 		}
85 
86 		//! Get the closest point on this line to a point
87 		/** \param point The point to compare to.
88 		\return The nearest point which is part of the line. */
getClosestPoint(const vector3d<T> & point)89 		vector3d<T> getClosestPoint(const vector3d<T>& point) const
90 		{
91 			vector3d<T> c = point - start;
92 			vector3d<T> v = end - start;
93 			T d = (T)v.getLength();
94 			v /= d;
95 			T t = v.dotProduct(c);
96 
97 			if (t < (T)0.0)
98 				return start;
99 			if (t > d)
100 				return end;
101 
102 			v *= t;
103 			return start + v;
104 		}
105 
106 		//! Check if the line intersects with a shpere
107 		/** \param sorigin: Origin of the shpere.
108 		\param sradius: Radius of the sphere.
109 		\param outdistance: The distance to the first intersection point.
110 		\return True if there is an intersection.
111 		If there is one, the distance to the first intersection point
112 		is stored in outdistance. */
getIntersectionWithSphere(vector3d<T> sorigin,T sradius,f64 & outdistance)113 		bool getIntersectionWithSphere(vector3d<T> sorigin, T sradius, f64& outdistance) const
114 		{
115 			const vector3d<T> q = sorigin - start;
116 			T c = q.getLength();
117 			T v = q.dotProduct(getVector().normalize());
118 			T d = sradius * sradius - (c*c - v*v);
119 
120 			if (d < 0.0)
121 				return false;
122 
123 			outdistance = v - core::squareroot ( d );
124 			return true;
125 		}
126 
127 		// member variables
128 
129 		//! Start point of line
130 		vector3d<T> start;
131 		//! End point of line
132 		vector3d<T> end;
133 };
134 
135 	//! Typedef for an f32 line.
136 	typedef line3d<f32> line3df;
137 	//! Typedef for an integer line.
138 	typedef line3d<s32> line3di;
139 
140 } // end namespace core
141 } // end namespace irr
142 
143 #endif
144 
145