1 // -*- Mode: C++; tab-width: 2; -*-
2 // vi: set ts=2:
3 //
4 // $Id: line3.h,v 1.48 2004/07/05 20:57:28 oliver Exp $
5 //
6 
7 #ifndef BALL_MATHS_LINE3_H
8 #define BALL_MATHS_LINE3_H
9 
10 #ifndef BALL_COMMON_EXCEPTION_H
11 # include <BALL/COMMON/exception.h>
12 #endif
13 
14 #ifndef BALL_MATHS_VECTOR3_H
15 #	include <BALL/MATHS/vector3.h>
16 #endif
17 
18 namespace BALL
19 {
20 	/** \defgroup Line Generic Line in Three-Dimensional Space.
21 
22 		\ingroup GeometricObjects
23 	*/
24 
25 	//@{
26 
27 	template <typename T>
28 	class TLine3;
29 
30 	/** @name Storers
31 		Stream operators of Line3
32 	*/
33 	//@{
34 	template <typename T>
35 	std::ostream& operator << (std::ostream& s, const TLine3<T>& line)
36 		;
37 
38 	template <typename T>
39 	std::istream& operator >> (std::istream& s, TLine3<T>& line)
40 		;
41 	//@}
42 
43 	/**	Generic Line in Three-Dimensional Space.
44 	*/
45 	template <typename T>
46 	class TLine3
47 	{
48 		public:
49 
50 		BALL_CREATE(TLine3<T>)
51 
52 		/**	@name	Enums
53 		*/
54 		//@{
55 
56 		/** form of parameter to describe the line:
57 				<tt>0</tt> one Point and one Vector.
58 				<tt>1</tt> two Points
59 		*/
60 		enum Form
61 		{
62 			FORM__PARAMETER  = 0,
63 			FORM__TWO_POINTS = 1
64 		};
65 		//@}
66 
67 		/**	@name	Constructors and Destructors
68 		*/
69 		//@{
70 
71 		/**	Default constructor
72 		*/
TLine3()73 		TLine3()
74 
75 			:	p(),
76 				d()
77 		{
78 		}
79 
80 		/**	Copy constructor.
81 				@param TLine3 the TLine3 object to be copied
82 				@param bool ignored - just for interface consistency
83 		*/
TLine3(const TLine3 & line)84 		TLine3(const TLine3& line)
85 
86 			:	p(line.p),
87 				d(line.d)
88 		{
89 		}
90 
91 		// form: PARAMETER (default) or TWO_POINTS
92 
93 		/**	Detailed constructor.
94 				Depending on form, create a new TLine3 object from a point and a vector
95 				or from two points.
96 				@param	point assigned to <tt>p</tt>
97 				@param	vector assigned to <tt>d</tt>
98 				@param	form assigns form of parameter
99 								<tt>0</tt> one Point and one Vector \par
100 								<tt>1</tt> two Points
101 		*/
102 		TLine3(const TVector3<T>& point, const TVector3<T>& vector, Form form = FORM__PARAMETER)
103 
p(point)104 			:	p(point),
105 				d((form == FORM__PARAMETER)
106 					? vector
107 					: vector - point)
108 		{
109 		}
110 
111 		/**	Destructor.
112 				Destructs the TLine3 object. As there are no dynamic
113 				data structures, nothing happens.
114 		*/
~TLine3()115 		virtual ~TLine3()
116 
117 		{
118 		}
119 
120 		/**	Clear method.
121 				The values are set to 0.
122 		*/
clear()123 		virtual void clear()
124 
125 		{
126 			p.clear();
127 			d.clear();
128 		}
129 
130 		//@}
131 
132 		/**	@name	Assignment
133 		*/
134 		//@{
135 
136 		/**	Swap the contents of two instances of lines.
137 				@param	line the TLine3 to swap contents with
138 		*/
swap(TLine3 & line)139 		void swap(TLine3& line)
140 
141 		{
142 			TVector3<T> temp_point(p);
143 			p = line.p;
144 			line.p = temp_point;
145 
146 			TVector3<T> temp_vector(d);
147 			d = line.d;
148 			line.d = temp_vector;
149 		}
150 
151 		/**	Assign from another instance of TLine3.
152 				@param line	the TLine3 object to assign from
153 		*/
set(const TLine3 & line)154 		void set(const TLine3& line)
155 
156 		{
157 			p = line.p;
158 			d = line.d;
159 		}
160 
161 		/**	Assign from one point and a vector
162 				or from two points, depending on form.
163 				@param	point assigned to <tt>p</tt>
164 				@param	vector assigned to <tt>d</tt>
165 				@param	form assigns form of parameter
166 		*/
167 		void set(const TVector3<T>& point, const TVector3<T>& vector, Form form = FORM__PARAMETER)
168 
169 		{
170 			p = point;
171 			if (form == FORM__PARAMETER)
172 			{
173 				d = vector;
174 			}
175 			else
176 			{
177 				d = vector - point;
178 			}
179 		}
180 
181 		/**	Assignment operator.
182 				Assign the components from another instance of line.
183 				@param line the vector to assign from
184 		**/
185 		TLine3& operator = (const TLine3& line)
186 
187 		{
188 			p = line.p;
189 			d = line.d;
190 
191 			return *this;
192 		}
193 
194 		/**	Assign to another instance of TLine3.
195 				Assigns the vector components to another vector.
196 				@param line	the line to be assigned to
197 		*/
get(TLine3 & line)198 		void get(TLine3& line) const
199 		{
200 			line.p = p;
201 			line.d = d;
202 		}
203 
204 		/**	Assign to two instances of <tt>TVector3</tt>.
205 				Type of components depends on form.
206 				@param	point the first point
207 				@param	vector the second point or the vector component
208 				@param	form assigns form of parameter  \par
209 								<tt>0</tt> one Point and one Vector  \par
210 								<tt>1</tt> two Points
211 		*/
212 		void get(TVector3<T>& point,TVector3<T>& vector, Form form = FORM__PARAMETER) const
213 
214 		{
215 			point = p;
216 			if (form == FORM__PARAMETER)
217 			{
218 				vector = d;
219 			}
220 			else
221 			{
222 				vector - point = d;
223 			}
224 		}
225 
226 		//@}
227 
228 		/**	@name	Accessors
229 		*/
230 		//@{
231 
232 		/**	Normalize the vector component.
233 				The vector is scaled with its length:
234 				\f$\{x|y|z|\} *= \sqrt{x^2 + y^2 + z^2}\f$.
235 				@exception DivisionByZero if the length of the vector is 0
236 		*/
normalize()237 		void normalize()
238 
239 		{
240 			d.normalize();
241 		}
242 		//@}
243 
244 		/**	@name	Predicates
245 		*/
246 		//@{
247 
248 		/**	Equality operator.
249 				@return bool, <b>true</b> if both components are equal, <b>false</b> otherwise
250 		*/
251 		bool operator == (const TLine3& line) const
252 
253 		{
254 			return (p == line.p && d == line.d);
255 		}
256 
257 		/**	Inequality operator.
258 				@return bool, <b>true</b> if the two lines differ in at least one component, <b>false</b> otherwise
259 		*/
260 		bool operator != (const TLine3& line) const
261 
262 		{
263 			return (p != line.p || d != line.d);
264 		}
265 
266 		/**	Test whether a given point is a member of the line.
267 				@return bool, <b>true</b> or <b>false</b>
268 		*/
has(const TVector3<T> & point)269 		bool has(const TVector3<T>& point) const
270 
271 		{
272 			if (Maths::isNotZero(d.x))
273 			{
274 				T c = (point.x - p.x) / d.x;
275 
276 				return (Maths::isEqual(p.y + c * d.y, point.y) && Maths::isEqual(p.z + c * d.z, point.z));
277 			}
278 			else
279 			{
280 				if (Maths::isNotZero(d.y))
281 				{
282 					T c = (point.y - p.y) / d.y;
283 
284 					return (Maths::isEqual(p.x, point.x)   // invariant: d.x == 0
285 												&& Maths::isEqual(p.z + c * d.z, point.z));
286 				}
287 				else
288 				{
289 					if (Maths::isNotZero(d.z))
290 					{
291 						return (Maths::isEqual(p.x, point.x)   // invariant: d.x == 0
292 													&& Maths::isEqual(p.y, point.y)); // invariant: d.y == 0
293 					}
294 					else
295 					{
296 						return false;
297 					}
298 				}
299 			}
300 		}
301 
302 		//@}
303 		/**	@name	Debugging and Diagnostics
304 		*/
305 		//@{
306 
307 		/**	Test whether instance is valid.
308 				Always returns true.
309 				@return bool <b>true</b>
310 		*/
isValid()311 		bool isValid() const
312 
313 		{
314 			return true;
315 		}
316 
317 		/** Internal state dump.
318 				Dump the current internal state of {\em *this} to
319 				the output ostream <b>  s </b> with dumping depth <b>  depth </b>.
320 				@param   s - output stream where to output the internal state of {\em *this}
321 				@param   depth - the dumping depth
322 		*/
323 		void dump(std::ostream& s = std::cout, Size depth = 0) const
324 
325 		{
326 			BALL_DUMP_STREAM_PREFIX(s);
327 
328 			BALL_DUMP_HEADER(s, this, this);
329 
330 			BALL_DUMP_DEPTH(s, depth);
331 			s << "  position: " << p << std::endl;
332 
333 			BALL_DUMP_DEPTH(s, depth);
334 			s << "  direction: " << d << std::endl;
335 
336 			BALL_DUMP_STREAM_SUFFIX(s);
337 		}
338 		//@}
339 
340 
341 		/**	@name	Attributes
342 		*/
343 		//@{
344 
345 		/**	Point Component.
346 		*/
347 		TVector3<T> p;
348 
349 		/**	Vector Component.
350 		*/
351 		TVector3<T> d;
352 		//@}
353 	};
354 	//@}
355 
356 	/**	Default line of type <b>float</b>.
357 	 		\ingroup Line
358 	*/
359 	typedef TLine3<float> Line3;
360 
361 	/**	Input operator.
362 			Reads two objcts of type <b>TVector3</b> from an <tt>istream</tt> and
363 			assigns them to <tt>d</tt> and <tt>p</tt>.
364 	*/
365 	template <typename T>
366 	std::istream& operator >> (std::istream& s, TLine3<T>& line)
367 
368 	{
369 		char c;
370 		s >> c >> line.p >> line.d >> c;
371 		return s;
372 	}
373 
374 	/**	Output operator.
375 			Writes the two public attributes <tt>d</tt> and <tt>p</tt> to an output stream.
376 			The values of the two vectors are enclosed in brackets. \par
377 			<b>Example:</b> \par
378 			<tt>((0 0 0) (1 2 1))</tt>
379 			@see TVector3::operator<<
380 	*/
381 	template <typename T>
382 	std::ostream& operator << (std::ostream& s, const TLine3<T>& line)
383 
384 	{
385 		s << '(' << line.p << ' ' << line.d << ')';
386 		return s;
387 	}
388 } // namespace BALL
389 
390 #endif // BALL_MATHS_LINE3_H
391