FRACTAL.C 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*****************************************************************************
  2. * fractal.c
  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
  9. * Copyright 1996,1999 Persistence of Vision Team
  10. *---------------------------------------------------------------------------
  11. * NOTICE: This source code file is provided so that users may experiment
  12. * with enhancements to POV-Ray and to port the software to platforms other
  13. * than those supported by the POV-Ray Team. There are strict rules under
  14. * which you are permitted to use this file. The rules are in the file
  15. * named POVLEGAL.DOC which should be distributed with this file.
  16. * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  17. * Team Coordinator by email to team-coord@povray.org or visit us on the web at
  18. * http://www.povray.org. The latest version of POV-Ray may be found at this site.
  19. *
  20. * This program is based on the popular DKB raytracer version 2.12.
  21. * DKBTrace was originally written by David K. Buck.
  22. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  23. *
  24. *****************************************************************************/
  25. #include "frame.h"
  26. #include "povray.h"
  27. #include "vector.h"
  28. #include "povproto.h"
  29. #include "bbox.h"
  30. #include "matrices.h"
  31. #include "objects.h"
  32. #include "spheres.h"
  33. #include "fractal.h"
  34. #include "quatern.h"
  35. #include "hcmplx.h"
  36. /*****************************************************************************
  37. * Local preprocessor defines
  38. ******************************************************************************/
  39. #ifndef Fractal_Tolerance
  40. #define Fractal_Tolerance 1e-7
  41. #endif
  42. /*****************************************************************************
  43. * Local typedefs
  44. ******************************************************************************/
  45. /*****************************************************************************
  46. * Static functions
  47. ******************************************************************************/
  48. static int All_Fractal_Intersections (OBJECT * Object, RAY * Ray, ISTACK * Depth_Stack);
  49. static int Inside_Fractal (VECTOR IPoint, OBJECT * Object);
  50. static void Fractal_Normal (VECTOR Result, OBJECT * Object, INTERSECTION * Intersect);
  51. static FRACTAL *Copy_Fractal (OBJECT * Object);
  52. static void Translate_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
  53. static void Rotate_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
  54. static void Scale_Fractal (OBJECT * Object, VECTOR Vector, TRANSFORM *Trans);
  55. static void Transform_Fractal (OBJECT * Object, TRANSFORM * Trans);
  56. static void Invert_Fractal (OBJECT * Object);
  57. static void Destroy_Fractal (OBJECT * Object);
  58. static void Compute_Fractal_BBox (FRACTAL * Fractal);
  59. /*****************************************************************************
  60. * Local variables
  61. ******************************************************************************/
  62. static METHODS Fractal_Methods =
  63. {
  64. All_Fractal_Intersections,
  65. Inside_Fractal, Fractal_Normal,
  66. (COPY_METHOD)Copy_Fractal,
  67. Translate_Fractal, Rotate_Fractal,
  68. Scale_Fractal, Transform_Fractal, Invert_Fractal,
  69. Destroy_Fractal
  70. };
  71. static int Allocated_Iteration_Stack_Length = 0;
  72. DBL *Sx = NULL, *Sy = NULL, *Sz = NULL, *Sw = NULL;
  73. DBL Precision;
  74. VECTOR Direction;
  75. static COMPLEX_FUNCTION_METHOD Complex_Function_List[] =
  76. {
  77. /* must match STYPE list in fractal.h */
  78. Complex_Exp,
  79. Complex_Log,
  80. Complex_Sin,
  81. Complex_ASin,
  82. Complex_Cos,
  83. Complex_ACos,
  84. Complex_Tan,
  85. Complex_ATan,
  86. Complex_Sinh,
  87. Complex_ASinh,
  88. Complex_Cosh,
  89. Complex_ACosh,
  90. Complex_Tanh,
  91. Complex_ATanh,
  92. Complex_Pwr
  93. };
  94. /*****************************************************************************
  95. *
  96. * FUNCTION
  97. *
  98. * INPUT
  99. *
  100. * OUTPUT
  101. *
  102. * RETURNS
  103. *
  104. * AUTHOR
  105. *
  106. * Pascal Massimino
  107. *
  108. * DESCRIPTION
  109. *
  110. * -
  111. *
  112. * CHANGES
  113. *
  114. * Dec 1994 : Creation.
  115. *
  116. ******************************************************************************/
  117. static int All_Fractal_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
  118. {
  119. int Intersection_Found;
  120. int Last = 0;
  121. int CURRENT, NEXT;
  122. DBL Depth, Depth_Max;
  123. DBL Dist, Dist_Next, Len;
  124. VECTOR IPoint, Mid_Point, Next_Point, Real_Pt;
  125. VECTOR Real_Normal, F_Normal;
  126. RAY New_Ray;
  127. FRACTAL *Fractal = (FRACTAL *) Object;
  128. Increase_Counter(stats[Ray_Fractal_Tests]);
  129. Intersection_Found = FALSE;
  130. Precision = Fractal->Precision;
  131. /* Get into Fractal's world. */
  132. if (Fractal->Trans != NULL)
  133. {
  134. MInvTransDirection(Direction, Ray->Direction, Fractal->Trans);
  135. VDot(Len, Direction, Direction);
  136. if (Len == 0.0)
  137. {
  138. return (FALSE);
  139. }
  140. if (Len != 1.0)
  141. {
  142. Len = 1.0 / sqrt(Len);
  143. VScaleEq(Direction, Len);
  144. }
  145. Assign_Vector(New_Ray.Direction, Direction);
  146. MInvTransPoint(New_Ray.Initial, Ray->Initial, Fractal->Trans);
  147. }
  148. else
  149. {
  150. Assign_Vector(Direction, Ray->Direction);
  151. New_Ray = *Ray;
  152. Len = 1.0;
  153. }
  154. /* Bound fractal. */
  155. if (!F_Bound(&New_Ray, Fractal, &Depth, &Depth_Max))
  156. {
  157. return (FALSE);
  158. }
  159. if (Depth_Max < Fractal_Tolerance)
  160. {
  161. return (FALSE);
  162. }
  163. if (Depth < Fractal_Tolerance)
  164. {
  165. Depth = Fractal_Tolerance;
  166. }
  167. /* Jump to starting point */
  168. VScale(Next_Point, Direction, Depth);
  169. VAddEq(Next_Point, New_Ray.Initial);
  170. CURRENT = D_Iteration(Next_Point, Fractal, &Dist);
  171. /* Light ray starting inside ? */
  172. if (CURRENT)
  173. {
  174. VAddScaledEq(Next_Point, 2.0 * Fractal_Tolerance, Direction);
  175. Depth += 2.0 * Fractal_Tolerance;
  176. if (Depth > Depth_Max)
  177. {
  178. return (FALSE);
  179. }
  180. CURRENT = D_Iteration(Next_Point, Fractal, &Dist);
  181. }
  182. /* Ok. Trace it */
  183. while (Depth < Depth_Max)
  184. {
  185. /*
  186. * Get close to the root: Advance with Next_Point, keeping track of last
  187. * position in IPoint...
  188. */
  189. while (1)
  190. {
  191. if (Dist < Precision)
  192. {
  193. Dist = Precision;
  194. }
  195. Depth += Dist;
  196. if (Depth > Depth_Max)
  197. {
  198. if (Intersection_Found)
  199. {
  200. Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
  201. }
  202. return (Intersection_Found);
  203. }
  204. Assign_Vector(IPoint, Next_Point);
  205. VAddScaledEq(Next_Point, Dist, Direction);
  206. NEXT = D_Iteration(Next_Point, Fractal, &Dist_Next);
  207. if (NEXT != CURRENT)
  208. {
  209. /* Set surface was crossed... */
  210. Depth -= Dist;
  211. break;
  212. }
  213. else
  214. {
  215. Dist = Dist_Next; /* not reached */
  216. }
  217. }
  218. /* then, polish the root via bisection method... */
  219. while (Dist > Fractal_Tolerance)
  220. {
  221. Dist *= 0.5;
  222. VAddScaled(Mid_Point, IPoint, Dist, Direction);
  223. Last = Iteration(Mid_Point, Fractal);
  224. if (Last == CURRENT)
  225. {
  226. Assign_Vector(IPoint, Mid_Point);
  227. Depth += Dist;
  228. if (Depth > Depth_Max)
  229. {
  230. if (Intersection_Found)
  231. {
  232. Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
  233. }
  234. return (Intersection_Found);
  235. }
  236. }
  237. }
  238. if (CURRENT == FALSE) /* Mid_Point isn't inside the set */
  239. {
  240. VAddScaledEq(IPoint, Dist, Direction);
  241. Depth += Dist;
  242. Iteration(IPoint, Fractal);
  243. }
  244. else
  245. {
  246. if (Last != CURRENT)
  247. {
  248. Iteration(IPoint, Fractal);
  249. }
  250. }
  251. if (Fractal->Trans != NULL)
  252. {
  253. MTransPoint(Real_Pt, IPoint, Fractal->Trans);
  254. Normal_Calc(Fractal, F_Normal);
  255. MTransNormal(Real_Normal, F_Normal, Fractal->Trans);
  256. }
  257. else
  258. {
  259. Assign_Vector(Real_Pt, IPoint);
  260. Normal_Calc(Fractal, Real_Normal);
  261. }
  262. if (Point_In_Clip(Real_Pt, Object->Clip))
  263. {
  264. VNormalize(Real_Normal, Real_Normal);
  265. push_normal_entry(Depth * Len, Real_Pt, Real_Normal, Object, Depth_Stack);
  266. Intersection_Found = TRUE;
  267. /* If fractal isn't used with CSG we can exit now. */
  268. if (!(Fractal->Type & IS_CHILD_OBJECT))
  269. {
  270. break;
  271. }
  272. }
  273. /* Start over where work was left */
  274. Assign_Vector(IPoint, Next_Point);
  275. Dist = Dist_Next;
  276. CURRENT = NEXT;
  277. }
  278. if (Intersection_Found)
  279. {
  280. Increase_Counter(stats[Ray_Fractal_Tests_Succeeded]);
  281. }
  282. return (Intersection_Found);
  283. }
  284. /*****************************************************************************
  285. *
  286. * FUNCTION
  287. *
  288. * INPUT
  289. *
  290. * OUTPUT
  291. *
  292. * RETURNS
  293. *
  294. * AUTHOR
  295. *
  296. * Pascal Massimino
  297. *
  298. * DESCRIPTION
  299. *
  300. * -
  301. *
  302. * CHANGES
  303. *
  304. * Dec 1994 : Creation.
  305. *
  306. ******************************************************************************/
  307. static int Inside_Fractal(VECTOR IPoint, OBJECT *Object)
  308. {
  309. FRACTAL *Fractal = (FRACTAL *) Object;
  310. int Result;
  311. static VECTOR New_Point;
  312. if (Fractal->Trans != NULL)
  313. {
  314. MInvTransPoint(New_Point, IPoint, Fractal->Trans);
  315. Result = Iteration(New_Point, Fractal);
  316. }
  317. else
  318. {
  319. Result = Iteration(IPoint, Fractal);
  320. }
  321. if (Fractal->Inverted)
  322. {
  323. return (!Result);
  324. }
  325. else
  326. {
  327. return (Result);
  328. }
  329. }
  330. /*****************************************************************************
  331. *
  332. * FUNCTION
  333. *
  334. * INPUT
  335. *
  336. * OUTPUT
  337. *
  338. * RETURNS
  339. *
  340. * AUTHOR
  341. *
  342. * Pascal Massimino
  343. *
  344. * DESCRIPTION
  345. *
  346. * -
  347. *
  348. * CHANGES
  349. *
  350. * Dec 1994 : Creation.
  351. *
  352. ******************************************************************************/
  353. static void Fractal_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Intersect)
  354. {
  355. Assign_Vector(Result, Intersect->INormal);
  356. }
  357. /*****************************************************************************
  358. *
  359. * FUNCTION
  360. *
  361. * INPUT
  362. *
  363. * OUTPUT
  364. *
  365. * RETURNS
  366. *
  367. * AUTHOR
  368. *
  369. * Pascal Massimino
  370. *
  371. * DESCRIPTION
  372. *
  373. * -
  374. *
  375. * CHANGES
  376. *
  377. * Dec 1994 : Creation.
  378. *
  379. ******************************************************************************/
  380. static void Translate_Fractal(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  381. {
  382. Transform_Fractal(Object, Trans);
  383. }
  384. /*****************************************************************************
  385. *
  386. * FUNCTION
  387. *
  388. * INPUT
  389. *
  390. * OUTPUT
  391. *
  392. * RETURNS
  393. *
  394. * AUTHOR
  395. *
  396. * Pascal Massimino
  397. *
  398. * DESCRIPTION
  399. *
  400. * -
  401. *
  402. * CHANGES
  403. *
  404. * Dec 1994 : Creation.
  405. *
  406. ******************************************************************************/
  407. static void Rotate_Fractal(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  408. {
  409. Transform_Fractal(Object, Trans);
  410. }
  411. /*****************************************************************************
  412. *
  413. * FUNCTION
  414. *
  415. * INPUT
  416. *
  417. * OUTPUT
  418. *
  419. * RETURNS
  420. *
  421. * AUTHOR
  422. *
  423. * Pascal Massimino
  424. *
  425. * DESCRIPTION
  426. *
  427. * -
  428. *
  429. * CHANGES
  430. *
  431. * Dec 1994 : Creation.
  432. *
  433. ******************************************************************************/
  434. static void Scale_Fractal(OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
  435. {
  436. Transform_Fractal(Object, Trans);
  437. }
  438. /*****************************************************************************
  439. *
  440. * FUNCTION
  441. *
  442. * INPUT
  443. *
  444. * OUTPUT
  445. *
  446. * RETURNS
  447. *
  448. * AUTHOR
  449. *
  450. * Pascal Massimino
  451. *
  452. * DESCRIPTION
  453. *
  454. * -
  455. *
  456. * CHANGES
  457. *
  458. * Dec 1994 : Creation.
  459. * Mar 1996 : Moved call to Recompute_BBox to Compute_Fractal_BBox() (TW)
  460. *
  461. ******************************************************************************/
  462. static void Transform_Fractal(OBJECT *Object, TRANSFORM *Trans)
  463. {
  464. FRACTAL *Fractal = (FRACTAL *) Object;
  465. if (((FRACTAL *) Object)->Trans == NULL)
  466. {
  467. ((FRACTAL *) Object)->Trans = Create_Transform();
  468. }
  469. Compose_Transforms(Fractal->Trans, Trans);
  470. Compute_Fractal_BBox((FRACTAL *) Object);
  471. }
  472. /*****************************************************************************
  473. *
  474. * FUNCTION
  475. *
  476. * INPUT
  477. *
  478. * OUTPUT
  479. *
  480. * RETURNS
  481. *
  482. * AUTHOR
  483. *
  484. * Pascal Massimino
  485. *
  486. * DESCRIPTION
  487. *
  488. * -
  489. *
  490. * CHANGES
  491. *
  492. * Dec 1994 : Creation.
  493. *
  494. ******************************************************************************/
  495. static void Invert_Fractal(OBJECT *Object)
  496. {
  497. ((FRACTAL *) Object)->Inverted ^= TRUE;
  498. }
  499. /*****************************************************************************
  500. *
  501. * FUNCTION
  502. *
  503. * INPUT
  504. *
  505. * OUTPUT
  506. *
  507. * RETURNS
  508. *
  509. * AUTHOR
  510. *
  511. * Pascal Massimino
  512. *
  513. * DESCRIPTION
  514. *
  515. * -
  516. *
  517. * CHANGES
  518. *
  519. * Dec 1994 : Creation.
  520. * Mar 1996 : Added call to recompute_BBox() to bottom (TW)
  521. *
  522. ******************************************************************************/
  523. static void Compute_Fractal_BBox(FRACTAL *Fractal)
  524. {
  525. DBL R;
  526. switch (Fractal->Algebra)
  527. {
  528. case QUATERNION_TYPE:
  529. R = 1.0 + sqrt(Sqr(Fractal->Julia_Parm[X]) + Sqr(Fractal->Julia_Parm[Y]) + Sqr(Fractal->Julia_Parm[Z]) + Sqr(Fractal->Julia_Parm[T]));
  530. R += Fractal_Tolerance; /* fix bug when Julia_Parameter exactly 0 */
  531. if (R > 2.0)
  532. {
  533. R = 2.0;
  534. }
  535. Fractal->Exit_Value = Sqr(R);
  536. break;
  537. case HYPERCOMPLEX_TYPE:
  538. default:
  539. R = 4.0;
  540. Fractal->Exit_Value = 16.0;
  541. break;
  542. }
  543. Fractal->Radius_Squared = Sqr(R);
  544. Fractal->Inverted = FALSE;
  545. Make_BBox(Fractal->BBox, -R, -R, -R, 2.0 * R, 2.0 * R, 2.0 * R);
  546. Recompute_BBox(&Fractal->BBox, Fractal->Trans);
  547. }
  548. /*****************************************************************************
  549. *
  550. * FUNCTION
  551. *
  552. * INPUT
  553. *
  554. * OUTPUT
  555. *
  556. * RETURNS
  557. *
  558. * AUTHOR
  559. *
  560. * Pascal Massimino
  561. *
  562. * DESCRIPTION
  563. *
  564. * -
  565. *
  566. * CHANGES
  567. *
  568. * Dec 1994 : Creation.
  569. *
  570. ******************************************************************************/
  571. FRACTAL *Create_Fractal()
  572. {
  573. FRACTAL *New;
  574. New = (FRACTAL *) POV_MALLOC(sizeof(FRACTAL), "Fractal Set");
  575. INIT_OBJECT_FIELDS(New, BASIC_OBJECT, &Fractal_Methods)
  576. New->Trans = NULL;
  577. Make_Vector(New->Center, 0.0, 0.0, 0.0);
  578. New->Julia_Parm[X] = 1.0;
  579. New->Julia_Parm[Y] = 0.0;
  580. New->Julia_Parm[Z] = 0.0;
  581. New->Julia_Parm[T] = 0.0;
  582. New->Slice[X] = 0.0;
  583. New->Slice[Y] = 0.0;
  584. New->Slice[Z] = 0.0;
  585. New->Slice[T] = 1.0;
  586. New->SliceDist = 0.0;
  587. New->Exit_Value = 4.0;
  588. New->n = 20;
  589. New->Precision = 1.0 / 20.0;
  590. New->Inverted = FALSE;
  591. New->Algebra = QUATERNION_TYPE;
  592. New->Sub_Type = SQR_STYPE;
  593. New->Bound = NULL;
  594. New->Clip = NULL;
  595. New->Normal_Calc_Method = NULL;
  596. New->Iteration_Method = NULL;
  597. New->D_Iteration_Method = NULL;
  598. New->F_Bound_Method = NULL;
  599. New->Complex_Function_Method = NULL;
  600. New->Radius_Squared = 0.0;
  601. New->exponent.x = 0.0;
  602. New->exponent.y = 0.0;
  603. return (New);
  604. }
  605. /*****************************************************************************
  606. *
  607. * FUNCTION
  608. *
  609. * INPUT
  610. *
  611. * OUTPUT
  612. *
  613. * RETURNS
  614. *
  615. * AUTHOR
  616. *
  617. * Pascal Massimino
  618. *
  619. * DESCRIPTION
  620. *
  621. * -
  622. *
  623. * CHANGES
  624. *
  625. * Dec 1994 : Creation.
  626. *
  627. ******************************************************************************/
  628. static FRACTAL *Copy_Fractal(OBJECT *Object)
  629. {
  630. FRACTAL *New;
  631. New = Create_Fractal();
  632. *New = *((FRACTAL *) Object);
  633. New->Trans = Copy_Transform(((FRACTAL *) Object)->Trans);
  634. return (New);
  635. }
  636. /*****************************************************************************
  637. *
  638. * FUNCTION
  639. *
  640. * INPUT
  641. *
  642. * OUTPUT
  643. *
  644. * RETURNS
  645. *
  646. * AUTHOR
  647. *
  648. * Pascal Massimino
  649. *
  650. * DESCRIPTION
  651. *
  652. * -
  653. *
  654. * CHANGES
  655. *
  656. * Dec 1994 : Creation.
  657. *
  658. ******************************************************************************/
  659. static void Destroy_Fractal(OBJECT *Object)
  660. {
  661. Destroy_Transform(((FRACTAL *) Object)->Trans);
  662. POV_FREE(Object);
  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. void SetUp_Fractal(FRACTAL *Fractal)
  688. {
  689. switch (Fractal->Algebra)
  690. {
  691. case QUATERNION_TYPE:
  692. switch(Fractal->Sub_Type)
  693. {
  694. case CUBE_STYPE:
  695. Fractal->Iteration_Method = Iteration_z3;
  696. Fractal->Normal_Calc_Method = Normal_Calc_z3;
  697. Fractal->D_Iteration_Method = D_Iteration_z3;
  698. break;
  699. case SQR_STYPE:
  700. Fractal->Iteration_Method = Iteration_Julia;
  701. Fractal->D_Iteration_Method = D_Iteration_Julia;
  702. Fractal->Normal_Calc_Method = Normal_Calc_Julia;
  703. break;
  704. default:
  705. Error("illegal function: quaternion only supports sqr and cube");
  706. }
  707. Fractal->F_Bound_Method = F_Bound_Julia;
  708. break;
  709. case HYPERCOMPLEX_TYPE:
  710. switch (Fractal->Sub_Type)
  711. {
  712. case RECIPROCAL_STYPE:
  713. Fractal->Iteration_Method = Iteration_HCompl_Reciprocal;
  714. Fractal->Normal_Calc_Method = Normal_Calc_HCompl_Reciprocal;
  715. Fractal->D_Iteration_Method = D_Iteration_HCompl_Reciprocal;
  716. Fractal->F_Bound_Method = F_Bound_HCompl_Reciprocal;
  717. break;
  718. case EXP_STYPE:
  719. case LOG_STYPE:
  720. case SIN_STYPE:
  721. case ASIN_STYPE:
  722. case COS_STYPE:
  723. case ACOS_STYPE:
  724. case TAN_STYPE:
  725. case ATAN_STYPE:
  726. case SINH_STYPE:
  727. case ASINH_STYPE:
  728. case COSH_STYPE:
  729. case ACOSH_STYPE:
  730. case TANH_STYPE:
  731. case ATANH_STYPE:
  732. case PWR_STYPE:
  733. Fractal->Iteration_Method = Iteration_HCompl_Func;
  734. Fractal->Normal_Calc_Method = Normal_Calc_HCompl_Func;
  735. Fractal->D_Iteration_Method = D_Iteration_HCompl_Func;
  736. Fractal->F_Bound_Method = F_Bound_HCompl_Func;
  737. Fractal->Complex_Function_Method = Complex_Function_List[Fractal->Sub_Type];
  738. break;
  739. case CUBE_STYPE:
  740. Fractal->Iteration_Method = Iteration_HCompl_z3;
  741. Fractal->Normal_Calc_Method = Normal_Calc_HCompl_z3;
  742. Fractal->D_Iteration_Method = D_Iteration_HCompl_z3;
  743. Fractal->F_Bound_Method = F_Bound_HCompl_z3;
  744. break;
  745. default: /* SQR_STYPE or else... */
  746. Fractal->Iteration_Method = Iteration_HCompl;
  747. Fractal->Normal_Calc_Method = Normal_Calc_HCompl;
  748. Fractal->D_Iteration_Method = D_Iteration_HCompl;
  749. Fractal->F_Bound_Method = F_Bound_HCompl;
  750. break;
  751. }
  752. break;
  753. default:
  754. Error("Algebra unknown in fractal.");
  755. }
  756. Allocate_Iteration_Stack(Fractal->n);
  757. Compute_Fractal_BBox(Fractal);
  758. }
  759. /*****************************************************************************
  760. *
  761. * FUNCTION
  762. *
  763. * INPUT
  764. *
  765. * OUTPUT
  766. *
  767. * RETURNS
  768. *
  769. * AUTHOR
  770. *
  771. * Pascal Massimino
  772. *
  773. * DESCRIPTION
  774. *
  775. * -
  776. *
  777. * CHANGES
  778. *
  779. * Dec 1994 : Creation.
  780. *
  781. ******************************************************************************/
  782. void Allocate_Iteration_Stack(int n)
  783. {
  784. if (n > Allocated_Iteration_Stack_Length)
  785. {
  786. Sx = (DBL *) POV_REALLOC(Sx, (n + 1) * sizeof(DBL), "x iteration stack");
  787. Sy = (DBL *) POV_REALLOC(Sy, (n + 1) * sizeof(DBL), "y iteration stack");
  788. Sz = (DBL *) POV_REALLOC(Sz, (n + 1) * sizeof(DBL), "w iteration stack");
  789. Sw = (DBL *) POV_REALLOC(Sw, (n + 1) * sizeof(DBL), "z iteration stack");
  790. Allocated_Iteration_Stack_Length = n;
  791. }
  792. }
  793. /*****************************************************************************
  794. *
  795. * FUNCTION
  796. *
  797. * INPUT
  798. *
  799. * OUTPUT
  800. *
  801. * RETURNS
  802. *
  803. * AUTHOR
  804. *
  805. * Pascal Massimino
  806. *
  807. * DESCRIPTION
  808. *
  809. * -
  810. *
  811. * CHANGES
  812. *
  813. * Dec 1994 : Creation.
  814. *
  815. ******************************************************************************/
  816. void Free_Iteration_Stack()
  817. {
  818. if (Sx != NULL)
  819. {
  820. POV_FREE(Sx);
  821. POV_FREE(Sy);
  822. POV_FREE(Sz);
  823. POV_FREE(Sw);
  824. }
  825. Sx = NULL;
  826. Sy = NULL;
  827. Sz = NULL;
  828. Sw = NULL;
  829. Allocated_Iteration_Stack_Length = 0;
  830. }