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