1 /*****************************************************************************
2 * fractal.cpp
3 *
4 * This module implements the fractal sets primitive.
5 *
6 * This file was written by Pascal Massimino.
7 *
8 * from Persistence of Vision(tm) Ray Tracer version 3.6.
9 * Copyright 1991-2003 Persistence of Vision Team
10 * Copyright 2003-2004 Persistence of Vision Raytracer Pty. Ltd.
11 *---------------------------------------------------------------------------
12 * NOTICE: This source code file is provided so that users may experiment
13 * with enhancements to POV-Ray and to port the software to platforms other
14 * than those supported by the POV-Ray developers. There are strict rules
15 * regarding how you are permitted to use this file. These rules are contained
16 * in the distribution and derivative versions licenses which should have been
17 * provided with this file.
18 *
19 * These licences may be found online, linked from the end-user license
20 * agreement that is located at http://www.povray.org/povlegal.html
21 *---------------------------------------------------------------------------
22 * This program is based on the popular DKB raytracer version 2.12.
23 * DKBTrace was originally written by David K. Buck.
24 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
25 *---------------------------------------------------------------------------
26 *
27 *===========================================================================
28 * This file is part of MegaPOV, a modified and unofficial version of POV-Ray
29 * For more information on MegaPOV visit our website:
30 * http://megapov.inetart.net/
31 *===========================================================================
32 *
33 * $RCSfile: fractal.cpp,v $
34 * $Revision: 1.12 $
35 * $Author: chris $
36 *
37 *****************************************************************************/
38
39 #include "frame.h"
40 #include "povray.h"
41 #include "vector.h"
42 #include "bbox.h"
43 #include "matrices.h"
44 #include "objects.h"
45 #include "spheres.h"
46 #include "fractal.h"
47 #include "quatern.h"
48 #include "hcmplx.h"
49
50 BEGIN_POV_NAMESPACE
51
52 /*****************************************************************************
53 * Local preprocessor defines
54 ******************************************************************************/
55
56 const DBL Fractal_Tolerance = 1e-7;
57
58
59
60 /*****************************************************************************
61 * Local typedefs
62 ******************************************************************************/
63
64
65
66 /*****************************************************************************
67 * Static functions
68 ******************************************************************************/
69
70 static int All_Fractal_Intersections (OBJECT * Object, RAY * Ray, ISTACK * Depth_Stack);
71 static int Inside_Fractal (VECTOR IPoint, OBJECT * Object);
72 static void Fractal_Normal (VECTOR Result, OBJECT * Object, INTERSECTION * Intersect);
73 static FRACTAL *Copy_Fractal (OBJECT * Object);
74 static void Translate_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
75 static void Rotate_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
76 static void Scale_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
77 static void Transform_Fractal (OBJECT * Object, TRANSFORM * Trans);
78 static void Invert_Fractal (OBJECT * Object);
79 static void Destroy_Fractal (OBJECT * Object);
80 static void Compute_Fractal_BBox (FRACTAL * Fractal);
81
82 /*****************************************************************************
83 * Local variables
84 ******************************************************************************/
85
86 #ifndef IS_PATCH
87 static
88 #endif
89 METHODS Fractal_Methods =
90 {
91 All_Fractal_Intersections,
92 Inside_Fractal, Fractal_Normal, Default_UVCoord,
93 (COPY_METHOD)Copy_Fractal,
94 Translate_Fractal, Rotate_Fractal,
95 Scale_Fractal, Transform_Fractal, Invert_Fractal,
96 Destroy_Fractal
97 };
98
99 static int Allocated_Iteration_Stack_Length = 0; // GLOBAL VARIABLE
100
101 DBL *Sx = NULL, *Sy = NULL, *Sz = NULL, *Sw = NULL; // GLOBAL VARIABLE
102 DBL Precision; // GLOBAL VARIABLE
103 VECTOR Direction; // GLOBAL VARIABLE
104
105 const COMPLEX_FUNCTION_METHOD Complex_Function_List[] =
106 {
107 /* must match STYPE list in fractal.h */
108 Complex_Exp,
109 Complex_Ln,
110 Complex_Sin,
111 Complex_ASin,
112 Complex_Cos,
113 Complex_ACos,
114 Complex_Tan,
115 Complex_ATan,
116 Complex_Sinh,
117 Complex_ASinh,
118 Complex_Cosh,
119 Complex_ACosh,
120 Complex_Tanh,
121 Complex_ATanh,
122 Complex_Pwr
123 };
124
125 /*****************************************************************************
126 *
127 * FUNCTION
128 *
129 * INPUT
130 *
131 * OUTPUT
132 *
133 * RETURNS
134 *
135 * AUTHOR
136 *
137 * Pascal Massimino
138 *
139 * DESCRIPTION
140 *
141 * -
142 *
143 * CHANGES
144 *
145 * Dec 1994 : Creation.
146 *
147 ******************************************************************************/
148
All_Fractal_Intersections(OBJECT * Object,RAY * Ray,ISTACK * Depth_Stack)149 static int All_Fractal_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
150 {
151 int Intersection_Found;
152 int Last = 0;
153 int CURRENT, NEXT;
154 DBL Depth, Depth_Max;
155 DBL Dist, Dist_Next, Len;
156
157 VECTOR IPoint, Mid_Point, Next_Point, Real_Pt;
158 VECTOR Real_Normal, F_Normal;
159 RAY New_Ray;
160 FRACTAL *Fractal = (FRACTAL *) Object;
161
162 Increase_Counter(stats[Ray_Fractal_Tests]);
163
164 Intersection_Found = false;
165 Precision = Fractal->Precision;
166
167 /* Get into Fractal's world. */
168
169 if (Fractal->Trans != NULL)
170 {
171 MInvTransDirection(Direction, Ray->Direction, Fractal->Trans);
172 VDot(Len, Direction, Direction);
173
174 if (Len == 0.0)
175 {
176 return (false);
177 }
178
179 if (Len != 1.0)
180 {
181 Len = 1.0 / sqrt(Len);
182 VScaleEq(Direction, Len);
183 }
184
185 Assign_Vector(New_Ray.Direction, Direction);
186 MInvTransPoint(New_Ray.Initial, Ray->Initial, Fractal->Trans);
187 }
188 else
189 {
190 Assign_Vector(Direction, Ray->Direction);
191 New_Ray = *Ray;
192 Len = 1.0;
193 }
194
195 /* Bound fractal. */
196
197 if (!F_Bound(&New_Ray, Fractal, &Depth, &Depth_Max))
198 {
199 return (false);
200 }
201
202 if (Depth_Max < Fractal_Tolerance)
203 {
204 return (false);
205 }
206
207 if (Depth < Fractal_Tolerance)
208 {
209 Depth = Fractal_Tolerance;
210 }
211
212 /* Jump to starting point */
213
214 VScale(Next_Point, Direction, Depth);
215 VAddEq(Next_Point, New_Ray.Initial);
216
217 CURRENT = D_Iteration(Next_Point, Fractal, &Dist);
218
219 /* Light ray starting inside ? */
220
221 if (CURRENT)
222 {
223 VAddScaledEq(Next_Point, 2.0 * Fractal_Tolerance, Direction);
224
225 Depth += 2.0 * Fractal_Tolerance;
226
227 if (Depth > Depth_Max)
228 {
229 return (false);
230 }
231
232 CURRENT = D_Iteration(Next_Point, Fractal, &Dist);
233 }
234
235 /* Ok. Trace it */
236
237 while (Depth < Depth_Max)
238 {
239 /*
240 * Get close to the root: Advance with Next_Point, keeping track of last
241 * position in IPoint...
242 */
243
244 while (1)
245 {
246 if (Dist < Precision)
247 {
248 Dist = Precision;
249 }
250
251 Depth += Dist;
252
253 if (Depth > Depth_Max)
254 {
255 if (Intersection_Found)
256 {
257 Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
258 }
259
260 return (Intersection_Found);
261 }
262
263 Assign_Vector(IPoint, Next_Point);
264 VAddScaledEq(Next_Point, Dist, Direction);
265
266 NEXT = D_Iteration(Next_Point, Fractal, &Dist_Next);
267
268 if (NEXT != CURRENT)
269 {
270 /* Set surface was crossed... */
271
272 Depth -= Dist;
273 break;
274 }
275 else
276 {
277 Dist = Dist_Next; /* not reached */
278 }
279 }
280
281 /* then, polish the root via bisection method... */
282
283 while (Dist > Fractal_Tolerance)
284 {
285 Dist *= 0.5;
286 VAddScaled(Mid_Point, IPoint, Dist, Direction);
287
288 Last = Iteration(Mid_Point, Fractal);
289
290 if (Last == CURRENT)
291 {
292 Assign_Vector(IPoint, Mid_Point);
293
294 Depth += Dist;
295
296 if (Depth > Depth_Max)
297 {
298 if (Intersection_Found)
299 {
300 Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
301 }
302
303 return (Intersection_Found);
304 }
305 }
306 }
307
308 if (CURRENT == false) /* Mid_Point isn't inside the set */
309 {
310 VAddScaledEq(IPoint, Dist, Direction);
311
312 Depth += Dist;
313
314 Iteration(IPoint, Fractal);
315 }
316 else
317 {
318 if (Last != CURRENT)
319 {
320 Iteration(IPoint, Fractal);
321 }
322 }
323
324 if (Fractal->Trans != NULL)
325 {
326 MTransPoint(Real_Pt, IPoint, Fractal->Trans);
327 Normal_Calc(Fractal, F_Normal);
328 MTransNormal(Real_Normal, F_Normal, Fractal->Trans);
329 }
330 else
331 {
332 Assign_Vector(Real_Pt, IPoint);
333 Normal_Calc(Fractal, Real_Normal);
334 }
335
336 if (Point_In_Clip(Real_Pt, Object->Clip))
337 {
338 VNormalize(Real_Normal, Real_Normal);
339 push_normal_entry(Depth * Len, Real_Pt, Real_Normal, Object, Depth_Stack);
340 Intersection_Found = true;
341
342 /* If fractal isn't used with CSG we can exit now. */
343
344 if (!(Fractal->Type & IS_CHILD_OBJECT))
345 {
346 break;
347 }
348 }
349
350 /* Start over where work was left */
351
352 Assign_Vector(IPoint, Next_Point);
353 Dist = Dist_Next;
354 CURRENT = NEXT;
355
356 }
357
358 if (Intersection_Found)
359 {
360 Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
361 }
362 return (Intersection_Found);
363 }
364
365 /*****************************************************************************
366 *
367 * FUNCTION
368 *
369 * INPUT
370 *
371 * OUTPUT
372 *
373 * RETURNS
374 *
375 * AUTHOR
376 *
377 * Pascal Massimino
378 *
379 * DESCRIPTION
380 *
381 * -
382 *
383 * CHANGES
384 *
385 * Dec 1994 : Creation.
386 *
387 ******************************************************************************/
388
Inside_Fractal(VECTOR IPoint,OBJECT * Object)389 static int Inside_Fractal(VECTOR IPoint, OBJECT *Object)
390 {
391 FRACTAL *Fractal = (FRACTAL *) Object;
392 int Result;
393 static VECTOR New_Point;
394
395 if (Fractal->Trans != NULL)
396 {
397 MInvTransPoint(New_Point, IPoint, Fractal->Trans);
398
399 Result = Iteration(New_Point, Fractal);
400 }
401 else
402 {
403 Result = Iteration(IPoint, Fractal);
404 }
405
406 if (Fractal->Inverted)
407 {
408 return (!Result);
409 }
410 else
411 {
412 return (Result);
413 }
414 }
415
416 /*****************************************************************************
417 *
418 * FUNCTION
419 *
420 * INPUT
421 *
422 * OUTPUT
423 *
424 * RETURNS
425 *
426 * AUTHOR
427 *
428 * Pascal Massimino
429 *
430 * DESCRIPTION
431 *
432 * -
433 *
434 * CHANGES
435 *
436 * Dec 1994 : Creation.
437 *
438 ******************************************************************************/
439
Fractal_Normal(VECTOR Result,OBJECT *,INTERSECTION * Intersect)440 static void Fractal_Normal(VECTOR Result, OBJECT *, INTERSECTION *Intersect)
441 {
442 Assign_Vector(Result, Intersect->INormal);
443 }
444
445 /*****************************************************************************
446 *
447 * FUNCTION
448 *
449 * INPUT
450 *
451 * OUTPUT
452 *
453 * RETURNS
454 *
455 * AUTHOR
456 *
457 * Pascal Massimino
458 *
459 * DESCRIPTION
460 *
461 * -
462 *
463 * CHANGES
464 *
465 * Dec 1994 : Creation.
466 *
467 ******************************************************************************/
468
Translate_Fractal(OBJECT * Object,VECTOR,TRANSFORM * Trans)469 static void Translate_Fractal(OBJECT *Object, VECTOR, TRANSFORM *Trans)
470 {
471 Transform_Fractal(Object, Trans);
472 }
473
474 /*****************************************************************************
475 *
476 * FUNCTION
477 *
478 * INPUT
479 *
480 * OUTPUT
481 *
482 * RETURNS
483 *
484 * AUTHOR
485 *
486 * Pascal Massimino
487 *
488 * DESCRIPTION
489 *
490 * -
491 *
492 * CHANGES
493 *
494 * Dec 1994 : Creation.
495 *
496 ******************************************************************************/
497
Rotate_Fractal(OBJECT * Object,VECTOR,TRANSFORM * Trans)498 static void Rotate_Fractal(OBJECT *Object, VECTOR, TRANSFORM *Trans)
499 {
500 Transform_Fractal(Object, Trans);
501 }
502
503 /*****************************************************************************
504 *
505 * FUNCTION
506 *
507 * INPUT
508 *
509 * OUTPUT
510 *
511 * RETURNS
512 *
513 * AUTHOR
514 *
515 * Pascal Massimino
516 *
517 * DESCRIPTION
518 *
519 * -
520 *
521 * CHANGES
522 *
523 * Dec 1994 : Creation.
524 *
525 ******************************************************************************/
526
Scale_Fractal(OBJECT * Object,VECTOR,TRANSFORM * Trans)527 static void Scale_Fractal(OBJECT *Object, VECTOR, TRANSFORM *Trans)
528 {
529 Transform_Fractal(Object, Trans);
530 }
531
532 /*****************************************************************************
533 *
534 * FUNCTION
535 *
536 * INPUT
537 *
538 * OUTPUT
539 *
540 * RETURNS
541 *
542 * AUTHOR
543 *
544 * Pascal Massimino
545 *
546 * DESCRIPTION
547 *
548 * -
549 *
550 * CHANGES
551 *
552 * Dec 1994 : Creation.
553 * Mar 1996 : Moved call to Recompute_BBox to Compute_Fractal_BBox() (TW)
554 *
555 ******************************************************************************/
556
Transform_Fractal(OBJECT * Object,TRANSFORM * Trans)557 static void Transform_Fractal(OBJECT *Object, TRANSFORM *Trans)
558 {
559 FRACTAL *Fractal = (FRACTAL *) Object;
560
561 if (((FRACTAL *) Object)->Trans == NULL)
562 {
563 ((FRACTAL *) Object)->Trans = Create_Transform();
564 }
565
566 Compose_Transforms(Fractal->Trans, Trans);
567
568 Compute_Fractal_BBox((FRACTAL *) Object);
569 }
570
571 /*****************************************************************************
572 *
573 * FUNCTION
574 *
575 * INPUT
576 *
577 * OUTPUT
578 *
579 * RETURNS
580 *
581 * AUTHOR
582 *
583 * Pascal Massimino
584 *
585 * DESCRIPTION
586 *
587 * -
588 *
589 * CHANGES
590 *
591 * Dec 1994 : Creation.
592 *
593 ******************************************************************************/
594
Invert_Fractal(OBJECT * Object)595 static void Invert_Fractal(OBJECT *Object)
596 {
597 ((FRACTAL *) Object)->Inverted ^= true;
598 }
599
600 /*****************************************************************************
601 *
602 * FUNCTION
603 *
604 * INPUT
605 *
606 * OUTPUT
607 *
608 * RETURNS
609 *
610 * AUTHOR
611 *
612 * Pascal Massimino
613 *
614 * DESCRIPTION
615 *
616 * -
617 *
618 * CHANGES
619 *
620 * Dec 1994 : Creation.
621 * Mar 1996 : Added call to recompute_BBox() to bottom (TW)
622 *
623 ******************************************************************************/
624
Compute_Fractal_BBox(FRACTAL * Fractal)625 static void Compute_Fractal_BBox(FRACTAL *Fractal)
626 {
627 DBL R;
628
629 switch (Fractal->Algebra)
630 {
631 case QUATERNION_TYPE:
632
633 R = 1.0 + sqrt(Sqr(Fractal->Julia_Parm[X]) + Sqr(Fractal->Julia_Parm[Y]) + Sqr(Fractal->Julia_Parm[Z]) + Sqr(Fractal->Julia_Parm[T]));
634 R += Fractal_Tolerance; /* fix bug when Julia_Parameter exactly 0 */
635
636 if (R > 2.0)
637 {
638 R = 2.0;
639 }
640
641 Fractal->Exit_Value = Sqr(R) + Fractal_Tolerance;
642
643 break;
644
645 case HYPERCOMPLEX_TYPE:
646 default:
647
648 R = 4.0;
649
650 Fractal->Exit_Value = 16.0;
651
652 break;
653 }
654
655 Fractal->Radius_Squared = Sqr(R);
656
657 Fractal->Inverted = false;
658
659 Make_BBox(Fractal->BBox, -R, -R, -R, 2.0 * R, 2.0 * R, 2.0 * R);
660
661 Recompute_BBox(&Fractal->BBox, Fractal->Trans);
662 }
663
664 /*****************************************************************************
665 *
666 * FUNCTION
667 *
668 * INPUT
669 *
670 * OUTPUT
671 *
672 * RETURNS
673 *
674 * AUTHOR
675 *
676 * Pascal Massimino
677 *
678 * DESCRIPTION
679 *
680 * -
681 *
682 * CHANGES
683 *
684 * Dec 1994 : Creation.
685 *
686 ******************************************************************************/
687
Create_Fractal()688 FRACTAL *Create_Fractal()
689 {
690 FRACTAL *New;
691
692 New = (FRACTAL *) POV_MALLOC(sizeof(FRACTAL), "Fractal Set");
693
694 INIT_OBJECT_FIELDS(New, BASIC_OBJECT, &Fractal_Methods)
695
696 New->Trans = NULL;
697
698 Make_Vector(New->Center, 0.0, 0.0, 0.0);
699
700 New->Julia_Parm[X] = 1.0;
701 New->Julia_Parm[Y] = 0.0;
702 New->Julia_Parm[Z] = 0.0;
703 New->Julia_Parm[T] = 0.0;
704
705 New->Slice[X] = 0.0;
706 New->Slice[Y] = 0.0;
707 New->Slice[Z] = 0.0;
708 New->Slice[T] = 1.0;
709 New->SliceDist = 0.0;
710
711 New->Exit_Value = 4.0;
712
713 New->n = 20;
714
715 New->Precision = 1.0 / 20.0;
716
717 New->Inverted = false;
718
719 New->Algebra = QUATERNION_TYPE;
720
721 New->Sub_Type = SQR_STYPE;
722
723 New->Bound = NULL;
724
725 New->Clip = NULL;
726
727 New->Normal_Calc_Method = NULL;
728 New->Iteration_Method = NULL;
729 New->D_Iteration_Method = NULL;
730 New->F_Bound_Method = NULL;
731 New->Complex_Function_Method = NULL;
732
733 New->Radius_Squared = 0.0;
734 New->exponent.x = 0.0;
735 New->exponent.y = 0.0;
736
737 return (New);
738 }
739
740 /*****************************************************************************
741 *
742 * FUNCTION
743 *
744 * INPUT
745 *
746 * OUTPUT
747 *
748 * RETURNS
749 *
750 * AUTHOR
751 *
752 * Pascal Massimino
753 *
754 * DESCRIPTION
755 *
756 * -
757 *
758 * CHANGES
759 *
760 * Dec 1994 : Creation.
761 *
762 ******************************************************************************/
763
Copy_Fractal(OBJECT * Object)764 static FRACTAL *Copy_Fractal(OBJECT *Object)
765 {
766 FRACTAL *New;
767
768 New = Create_Fractal();
769
770 *New = *((FRACTAL *) Object);
771
772 New->Trans = Copy_Transform(((FRACTAL *) Object)->Trans);
773
774 return (New);
775 }
776
777 /*****************************************************************************
778 *
779 * FUNCTION
780 *
781 * INPUT
782 *
783 * OUTPUT
784 *
785 * RETURNS
786 *
787 * AUTHOR
788 *
789 * Pascal Massimino
790 *
791 * DESCRIPTION
792 *
793 * -
794 *
795 * CHANGES
796 *
797 * Dec 1994 : Creation.
798 *
799 ******************************************************************************/
800
Destroy_Fractal(OBJECT * Object)801 static void Destroy_Fractal(OBJECT *Object)
802 {
803 Destroy_Transform(((FRACTAL *) Object)->Trans);
804 POV_FREE(Object);
805 }
806
807 /*****************************************************************************
808 *
809 * FUNCTION
810 *
811 * INPUT
812 *
813 * OUTPUT
814 *
815 * RETURNS
816 *
817 * AUTHOR
818 *
819 * Pascal Massimino
820 *
821 * DESCRIPTION
822 *
823 * -
824 *
825 * CHANGES
826 *
827 * Dec 1994 : Creation.
828 *
829 ******************************************************************************/
830
SetUp_Fractal(FRACTAL * Fractal)831 void SetUp_Fractal(FRACTAL *Fractal)
832 {
833 switch (Fractal->Algebra)
834 {
835 case QUATERNION_TYPE:
836
837 switch(Fractal->Sub_Type)
838 {
839 case CUBE_STYPE:
840 Fractal->Iteration_Method = Iteration_z3;
841 Fractal->Normal_Calc_Method = Normal_Calc_z3;
842 Fractal->D_Iteration_Method = D_Iteration_z3;
843 break;
844 case SQR_STYPE:
845 Fractal->Iteration_Method = Iteration_Julia;
846 Fractal->D_Iteration_Method = D_Iteration_Julia;
847 Fractal->Normal_Calc_Method = Normal_Calc_Julia;
848 break;
849 default:
850 Error("Illegal function: quaternion only supports sqr and cube");
851 }
852 Fractal->F_Bound_Method = F_Bound_Julia;
853
854 break;
855
856 case HYPERCOMPLEX_TYPE:
857
858 switch (Fractal->Sub_Type)
859 {
860 case RECIPROCAL_STYPE:
861
862 Fractal->Iteration_Method = Iteration_HCompl_Reciprocal;
863 Fractal->Normal_Calc_Method = Normal_Calc_HCompl_Reciprocal;
864 Fractal->D_Iteration_Method = D_Iteration_HCompl_Reciprocal;
865 Fractal->F_Bound_Method = F_Bound_HCompl_Reciprocal;
866
867 break;
868
869 case EXP_STYPE:
870 case LN_STYPE:
871 case SIN_STYPE:
872 case ASIN_STYPE:
873 case COS_STYPE:
874 case ACOS_STYPE:
875 case TAN_STYPE:
876 case ATAN_STYPE:
877 case SINH_STYPE:
878 case ASINH_STYPE:
879 case COSH_STYPE:
880 case ACOSH_STYPE:
881 case TANH_STYPE:
882 case ATANH_STYPE:
883 case PWR_STYPE:
884
885 Fractal->Iteration_Method = Iteration_HCompl_Func;
886 Fractal->Normal_Calc_Method = Normal_Calc_HCompl_Func;
887 Fractal->D_Iteration_Method = D_Iteration_HCompl_Func;
888 Fractal->F_Bound_Method = F_Bound_HCompl_Func;
889 Fractal->Complex_Function_Method = Complex_Function_List[Fractal->Sub_Type];
890
891 break;
892
893 case CUBE_STYPE:
894
895 Fractal->Iteration_Method = Iteration_HCompl_z3;
896 Fractal->Normal_Calc_Method = Normal_Calc_HCompl_z3;
897 Fractal->D_Iteration_Method = D_Iteration_HCompl_z3;
898 Fractal->F_Bound_Method = F_Bound_HCompl_z3;
899
900 break;
901
902 default: /* SQR_STYPE or else... */
903
904 Fractal->Iteration_Method = Iteration_HCompl;
905 Fractal->Normal_Calc_Method = Normal_Calc_HCompl;
906 Fractal->D_Iteration_Method = D_Iteration_HCompl;
907 Fractal->F_Bound_Method = F_Bound_HCompl;
908
909 break;
910 }
911
912 break;
913
914 default:
915
916 Error("Algebra unknown in fractal.");
917 }
918
919 Allocate_Iteration_Stack(Fractal->n);
920
921 Compute_Fractal_BBox(Fractal);
922 }
923
924 /*****************************************************************************
925 *
926 * FUNCTION
927 *
928 * INPUT
929 *
930 * OUTPUT
931 *
932 * RETURNS
933 *
934 * AUTHOR
935 *
936 * Pascal Massimino
937 *
938 * DESCRIPTION
939 *
940 * -
941 *
942 * CHANGES
943 *
944 * Dec 1994 : Creation.
945 *
946 ******************************************************************************/
947
Allocate_Iteration_Stack(int n)948 void Allocate_Iteration_Stack(int n)
949 {
950 if (n > Allocated_Iteration_Stack_Length)
951 {
952 Sx = (DBL *) POV_REALLOC(Sx, (n + 1) * sizeof(DBL), "x iteration stack");
953 Sy = (DBL *) POV_REALLOC(Sy, (n + 1) * sizeof(DBL), "y iteration stack");
954 Sz = (DBL *) POV_REALLOC(Sz, (n + 1) * sizeof(DBL), "w iteration stack");
955 Sw = (DBL *) POV_REALLOC(Sw, (n + 1) * sizeof(DBL), "z iteration stack");
956
957 Allocated_Iteration_Stack_Length = n;
958 }
959 }
960
961 /*****************************************************************************
962 *
963 * FUNCTION
964 *
965 * INPUT
966 *
967 * OUTPUT
968 *
969 * RETURNS
970 *
971 * AUTHOR
972 *
973 * Pascal Massimino
974 *
975 * DESCRIPTION
976 *
977 * -
978 *
979 * CHANGES
980 *
981 * Dec 1994 : Creation.
982 *
983 ******************************************************************************/
984
Free_Iteration_Stack()985 void Free_Iteration_Stack()
986 {
987 if (Sx != NULL)
988 {
989 POV_FREE(Sx);
990 POV_FREE(Sy);
991 POV_FREE(Sz);
992 POV_FREE(Sw);
993 }
994
995 Sx = NULL;
996 Sy = NULL;
997 Sz = NULL;
998 Sw = NULL;
999
1000 Allocated_Iteration_Stack_Length = 0;
1001 }
1002
1003 END_POV_NAMESPACE
1004