1 /*******************************************************************************
2  * types.h
3  *
4  * ---------------------------------------------------------------------------
5  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
6  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
7  *
8  * POV-Ray is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Affero General Public License as
10  * published by the Free Software Foundation, either version 3 of the
11  * License, or (at your option) any later version.
12  *
13  * POV-Ray is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Affero General Public License for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * ---------------------------------------------------------------------------
21  * POV-Ray is based on the popular DKB raytracer version 2.12.
22  * DKBTrace was originally written by David K. Buck.
23  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
24  * ---------------------------------------------------------------------------
25  * $File: //depot/public/povray/3.x/source/base/types.h $
26  * $Revision: #1 $
27  * $Change: 6069 $
28  * $DateTime: 2013/11/06 11:59:40 $
29  * $Author: chrisc $
30  *******************************************************************************/
31 
32 #ifndef POVRAY_BASE_TYPES_H
33 #define POVRAY_BASE_TYPES_H
34 
35 #include <algorithm>
36 #include <vector>
37 
38 #include "base/configbase.h"
39 
40 namespace pov_base
41 {
42 
43 // Get minimum/maximum of three values.
44 template<typename T>
max3(T x,T y,T z)45 inline T max3(T x, T y, T z) { return max(x, max(y, z)); }
46 template<typename T>
min3(T x,T y,T z)47 inline T min3(T x, T y, T z) { return min(x, min(y, z)); }
48 
49 template<typename T>
50 inline T clip(T val, T minv, T maxv);
51 
52 template<typename T>
clip(T val,T minv,T maxv)53 inline T clip(T val, T minv, T maxv)
54 {
55 	if(val < minv)
56 		return minv;
57 	else if(val > maxv)
58 		return maxv;
59 	else
60 		return val;
61 }
62 
63 // force a value's precision to a given type, even if computations are normally done with extended precision
64 // (such as GNU Linux on 32-bit CPU, which uses 80-bit extended double precision)
65 // TODO - we might make this code platform-specific
66 template<typename T>
forcePrecision(T val)67 inline T forcePrecision(T val)
68 {
69 	volatile T tempVal;
70 	tempVal = val;
71 	return tempVal;
72 }
73 
74 // wrap value into the range [0..upperLimit);
75 // (this is equivalent to fmod() for positive values, but not for negative ones)
76 template<typename T>
wrap(T val,T upperLimit)77 inline T wrap(T val, T upperLimit)
78 {
79 	T tempVal = fmod(val, upperLimit);
80 	// NB: The range of the value computed by fmod() should be in the range [0..upperLimit) already,
81 	// but on some architectures may actually be in the range [0..upperLimit].
82 
83 	if (tempVal < T(0.0))
84 	{
85 		// For negative values, fmod() returns a value in the range [-upperLimit..0];
86 		// transpose it into the range [0..upperLimit].
87 		tempVal += upperLimit;
88 	}
89 
90 	// for negative values (and also for positive values on systems that internally use higher precision
91 	// than double for computations) we may end up with value equal to upperLimit (in double precision);
92 	// make sure to wrap these special cases to the range [0..upperLimit) as well.
93 	if (forcePrecision<double>(tempVal) >= upperLimit)
94 		tempVal = T(0.0);
95 
96 	return tempVal;
97 }
98 
99 // round up/down to a multiple of some value
100 template<typename T1, typename T2>
RoundDownToMultiple(T1 x,T2 base)101 inline T1 RoundDownToMultiple(T1 x, T2 base) { return x - (x % base); }
102 template<typename T1, typename T2>
RoundUpToMultiple(T1 x,T2 base)103 inline T1 RoundUpToMultiple(T1 x, T2 base) { return RoundDownToMultiple (x + base - 1, base); }
104 
105 
106 template<typename T>
107 class GenericRGBColour;
108 
109 #define RED_INTENSITY   0.297
110 #define GREEN_INTENSITY 0.589
111 #define BLUE_INTENSITY  0.114
112 
113 template<typename T>
114 class GenericColour
115 {
116 	public:
117 		typedef DBL EXPRESS[5];
118 		typedef COLC COLOUR[5];
119 		typedef T DATA[5];
120 
121 		enum
122 		{
123 			RED    = 0,
124 			GREEN  = 1,
125 			BLUE   = 2,
126 			FILTER = 3,
127 			TRANSM = 4
128 		};
129 
GenericColour()130 		GenericColour()
131 		{
132 			colour[RED] = 0.0;
133 			colour[GREEN] = 0.0;
134 			colour[BLUE] = 0.0;
135 			colour[FILTER] = 0.0;
136 			colour[TRANSM] = 0.0;
137 		}
138 
GenericColour(T grey)139 		explicit GenericColour(T grey)
140 		{
141 			colour[RED] = grey;
142 			colour[GREEN] = grey;
143 			colour[BLUE] = grey;
144 			colour[FILTER] = 0.0;
145 			colour[TRANSM] = 0.0;
146 		}
147 
148 		explicit inline GenericColour(const GenericRGBColour<T>& col);
149 
150 		explicit inline GenericColour(const GenericRGBColour<T>& col, T nfilter, T ntransm);
151 
GenericColour(T nred,T ngreen,T nblue)152 		GenericColour(T nred, T ngreen, T nblue)
153 		{
154 			colour[RED] = nred;
155 			colour[GREEN] = ngreen;
156 			colour[BLUE] = nblue;
157 			colour[FILTER] = 0.0;
158 			colour[TRANSM] = 0.0;
159 		}
160 
GenericColour(T nred,T ngreen,T nblue,T nfilter,T ntransm)161 		GenericColour(T nred, T ngreen, T nblue, T nfilter, T ntransm)
162 		{
163 			colour[RED] = nred;
164 			colour[GREEN] = ngreen;
165 			colour[BLUE] = nblue;
166 			colour[FILTER] = nfilter;
167 			colour[TRANSM] = ntransm;
168 		}
169 
GenericColour(const COLOUR col)170 		explicit GenericColour(const COLOUR col)
171 		{
172 			colour[RED] = col[RED];
173 			colour[GREEN] = col[GREEN];
174 			colour[BLUE] = col[BLUE];
175 			colour[FILTER] = col[FILTER];
176 			colour[TRANSM] = col[TRANSM];
177 		}
178 
GenericColour(const EXPRESS col)179 		explicit GenericColour(const EXPRESS col)
180 		{
181 			colour[RED] = col[RED];
182 			colour[GREEN] = col[GREEN];
183 			colour[BLUE] = col[BLUE];
184 			colour[FILTER] = col[FILTER];
185 			colour[TRANSM] = col[TRANSM];
186 		}
187 
GenericColour(const GenericColour & col)188 		GenericColour(const GenericColour& col)
189 		{
190 			colour[RED] = col[RED];
191 			colour[GREEN] = col[GREEN];
192 			colour[BLUE] = col[BLUE];
193 			colour[FILTER] = col[FILTER];
194 			colour[TRANSM] = col[TRANSM];
195 		}
196 
197 		template<typename T2>
GenericColour(const GenericColour<T2> & col)198 		explicit GenericColour(const GenericColour<T2>& col)
199 		{
200 			colour[RED] = col[RED];
201 			colour[GREEN] = col[GREEN];
202 			colour[BLUE] = col[BLUE];
203 			colour[FILTER] = col[FILTER];
204 			colour[TRANSM] = col[TRANSM];
205 		}
206 
207 		GenericColour(vector<POVMSFloat>::const_iterator& it, bool filter = true, bool transmit = true)
208 		{
209 			colour[RED] = *it++;
210 			colour[GREEN] = *it++;
211 			colour[BLUE] = *it++;
212 			if (filter)
213 				colour[FILTER] = *it++;
214 			if (transmit)
215 				colour[TRANSM] = *it++;
216 		}
217 
218 		GenericColour& operator=(const GenericColour& col)
219 		{
220 			colour[RED] = col[RED];
221 			colour[GREEN] = col[GREEN];
222 			colour[BLUE] = col[BLUE];
223 			colour[FILTER] = col[FILTER];
224 			colour[TRANSM] = col[TRANSM];
225 			return *this;
226 		}
227 
228 		GenericColour& operator=(const T& col)
229 		{
230 			colour[RED] = col;
231 			colour[GREEN] = col;
232 			colour[BLUE] = col;
233 			colour[FILTER] = 0.0f;
234 			colour[TRANSM] = 0.0f;
235 			return *this;
236 		}
237 
238 		T operator[](int idx) const { return colour[idx]; }
239 		T& operator[](int idx) { return colour[idx]; }
240 
241 		const DATA& operator*() const { return colour; }
242 		DATA& operator*() { return colour; }
243 
red()244 		T red() const { return colour[RED]; }
red()245 		T& red() { return colour[RED]; }
246 
green()247 		T green() const { return colour[GREEN]; }
green()248 		T& green() { return colour[GREEN]; }
249 
blue()250 		T blue() const { return colour[BLUE]; }
blue()251 		T& blue() { return colour[BLUE]; }
252 
filter()253 		T filter() const { return colour[FILTER]; }
filter()254 		T& filter() { return colour[FILTER]; }
255 
transm()256 		T transm() const { return colour[TRANSM]; }
transm()257 		T& transm() { return colour[TRANSM]; }
258 
opacity()259 		T opacity() const { return 1.0 - colour[FILTER] - colour[TRANSM]; }
260 
greyscale()261 		T greyscale() const { return RED_INTENSITY * colour[RED] + GREEN_INTENSITY * colour[GREEN] + BLUE_INTENSITY * colour[BLUE]; }
262 
263 		// TODO: find a more correct way of handling alpha <-> filter/transmit
AtoFT(T alpha,T & f,T & t)264 		static void AtoFT(T alpha, T& f, T& t) { f = 0.0f; t = 1.0f - alpha; }
AtoFT(T alpha)265 		void AtoFT(T alpha) { colour[FILTER] = 0.0f; colour[TRANSM] = 1.0f - alpha; }
FTtoA(T,T t)266 		static T FTtoA(T /*f*/, T t) { return 1.0f - t; }
FTtoA()267 		T FTtoA() const { return 1.0f - colour[TRANSM]; }
268 
clear()269 		void clear()
270 		{
271 			colour[RED] = 0.0;
272 			colour[GREEN] = 0.0;
273 			colour[BLUE] = 0.0;
274 			colour[FILTER] = 0.0;
275 			colour[TRANSM] = 0.0;
276 		}
277 
set(T grey)278 		void set(T grey)
279 		{
280 			colour[RED] = grey;
281 			colour[GREEN] = grey;
282 			colour[BLUE] = grey;
283 			colour[FILTER] = 0.0;
284 			colour[TRANSM] = 0.0;
285 		}
286 
set(T nred,T ngreen,T nblue)287 		void set(T nred, T ngreen, T nblue)
288 		{
289 			colour[RED] = nred;
290 			colour[GREEN] = ngreen;
291 			colour[BLUE] = nblue;
292 			colour[FILTER] = 0.0;
293 			colour[TRANSM] = 0.0;
294 		}
295 
set(T nred,T ngreen,T nblue,T nfilter,T ntransm)296 		void set(T nred, T ngreen, T nblue, T nfilter, T ntransm)
297 		{
298 			colour[RED] = nred;
299 			colour[GREEN] = ngreen;
300 			colour[BLUE] = nblue;
301 			colour[FILTER] = nfilter;
302 			colour[TRANSM] = ntransm;
303 		}
304 
clip(T minc,T maxc)305 		GenericColour clip(T minc, T maxc)
306 		{
307 			return GenericColour(pov_base::clip<T>(colour[RED], minc, maxc),
308 			                     pov_base::clip<T>(colour[GREEN], minc, maxc),
309 			                     pov_base::clip<T>(colour[BLUE], minc, maxc),
310 			                     pov_base::clip<T>(colour[FILTER], minc, maxc),
311 			                     pov_base::clip<T>(colour[TRANSM], minc, maxc));
312 		}
313 
314 		inline GenericRGBColour<T> rgbTransm() const;
315 
316 		GenericColour operator+(const GenericColour& b) const
317 		{
318 			return GenericColour(colour[RED] + b[RED], colour[GREEN] + b[GREEN], colour[BLUE] + b[BLUE], colour[FILTER] + b[FILTER], colour[TRANSM] + b[TRANSM]);
319 		}
320 
321 		GenericColour operator-(const GenericColour& b) const
322 		{
323 			return GenericColour(colour[RED] - b[RED], colour[GREEN] - b[GREEN], colour[BLUE] - b[BLUE], colour[FILTER] - b[FILTER], colour[TRANSM] - b[TRANSM]);
324 		}
325 
326 		GenericColour operator*(const GenericColour& b) const
327 		{
328 			return GenericColour(colour[RED] * b[RED], colour[GREEN] * b[GREEN], colour[BLUE] * b[BLUE], colour[FILTER] * b[FILTER], colour[TRANSM] * b[TRANSM]);
329 		}
330 
331 		GenericColour operator/(const GenericColour& b) const
332 		{
333 			return GenericColour(colour[RED] / b[RED], colour[GREEN] / b[GREEN], colour[BLUE] / b[BLUE], colour[FILTER] / b[FILTER], colour[TRANSM] / b[TRANSM]);
334 		}
335 
336 		GenericColour& operator+=(const GenericColour& b)
337 		{
338 			colour[RED] += b[RED];
339 			colour[GREEN] += b[GREEN];
340 			colour[BLUE] += b[BLUE];
341 			colour[FILTER] += b[FILTER];
342 			colour[TRANSM] += b[TRANSM];
343 			return *this;
344 		}
345 
346 		GenericColour& operator-=(const GenericColour& b)
347 		{
348 			colour[RED] -= b[RED];
349 			colour[GREEN] -= b[GREEN];
350 			colour[BLUE] -= b[BLUE];
351 			colour[FILTER] -= b[FILTER];
352 			colour[TRANSM] -= b[TRANSM];
353 			return *this;
354 		}
355 
356 		GenericColour& operator*=(const GenericColour& b)
357 		{
358 			colour[RED] *= b[RED];
359 			colour[GREEN] *= b[GREEN];
360 			colour[BLUE] *= b[BLUE];
361 			colour[FILTER] *= b[FILTER];
362 			colour[TRANSM] *= b[TRANSM];
363 			return *this;
364 		}
365 
366 		GenericColour& operator/=(const GenericColour& b)
367 		{
368 			colour[RED] /= b[RED];
369 			colour[GREEN] /= b[GREEN];
370 			colour[BLUE] /= b[BLUE];
371 			colour[FILTER] /= b[FILTER];
372 			colour[TRANSM] /= b[TRANSM];
373 			return *this;
374 		}
375 
376 		GenericColour operator-() const
377 		{
378 			return GenericColour(-colour[RED], -colour[GREEN], -colour[BLUE], -colour[FILTER], -colour[TRANSM]);
379 		}
380 
381 		GenericColour operator+(DBL b) const
382 		{
383 			return GenericColour(colour[RED] + b, colour[GREEN] + b, colour[BLUE] + b, colour[FILTER] + b, colour[TRANSM] + b);
384 		}
385 
386 		GenericColour operator-(DBL b) const
387 		{
388 			return GenericColour(colour[RED] - b, colour[GREEN] - b, colour[BLUE] - b, colour[FILTER] - b, colour[TRANSM] - b);
389 		}
390 
391 		GenericColour operator*(DBL b) const
392 		{
393 			return GenericColour(colour[RED] * b, colour[GREEN] * b, colour[BLUE] * b, colour[FILTER] * b, colour[TRANSM] * b);
394 		}
395 
396 		GenericColour operator/(DBL b) const
397 		{
398 			return GenericColour(colour[RED] / b, colour[GREEN] / b, colour[BLUE] / b, colour[FILTER] / b, colour[TRANSM] / b);
399 		}
400 
401 		GenericColour& operator+=(DBL b)
402 		{
403 			colour[RED] += b;
404 			colour[GREEN] += b;
405 			colour[BLUE] += b;
406 			colour[FILTER] += b;
407 			colour[TRANSM] += b;
408 			return *this;
409 		}
410 
411 		GenericColour& operator-=(DBL b)
412 		{
413 			colour[RED] -= b;
414 			colour[GREEN] -= b;
415 			colour[BLUE] -= b;
416 			colour[FILTER] -= b;
417 			colour[TRANSM] -= b;
418 			return *this;
419 		}
420 
421 		GenericColour& operator*=(DBL b)
422 		{
423 			colour[RED] *= b;
424 			colour[GREEN] *= b;
425 			colour[BLUE] *= b;
426 			colour[FILTER] *= b;
427 			colour[TRANSM] *= b;
428 			return *this;
429 		}
430 
431 		GenericColour& operator/=(DBL b)
432 		{
433 			colour[RED] /= b;
434 			colour[GREEN] /= b;
435 			colour[BLUE] /= b;
436 			colour[FILTER] /= b;
437 			colour[TRANSM] /= b;
438 			return *this;
439 		}
440 	private:
441 		DATA colour;
442 };
443 
444 template<typename T>
445 class GenericRGBColour
446 {
447 	public:
448 		typedef DBL VECTOR[3];
449 		typedef COLC RGB[3];
450 		typedef T DATA[3];
451 
452 		enum
453 		{
454 			RED    = 0,
455 			GREEN  = 1,
456 			BLUE   = 2
457 		};
458 
GenericRGBColour()459 		GenericRGBColour()
460 		{
461 			colour[RED] = 0.0;
462 			colour[GREEN] = 0.0;
463 			colour[BLUE] = 0.0;
464 		}
465 
GenericRGBColour(T grey)466 		explicit GenericRGBColour(T grey)
467 		{
468 			colour[RED] = grey;
469 			colour[GREEN] = grey;
470 			colour[BLUE] = grey;
471 		}
472 
GenericRGBColour(T nred,T ngreen,T nblue)473 		GenericRGBColour(T nred, T ngreen, T nblue)
474 		{
475 			colour[RED] = nred;
476 			colour[GREEN] = ngreen;
477 			colour[BLUE] = nblue;
478 		}
479 
GenericRGBColour(const RGB col)480 		explicit GenericRGBColour(const RGB col)
481 		{
482 			colour[RED] = col[RED];
483 			colour[GREEN] = col[GREEN];
484 			colour[BLUE] = col[BLUE];
485 		}
486 
GenericRGBColour(const VECTOR col)487 		explicit GenericRGBColour(const VECTOR col)
488 		{
489 			colour[RED] = col[RED];
490 			colour[GREEN] = col[GREEN];
491 			colour[BLUE] = col[BLUE];
492 		}
493 
GenericRGBColour(const GenericColour<T> & col)494 		explicit GenericRGBColour(const GenericColour<T>& col)
495 		{
496 			colour[RED] = col[RED];
497 			colour[GREEN] = col[GREEN];
498 			colour[BLUE] = col[BLUE];
499 		}
500 
GenericRGBColour(const GenericRGBColour & col)501 		GenericRGBColour(const GenericRGBColour& col)
502 		{
503 			colour[RED] = col[RED];
504 			colour[GREEN] = col[GREEN];
505 			colour[BLUE] = col[BLUE];
506 		}
507 
508 		template<typename T2>
GenericRGBColour(const GenericRGBColour<T2> & col)509 		explicit GenericRGBColour(const GenericRGBColour<T2>& col)
510 		{
511 			colour[RED] = col[RED];
512 			colour[GREEN] = col[GREEN];
513 			colour[BLUE] = col[BLUE];
514 		}
515 
GenericRGBColour(vector<POVMSFloat>::const_iterator & it)516 		GenericRGBColour(vector<POVMSFloat>::const_iterator& it)
517 		{
518 			colour[RED] = *it++;
519 			colour[GREEN] = *it++;
520 			colour[BLUE] = *it++;
521 		}
522 
523 		GenericRGBColour& operator=(const GenericRGBColour& col)
524 		{
525 			colour[RED] = col[RED];
526 			colour[GREEN] = col[GREEN];
527 			colour[BLUE] = col[BLUE];
528 			return *this;
529 		}
530 
531 		GenericRGBColour& operator=(const T& col)
532 		{
533 			colour[RED] = col;
534 			colour[GREEN] = col;
535 			colour[BLUE] = col;
536 			return *this;
537 		}
538 
539 		T operator[](int idx) const { return colour[idx]; }
540 		T& operator[](int idx) { return colour[idx]; }
541 
542 		const DATA& operator*() const { return colour; }
543 		DATA& operator*() { return colour; }
544 
red()545 		T red() const { return colour[RED]; }
red()546 		T& red() { return colour[RED]; }
547 
green()548 		T green() const { return colour[GREEN]; }
green()549 		T& green() { return colour[GREEN]; }
550 
blue()551 		T blue() const { return colour[BLUE]; }
blue()552 		T& blue() { return colour[BLUE]; }
553 
greyscale()554 		T greyscale() const { return RED_INTENSITY * colour[RED] + GREEN_INTENSITY * colour[GREEN] + BLUE_INTENSITY * colour[BLUE]; }
555 
isZero()556 		bool isZero() const { return (colour[RED] == 0) && (colour[GREEN] == 0) && (colour[BLUE] == 0); }
557 
clear()558 		void clear()
559 		{
560 			colour[RED] = 0.0;
561 			colour[GREEN] = 0.0;
562 			colour[BLUE] = 0.0;
563 		}
564 
set(T grey)565 		void set(T grey)
566 		{
567 			colour[RED] = grey;
568 			colour[GREEN] = grey;
569 			colour[BLUE] = grey;
570 		}
571 
set(T nred,T ngreen,T nblue)572 		void set(T nred, T ngreen, T nblue)
573 		{
574 			colour[RED] = nred;
575 			colour[GREEN] = ngreen;
576 			colour[BLUE] = nblue;
577 		}
578 
clip(T minc,T maxc)579 		GenericRGBColour clip(T minc, T maxc)
580 		{
581 			return GenericRGBColour(pov_base::clip<T>(colour[RED], minc, maxc),
582 			                        pov_base::clip<T>(colour[GREEN], minc, maxc),
583 			                        pov_base::clip<T>(colour[BLUE], minc, maxc));
584 		}
585 
586 		GenericRGBColour operator+(const GenericRGBColour& b) const
587 		{
588 			return GenericRGBColour(colour[RED] + b[RED], colour[GREEN] + b[GREEN], colour[BLUE] + b[BLUE]);
589 		}
590 
591 		GenericRGBColour operator-(const GenericRGBColour& b) const
592 		{
593 			return GenericRGBColour(colour[RED] - b[RED], colour[GREEN] - b[GREEN], colour[BLUE] - b[BLUE]);
594 		}
595 
596 		GenericRGBColour operator*(const GenericRGBColour& b) const
597 		{
598 			return GenericRGBColour(colour[RED] * b[RED], colour[GREEN] * b[GREEN], colour[BLUE] * b[BLUE]);
599 		}
600 
601 		GenericRGBColour operator/(const GenericRGBColour& b) const
602 		{
603 			return GenericRGBColour(colour[RED] / b[RED], colour[GREEN] / b[GREEN], colour[BLUE] / b[BLUE]);
604 		}
605 
606 		GenericRGBColour& operator+=(const GenericRGBColour& b)
607 		{
608 			colour[RED] += b[RED];
609 			colour[GREEN] += b[GREEN];
610 			colour[BLUE] += b[BLUE];
611 			return *this;
612 		}
613 
614 		GenericRGBColour& operator-=(const GenericRGBColour& b)
615 		{
616 			colour[RED] -= b[RED];
617 			colour[GREEN] -= b[GREEN];
618 			colour[BLUE] -= b[BLUE];
619 			return *this;
620 		}
621 
622 		GenericRGBColour& operator*=(const GenericRGBColour& b)
623 		{
624 			colour[RED] *= b[RED];
625 			colour[GREEN] *= b[GREEN];
626 			colour[BLUE] *= b[BLUE];
627 			return *this;
628 		}
629 
630 		GenericRGBColour& operator/=(const GenericRGBColour& b)
631 		{
632 			colour[RED] /= b[RED];
633 			colour[GREEN] /= b[GREEN];
634 			colour[BLUE] /= b[BLUE];
635 			return *this;
636 		}
637 
638 		GenericRGBColour operator-() const
639 		{
640 			return GenericRGBColour(-colour[RED], -colour[GREEN], -colour[BLUE]);
641 		}
642 
643 		GenericRGBColour operator+(DBL b) const
644 		{
645 			return GenericRGBColour(colour[RED] + b, colour[GREEN] + b, colour[BLUE] + b);
646 		}
647 
648 		GenericRGBColour operator-(DBL b) const
649 		{
650 			return GenericRGBColour(colour[RED] - b, colour[GREEN] - b, colour[BLUE] - b);
651 		}
652 
653 		GenericRGBColour operator*(DBL b) const
654 		{
655 			return GenericRGBColour(colour[RED] * b, colour[GREEN] * b, colour[BLUE] * b);
656 		}
657 
658 		GenericRGBColour operator/(DBL b) const
659 		{
660 			return GenericRGBColour(colour[RED] / b, colour[GREEN] / b, colour[BLUE] / b);
661 		}
662 
663 		GenericRGBColour& operator+=(DBL b)
664 		{
665 			colour[RED] += b;
666 			colour[GREEN] += b;
667 			colour[BLUE] += b;
668 			return *this;
669 		}
670 
671 		GenericRGBColour& operator-=(DBL b)
672 		{
673 			colour[RED] -= b;
674 			colour[GREEN] -= b;
675 			colour[BLUE] -= b;
676 			return *this;
677 		}
678 
679 		GenericRGBColour& operator*=(DBL b)
680 		{
681 			colour[RED] *= b;
682 			colour[GREEN] *= b;
683 			colour[BLUE] *= b;
684 			return *this;
685 		}
686 
687 		GenericRGBColour& operator/=(DBL b)
688 		{
689 			colour[RED] /= b;
690 			colour[GREEN] /= b;
691 			colour[BLUE] /= b;
692 			return *this;
693 		}
694 	private:
695 		DATA colour;
696 };
697 
698 template<typename T>
GenericColour(const GenericRGBColour<T> & col)699 inline GenericColour<T>::GenericColour(const GenericRGBColour<T>& col)
700 {
701 	colour[RED] = col[RED];
702 	colour[GREEN] = col[GREEN];
703 	colour[BLUE] = col[BLUE];
704 	colour[FILTER] = 0.0;
705 	colour[TRANSM] = 0.0;
706 }
707 
708 template<typename T>
GenericColour(const GenericRGBColour<T> & col,T nfilter,T ntransm)709 inline GenericColour<T>::GenericColour(const GenericRGBColour<T>& col, T nfilter, T ntransm)
710 {
711 	colour[RED] = col[RED];
712 	colour[GREEN] = col[GREEN];
713 	colour[BLUE] = col[BLUE];
714 	colour[FILTER] = nfilter;
715 	colour[TRANSM] = ntransm;
716 }
717 
718 template<typename T>
rgbTransm()719 inline GenericRGBColour<T> GenericColour<T>::rgbTransm() const
720 {
721 	return GenericRGBColour<T>( colour[RED]   * colour[FILTER] + colour[TRANSM],
722 	                            colour[GREEN] * colour[FILTER] + colour[TRANSM],
723 	                            colour[BLUE]  * colour[FILTER] + colour[TRANSM] );
724 }
725 
726 template<typename T>
727 inline GenericColour<T> operator* (double a, const GenericColour<T>& b) { return b * a; }
728 template<typename T>
729 inline GenericRGBColour<T> operator* (double a, const GenericRGBColour<T>& b) { return b * a; }
730 
731 template<typename T>
colourDistance(const GenericColour<T> & a,const GenericColour<T> & b)732 inline double colourDistance (const GenericColour<T>& a, const GenericColour<T>& b) { return fabs(a.red() - b.red()) + fabs(a.green() - b.green()) + fabs(a.blue() - b.blue()); }
733 template<typename T>
colourDistance(const GenericRGBColour<T> & a,const GenericRGBColour<T> & b)734 inline double colourDistance (const GenericRGBColour<T>& a, const GenericRGBColour<T>& b) { return fabs(a.red() - b.red()) + fabs(a.green() - b.green()) + fabs(a.blue() - b.blue()); }
735 
736 template<typename T>
Sqr(const GenericRGBColour<T> & a)737 inline GenericRGBColour<T> Sqr(const GenericRGBColour<T>& a) { return a * a; }
738 template<typename T>
exp(const GenericRGBColour<T> & a)739 inline GenericRGBColour<T> exp(const GenericRGBColour<T>& a) { return GenericRGBColour<T>(::exp(a.red()), ::exp(a.green()), ::exp(a.blue())); }
740 template<typename T>
sqrt(const GenericRGBColour<T> & a)741 inline GenericRGBColour<T> sqrt(const GenericRGBColour<T>& a) { return GenericRGBColour<T>(::sqrt(a.red()), ::sqrt(a.green()), ::sqrt(a.blue())); }
742 
743 typedef GenericColour<COLC>    Colour;
744 typedef GenericColour<DBL>     DblColour;
745 typedef GenericRGBColour<COLC> RGBColour;
746 typedef GenericRGBColour<DBL>  DblRGBColour;
747 
748 struct POVRect
749 {
750 	unsigned int top;
751 	unsigned int left;
752 	unsigned int bottom;
753 	unsigned int right;
754 
POVRectPOVRect755 	POVRect() : top(0), left(0), bottom(0), right(0) { }
POVRectPOVRect756 	POVRect(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) :
757 		top(y1), left(x1), bottom(y2), right(x2) { }
758 
GetAreaPOVRect759 	unsigned int GetArea() const { return ((bottom - top + 1) * (right - left + 1)); }
GetWidthPOVRect760 	unsigned int GetWidth() const { return (right - left + 1); }
GetHeightPOVRect761 	unsigned int GetHeight() const { return (bottom - top + 1); }
762 };
763 
764 class GenericSetting
765 {
766 	public:
set(set)767 		explicit GenericSetting(bool set = false): set(set) {}
Unset()768 		void Unset() { set = false; }
isSet()769 		bool isSet() const { return set; }
770 	protected:
771 		bool set;
772 };
773 
774 class FloatSetting : public GenericSetting
775 {
776 	public:
data(data)777 		explicit FloatSetting(double data = 0.0, bool set = false): data(data), GenericSetting(set) {}
778 		double operator=(double b)          { data = b; set = true; return data; }
779 		operator double() const             { return data; }
operator()780 		double operator()(double def) const { if (set) return data; else return def; }
781 	private:
782 		double  data;
783 };
784 
785 }
786 
787 #endif // POVRAY_BASE_TYPES_H
788