home *** CD-ROM | disk | FTP | other *** search
/ Computerworld 1996 March / Computerworld_1996-03_cd.bin / idg_cd3 / grafika / fraktaly / frasr192 / lorenz.c < prev    next >
C/C++ Source or Header  |  1995-03-08  |  70KB  |  2,593 lines

  1. /*
  2.    This file contains two 3 dimensional orbit-type fractal
  3.    generators - IFS and LORENZ3D, along with code to generate
  4.    red/blue 3D images. Tim Wegner
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <float.h>
  10. #include <math.h>
  11. #include <string.h>
  12. #include "mpmath.h"
  13. #include "fractint.h"
  14. #include "fractype.h"
  15. #include "prototyp.h"
  16.  
  17. /* orbitcalc is declared with no arguments so jump through hoops here */
  18. #define LORBIT(x,y,z) \
  19.    (*(int(*)(long *,long *,long *))curfractalspecific->orbitcalc)(x,y,z)
  20. #define FORBIT(x,y,z) \
  21.    (*(int(*)(double*,double*,double*))curfractalspecific->orbitcalc)(x,y,z)
  22.  
  23. #define RANDOM(x)  (rand()%(x))
  24. /* BAD_PIXEL is used to cutoff orbits that are diverging. It might be better
  25. to test the actual floating point prbit values, but this seems safe for now.
  26. A higher value cannot be used - to test, turn off math coprocessor and
  27. use +2.24 for type ICONS. If BAD_PIXEL is set to 20000, this will abort
  28. Fractint with a math error. Note that this approach precludes zooming in very
  29. far to an orbit type. */
  30.  
  31. #define BAD_PIXEL  10000L    /* pixels can't get this big */
  32.  
  33. struct l_affine
  34. {
  35.    /* weird order so a,b,e and c,d,f are vectors */
  36.    long a;
  37.    long b;
  38.    long e;
  39.    long c;
  40.    long d;
  41.    long f;
  42. };
  43. struct long3dvtinf /* data used by 3d view transform subroutine */
  44. {
  45.    long orbit[3];    /* interated function orbit value */
  46.    long iview[3];    /* perspective viewer's coordinates */
  47.    long viewvect[3];    /* orbit transformed for viewing */
  48.    long viewvect1[3];    /* orbit transformed for viewing */
  49.    long maxvals[3];
  50.    long minvals[3];
  51.    MATRIX doublemat;    /* transformation matrix */
  52.    MATRIX doublemat1;    /* transformation matrix */
  53.    long longmat[4][4];    /* long version of matrix */
  54.    long longmat1[4][4]; /* long version of matrix */
  55.    int row,col;     /* results */
  56.    int row1,col1;
  57.    struct l_affine cvt;
  58. };
  59.  
  60. struct float3dvtinf /* data used by 3d view transform subroutine */
  61. {
  62.    double orbit[3];           /* interated function orbit value */
  63.    double viewvect[3];          /* orbit transformed for viewing */
  64.    double viewvect1[3];        /* orbit transformed for viewing */
  65.    double maxvals[3];
  66.    double minvals[3];
  67.    MATRIX doublemat;    /* transformation matrix */
  68.    MATRIX doublemat1;    /* transformation matrix */
  69.    int row,col;     /* results */
  70.    int row1,col1;
  71.    struct affine cvt;
  72. };
  73.  
  74. /* Routines in this module    */
  75.  
  76. static int  ifs2d(void);
  77. static int  ifs3d(void);
  78. static int  ifs3dlong(void);
  79. static int  ifs3dfloat(void);
  80. static double determinant(double mat[3][3]);
  81. static int  solve3x3(double mat[3][3],double vec[3],double ans[3]);
  82. static int  l_setup_convert_to_screen(struct l_affine *);
  83. static void setupmatrix(MATRIX);
  84. static int  long3dviewtransf(struct long3dvtinf *inf);
  85. static int  float3dviewtransf(struct float3dvtinf *inf);
  86. static FILE *open_orbitsave(void);
  87. static void _fastcall plothist(int x, int y, int color);
  88. static int realtime;
  89. static char orbitsavename[]    = {"orbits.raw"};
  90. static char orbitsave_format[] = {"%g %g %g 15\n"};
  91.  
  92. S32 maxct;
  93. static int t;
  94. static long l_dx,l_dy,l_dz,l_dt,l_a,l_b,l_c,l_d;
  95. static long l_adt,l_bdt,l_cdt,l_xdt,l_ydt;
  96. static long initorbitlong[3];
  97.  
  98. static double dx,dy,dz,dt,a,b,c,d;
  99. static double adt,bdt,cdt,xdt,ydt,zdt;
  100. static double initorbitfp[3];
  101.  
  102. /*
  103.  * The following declarations used for Inverse Julia.  MVS
  104.  */
  105.  
  106. static FCODE NoQueue[] =
  107.   "Not enough memory: switching to random walk.\n";
  108.  
  109. static int    mxhits;
  110. int    run_length;
  111. /*
  112. enum   {breadth_first, depth_first, random_walk, random_run} major_method;
  113. enum   {left_first, right_first}                             minor_method;
  114. */
  115. enum   Major major_method;
  116. enum   Minor minor_method;
  117. struct affine cvt;
  118. struct l_affine lcvt;
  119.  
  120. double Cx, Cy;
  121. long   CxLong, CyLong;
  122.  
  123. /*
  124.  * end of Inverse Julia declarations;
  125.  */
  126.  
  127. /* these are potential user parameters */
  128. int connect = 1;    /* flag to connect points with a line */
  129. int euler = 0;        /* use implicit euler approximation for dynamic system */
  130. int waste = 100;    /* waste this many points before plotting */
  131. int projection = 2; /* projection plane - default is to plot x-y */
  132.  
  133. /******************************************************************/
  134. /*           zoom box conversion functions          */
  135. /******************************************************************/
  136.  
  137. static double determinant(double mat[3][3]) /* determinant of 3x3 matrix */
  138. {
  139.    /* calculate determinant of 3x3 matrix */
  140.    return(mat[0][0]*mat[1][1]*mat[2][2] +
  141.       mat[0][2]*mat[1][0]*mat[2][1] +
  142.       mat[0][1]*mat[1][2]*mat[2][0] -
  143.       mat[2][0]*mat[1][1]*mat[0][2] -
  144.       mat[1][0]*mat[0][1]*mat[2][2] -
  145.       mat[0][0]*mat[1][2]*mat[2][1]);
  146.  
  147. }
  148.  
  149. static int solve3x3(double mat[3][3],double vec[3],double ans[3])
  150. /* solve 3x3 inhomogeneous linear equations */
  151. {
  152.    /* solve 3x3 linear equation [mat][ans] = [vec] */
  153.    double denom;
  154.    double tmp[3][3];
  155.    int i;
  156.    denom = determinant(mat);
  157.    if(fabs(denom) < DBL_EPSILON) /* test if can solve */
  158.    {
  159.      /* stopmsg(0,"determin 0"); */
  160.      return(-1);
  161.    }
  162.    memcpy(tmp,mat,sizeof(double)*9);
  163.    for(i=0;i<3;i++)
  164.    {
  165.       tmp[0][i] = vec[0];
  166.       tmp[1][i] = vec[1];
  167.       tmp[2][i] = vec[2];
  168.       ans[i]  =  determinant(tmp)/denom;
  169.       tmp[0][i] = mat[0][i];
  170.       tmp[1][i] = mat[1][i];
  171.       tmp[2][i] = mat[2][i];
  172.     }
  173.     return(0);
  174. }
  175.  
  176.  
  177. /* Conversion of complex plane to screen coordinates for rotating zoom box.
  178.    Assume there is an affine transformation mapping complex zoom parallelogram
  179.    to rectangular screen. We know this map must map parallelogram corners to
  180.    screen corners, so we have following equations:
  181.  
  182.       a*xxmin+b*yymax+e == 0        (upper left)
  183.       c*xxmin+d*yymax+f == 0
  184.  
  185.       a*xx3rd+b*yy3rd+e == 0        (lower left)
  186.       c*xx3rd+d*yy3rd+f == ydots-1
  187.  
  188.       a*xxmax+b*yymin+e == xdots-1  (lower right)
  189.       c*xxmax+d*yymin+f == ydots-1
  190.  
  191.       First we must solve for a,b,c,d,e,f - (which we do once per image),
  192.       then we just apply the transformation to each orbit value.
  193. */
  194.  
  195. int setup_convert_to_screen(struct affine *scrn_cnvt)
  196. {
  197.    /* we do this twice - rather than having six equations with six unknowns,
  198.       everything partitions to two sets of three equations with three
  199.       unknowns. Nice, because who wants to calculate a 6x6 determinant??
  200.     */
  201.    double mat[3][3];
  202.    double vec[3];
  203.    /*
  204.       first these equations - solve for a,b,e
  205.       a*xxmin+b*yymax+e == 0        (upper left)
  206.       a*xx3rd+b*yy3rd+e == 0        (lower left)
  207.       a*xxmax+b*yymin+e == xdots-1  (lower right)
  208.    */
  209.    mat[0][0] = xxmin;
  210.    mat[0][1] = yymax;
  211.    mat[0][2] = 1.0;
  212.    mat[1][0] = xx3rd;
  213.    mat[1][1] = yy3rd;
  214.    mat[1][2] = 1.0;
  215.    mat[2][0] = xxmax;
  216.    mat[2][1] = yymin;
  217.    mat[2][2] = 1.0;
  218.    vec[0]    = 0.0;
  219.    vec[1]    = 0.0;
  220.    vec[2]    = (double)(xdots-1);
  221.  
  222.    if(solve3x3(mat,vec, &(scrn_cnvt->a)))
  223.       return(-1);
  224.    /*
  225.       now solve these:
  226.       c*xxmin+d*yymax+f == 0
  227.       c*xx3rd+d*yy3rd+f == ydots-1
  228.       c*xxmax+d*yymin+f == ydots-1
  229.       (mat[][] has not changed - only vec[])
  230.    */
  231.    vec[0]    = 0.0;
  232.    vec[1]    = (double)(ydots-1);
  233.    vec[2]    = (double)(ydots-1);
  234.  
  235.    if(solve3x3(mat,vec, &scrn_cnvt->c))
  236.       return(-1);
  237.    return(0);
  238. }
  239.  
  240. static int l_setup_convert_to_screen(struct l_affine *l_cvt)
  241. {
  242.    struct affine cvt;
  243.  
  244.    /* MCP 7-7-91, This function should return a something! */
  245.    if(setup_convert_to_screen(&cvt))
  246.       return(-1);
  247.    l_cvt->a = (long)(cvt.a*fudge); l_cvt->b = (long)(cvt.b*fudge); l_cvt->c = (long)(cvt.c*fudge);
  248.    l_cvt->d = (long)(cvt.d*fudge); l_cvt->e = (long)(cvt.e*fudge); l_cvt->f = (long)(cvt.f*fudge);
  249.  
  250.    /* MCP 7-7-91 */
  251.    return(0);
  252. }
  253.  
  254.  
  255. /******************************************************************/
  256. /*   setup functions - put in fractalspecific[fractype].per_image */
  257. /******************************************************************/
  258.  
  259. static double orbit;
  260. static long   l_orbit;
  261. static long l_sinx,l_cosx;
  262.  
  263. int orbit3dlongsetup()
  264. {
  265.    maxct = 0L;
  266.    connect = 1;
  267.    waste = 100;
  268.    projection = 2;
  269.    if (fractype==LHENON || fractype==KAM || fractype==KAM3D || 
  270.        fractype==INVERSEJULIA)
  271.       connect=0;
  272.    if(fractype==LROSSLER)
  273.       waste = 500;
  274.    if(fractype==LLORENZ)
  275.       projection = 1;
  276.  
  277.    initorbitlong[0] = fudge;  /* initial conditions */
  278.    initorbitlong[1] = fudge;
  279.    initorbitlong[2] = fudge;
  280.  
  281.    if(fractype==LHENON)
  282.    {
  283.       l_a =  (long)(param[0]*fudge);
  284.       l_b =  (long)(param[1]*fudge);
  285.       l_c =  (long)(param[2]*fudge);
  286.       l_d =  (long)(param[3]*fudge);
  287.    }
  288.    else if(fractype==KAM || fractype==KAM3D)
  289.    {
  290.       maxct = 1L;                
  291.       a   = param[0];        /* angle */
  292.       if(param[1] <= 0.0)
  293.      param[1] = .01;
  294.       l_b =  (long)(param[1]*fudge);    /* stepsize */
  295.       l_c =  (long)(param[2]*fudge);    /* stop */
  296.       t = (int)(l_d =  (long)(param[3]));     /* points per orbit */
  297.  
  298.       l_sinx = (long)(sin(a)*fudge);
  299.       l_cosx = (long)(cos(a)*fudge);
  300.       l_orbit = 0;
  301.       initorbitlong[0] = initorbitlong[1] = initorbitlong[2] = 0;
  302.    }
  303.    else if (fractype == INVERSEJULIA)
  304.    {
  305.       LCMPLX Sqrt;
  306.  
  307.       CxLong = (long)(param[0] * fudge);
  308.       CyLong = (long)(param[1] * fudge);
  309.  
  310.       mxhits    = (int) param[2];
  311.       run_length = (int) param[3];
  312.       if (mxhits == 0)
  313.       mxhits = 1;
  314.       else if (mxhits >= colors)
  315.       mxhits = colors - 1;
  316.  
  317.       setup_convert_to_screen(&cvt);
  318.       /* Note: using bitshift of 21 for affine, 24 otherwise */
  319.  
  320.       lcvt.a = (long)(cvt.a * (1L << 21));
  321.       lcvt.b = (long)(cvt.b * (1L << 21));
  322.       lcvt.c = (long)(cvt.c * (1L << 21));
  323.       lcvt.d = (long)(cvt.d * (1L << 21));
  324.       lcvt.e = (long)(cvt.e * (1L << 21));
  325.       lcvt.f = (long)(cvt.f * (1L << 21));
  326.  
  327.       Sqrt = ComplexSqrtLong(fudge - 4 * CxLong, -4 * CyLong);
  328.  
  329.       switch (major_method) {
  330.      case breadth_first:
  331.         if (Init_Queue((long)32*1024) == 0)
  332.         { /* can't get queue memory: fall back to random walk */
  333.            stopmsg(20, NoQueue);
  334.            major_method = random_walk;
  335.            goto lrwalk;
  336.         }
  337.         EnQueueLong((fudge + Sqrt.x) / 2,  Sqrt.y / 2);
  338.         EnQueueLong((fudge - Sqrt.x) / 2, -Sqrt.y / 2);
  339.         break;
  340.      case depth_first:
  341.         if (Init_Queue((long)32*1024) == 0)
  342.         { /* can't get queue memory: fall back to random walk */
  343.            stopmsg(20, NoQueue);
  344.            major_method = random_walk;
  345.            goto lrwalk;
  346.         }
  347.         switch (minor_method) {
  348.            case left_first:
  349.           PushLong((fudge + Sqrt.x) / 2,  Sqrt.y / 2);
  350.           PushLong((fudge - Sqrt.x) / 2, -Sqrt.y / 2);
  351.           break;
  352.            case right_first:
  353.           PushLong((fudge - Sqrt.x) / 2, -Sqrt.y / 2);
  354.           PushLong((fudge + Sqrt.x) / 2,  Sqrt.y / 2);
  355.           break;
  356.         }
  357.         break;
  358.      case random_walk:
  359. lrwalk:
  360.         lnew.x = initorbitlong[0] = fudge + Sqrt.x / 2;
  361.         lnew.y = initorbitlong[1] =         Sqrt.y / 2;
  362.         break;
  363.      case random_run:
  364.         lnew.x = initorbitlong[0] = fudge + Sqrt.x / 2;
  365.         lnew.y = initorbitlong[1] =         Sqrt.y / 2;
  366.         break;
  367.       }
  368.    }
  369.    else
  370.    {
  371.       l_dt = (long)(param[0]*fudge);
  372.       l_a =  (long)(param[1]*fudge);
  373.       l_b =  (long)(param[2]*fudge);
  374.       l_c =  (long)(param[3]*fudge);
  375.    }
  376.  
  377.    /* precalculations for speed */
  378.    l_adt = multiply(l_a,l_dt,bitshift);
  379.    l_bdt = multiply(l_b,l_dt,bitshift);
  380.    l_cdt = multiply(l_c,l_dt,bitshift);
  381.    return(1);
  382. }
  383.  
  384. #define COSB   dx
  385. #define SINABC dy
  386.  
  387. int orbit3dfloatsetup()
  388. {
  389.    maxct = 0L;
  390.    connect = 1;
  391.    waste = 100;
  392.    projection = 2;
  393.  
  394.    if(fractype==FPHENON || fractype==FPPICKOVER || fractype==FPGINGERBREAD
  395.         || fractype == KAMFP || fractype == KAM3DFP
  396.         || fractype == FPHOPALONG || fractype == INVERSEJULIAFP)
  397.       connect=0;
  398.    if(fractype==FPLORENZ3D1 || fractype==FPLORENZ3D3 ||
  399.       fractype==FPLORENZ3D4)
  400.       waste = 750;
  401.    if(fractype==FPROSSLER)
  402.       waste = 500;
  403.    if(fractype==FPLORENZ)
  404.       projection = 1; /* plot x and z */
  405.  
  406.    initorbitfp[0] = 1;  /* initial conditions */
  407.    initorbitfp[1] = 1;
  408.    initorbitfp[2] = 1;
  409.    if(fractype==FPGINGERBREAD)
  410.    {
  411.       initorbitfp[0] = param[0];    /* initial conditions */
  412.       initorbitfp[1] = param[1];
  413.    }
  414.  
  415.    if(fractype==ICON || fractype==ICON3D)        /* DMF */
  416.    {
  417.       initorbitfp[0] = 0.01;  /* initial conditions */
  418.       initorbitfp[1] = 0.003;
  419.       connect = 0;
  420.       waste = 2000;
  421.    }
  422.  
  423.    if(fractype==FPHENON || fractype==FPPICKOVER)
  424.    {
  425.       a =  param[0];
  426.       b =  param[1];
  427.       c =  param[2];
  428.       d =  param[3];
  429.    }
  430.    else if(fractype==ICON || fractype==ICON3D)        /* DMF */
  431.    {
  432.       initorbitfp[0] = 0.01;  /* initial conditions */
  433.       initorbitfp[1] = 0.003;
  434.       connect = 0;
  435.       waste = 2000;
  436.       /* Initialize parameters */
  437.       a  =   param[0];
  438.       b  =   param[1];
  439.       c  =   param[2];
  440.       d  =   param[3];
  441.    }
  442.    else if(fractype==KAMFP || fractype==KAM3DFP)
  443.    {
  444.       maxct = 1L;                
  445.       a = param[0];          /* angle */
  446.       if(param[1] <= 0.0)
  447.      param[1] = .01;
  448.       b =  param[1];    /* stepsize */
  449.       c =  param[2];    /* stop */
  450.       t = (int)(l_d =  (long)(param[3]));     /* points per orbit */
  451.       sinx = sin(a);
  452.       cosx = cos(a);
  453.       orbit = 0;
  454.       initorbitfp[0] = initorbitfp[1] = initorbitfp[2] = 0;
  455.    }
  456.    else if(fractype==FPHOPALONG || fractype==FPMARTIN || fractype==CHIP
  457.         || fractype==QUADRUPTWO || fractype==THREEPLY)
  458.    {
  459.       initorbitfp[0] = 0;  /* initial conditions */
  460.       initorbitfp[1] = 0;
  461.       initorbitfp[2] = 0;
  462.       connect = 0;
  463.       a =  param[0];
  464.       b =  param[1];
  465.       c =  param[2];
  466.       d =  param[3];
  467.       if(fractype==THREEPLY)
  468.       {
  469.          COSB   = cos(b);
  470.          SINABC = sin(a+b+c);
  471.       } 
  472.    }
  473.    else if (fractype == INVERSEJULIAFP)
  474.    {
  475.       _CMPLX Sqrt;
  476.  
  477.       Cx = param[0];
  478.       Cy = param[1];
  479.  
  480.       mxhits    = (int) param[2];
  481.       run_length = (int) param[3];
  482.       if (mxhits == 0)
  483.       mxhits = 1;
  484.       else if (mxhits >= colors)
  485.       mxhits = colors - 1;
  486.  
  487.       setup_convert_to_screen(&cvt);
  488.  
  489.       /* find fixed points: guaranteed to be in the set */
  490.       Sqrt = ComplexSqrtFloat(1 - 4 * Cx, -4 * Cy);
  491.       switch ((int) major_method) {
  492.      case breadth_first:
  493.         if (Init_Queue((long)32*1024) == 0)
  494.         { /* can't get queue memory: fall back to random walk */
  495.            stopmsg(20, NoQueue);
  496.            major_method = random_walk;
  497.            goto rwalk;
  498.         }
  499.         EnQueueFloat((float)((1 + Sqrt.x) / 2), (float)(Sqrt.y / 2));
  500.         EnQueueFloat((float)((1 - Sqrt.x) / 2), (float)(-Sqrt.y / 2));
  501.         break;
  502.      case depth_first:            /* depth first (choose direction) */
  503.         if (Init_Queue((long)32*1024) == 0)
  504.         { /* can't get queue memory: fall back to random walk */
  505.            stopmsg(20, NoQueue);
  506.            major_method = random_walk;
  507.            goto rwalk;
  508.         }
  509.         switch (minor_method) {
  510.            case left_first:
  511.           PushFloat((float)((1 + Sqrt.x) / 2), (float)(Sqrt.y / 2));
  512.           PushFloat((float)((1 - Sqrt.x) / 2), (float)(-Sqrt.y / 2));
  513.           break;
  514.            case right_first:
  515.           PushFloat((float)((1 - Sqrt.x) / 2), (float)(-Sqrt.y / 2));
  516.           PushFloat((float)((1 + Sqrt.x) / 2), (float)(Sqrt.y / 2));
  517.           break;
  518.         }
  519.         break;
  520.      case random_walk:
  521. rwalk:
  522.         new.x = initorbitfp[0] = 1 + Sqrt.x / 2;
  523.         new.y = initorbitfp[1] = Sqrt.y / 2;
  524.         break;
  525.      case random_run:    /* random run, choose intervals */
  526.         major_method = random_run;
  527.         new.x = initorbitfp[0] = 1 + Sqrt.x / 2;
  528.         new.y = initorbitfp[1] = Sqrt.y / 2;
  529.         break;
  530.       }
  531.    }
  532.    else
  533.    {
  534.       dt = param[0];
  535.       a =  param[1];
  536.       b =  param[2];
  537.       c =  param[3];
  538.  
  539.    }
  540.  
  541.    /* precalculations for speed */
  542.    adt = a*dt;
  543.    bdt = b*dt;
  544.    cdt = c*dt;
  545.  
  546.    return(1);
  547. }
  548.  
  549. /******************************************************************/
  550. /*   orbit functions - put in fractalspecific[fractype].orbitcalc */
  551. /******************************************************************/
  552.  
  553. /* Julia sets by inverse iterations added by Juan J. Buhler 4/3/92 */
  554. /* Integrated with Lorenz by Tim Wegner 7/20/92 */
  555. /* Add Modified Inverse Iteration Method, 11/92 by Michael Snyder  */
  556.  
  557. int
  558. Minverse_julia_orbit()
  559. {
  560.    static int   random_dir = 0, random_len = 0;
  561.    int    newrow, newcol;
  562.    int    color,  leftright;
  563.  
  564.    /*
  565.     * First, compute new point
  566.     */
  567.    switch (major_method) {
  568.       case breadth_first:
  569.      if (QueueEmpty())
  570.         return -1;
  571.      new = DeQueueFloat();
  572.      break;
  573.       case depth_first:
  574.      if (QueueEmpty())
  575.         return -1;
  576.      new = PopFloat();
  577.      break;
  578.       case random_walk:
  579. #if 0
  580.      new = ComplexSqrtFloat(new.x - Cx, new.y - Cy);
  581.      if (RANDOM(2))
  582.      {
  583.         new.x = -new.x;
  584.         new.y = -new.y;
  585.      }
  586. #endif
  587.      break;
  588.       case random_run:
  589. #if 0
  590.      new = ComplexSqrtFloat(new.x - Cx, new.y - Cy);
  591.      if (random_len == 0)
  592.      {
  593.         random_len = RANDOM(run_length);
  594.         random_dir = RANDOM(3);
  595.      }
  596.      switch (random_dir) {
  597.         case 0:    /* left */
  598.            break;
  599.         case 1:    /* right */
  600.            new.x = -new.x;
  601.            new.y = -new.y;
  602.            break;
  603.         case 2:    /* random direction */
  604.            if (RANDOM(2))
  605.            {
  606.           new.x = -new.x;
  607.           new.y = -new.y;
  608.            }
  609.            break;
  610.      }
  611. #endif
  612.      break;
  613.    }
  614.  
  615.    /*
  616.     * Next, find its pixel position
  617.     */
  618.    newcol = (int)(cvt.a * new.x + cvt.b * new.y + cvt.e);
  619.    newrow = (int)(cvt.c * new.x + cvt.d * new.y + cvt.f);
  620.  
  621.    /*
  622.     * Now find the next point(s), and flip a coin to choose one.
  623.     */
  624.  
  625.    new       = ComplexSqrtFloat(new.x - Cx, new.y - Cy);
  626.    leftright = (RANDOM(2)) ? 1 : -1;
  627.  
  628.    if (newcol < 1 || newcol >= xdots || newrow < 1 || newrow >= ydots)
  629.    {
  630.       /*
  631.        * MIIM must skip points that are off the screen boundary,
  632.        * since it cannot read their color.
  633.        */
  634.       switch (major_method) {
  635.      case breadth_first:
  636.         EnQueueFloat((float)(leftright * new.x), (float)(leftright * new.y));
  637.         return 1;
  638.      case depth_first:
  639.         PushFloat   ((float)(leftright * new.x), (float)(leftright * new.y));
  640.         return 1;
  641.      case random_run:
  642.      case random_walk:
  643.         break;
  644.       }
  645.    }
  646.  
  647.    /*
  648.     * Read the pixel's color:
  649.     * For MIIM, if color >= mxhits, discard the point
  650.     *           else put the point's children onto the queue
  651.     */
  652.    color  = getcolor(newcol, newrow);
  653.    switch (major_method) {
  654.       case breadth_first:
  655.      if (color < mxhits)
  656.      {
  657.         putcolor(newcol, newrow, color+1);
  658. /*        new = ComplexSqrtFloat(new.x - Cx, new.y - Cy); */
  659.         EnQueueFloat( (float)new.x, (float)new.y);
  660.         EnQueueFloat((float)-new.x, (float)-new.y);
  661.      }
  662.      break;
  663.       case depth_first:
  664.      if (color < mxhits)
  665.      {
  666.         putcolor(newcol, newrow, color+1);
  667. /*        new = ComplexSqrtFloat(new.x - Cx, new.y - Cy); */
  668.         if (minor_method == left_first)
  669.         {
  670.            if (QueueFullAlmost())
  671.           PushFloat((float)-new.x, (float)-new.y);
  672.            else
  673.            {
  674.           PushFloat( (float)new.x, (float)new.y);
  675.           PushFloat((float)-new.x, (float)-new.y);
  676.            }
  677.         }
  678.         else
  679.         {
  680.            if (QueueFullAlmost())
  681.           PushFloat( (float)new.x, (float)new.y);
  682.            else
  683.            {
  684.           PushFloat((float)-new.x, (float)-new.y);
  685.           PushFloat( (float)new.x, (float)new.y);
  686.            }
  687.         }
  688.      }
  689.      break;
  690.       case random_run:
  691.      if (random_len-- == 0)
  692.      {
  693.         random_len = RANDOM(run_length);
  694.         random_dir = RANDOM(3);
  695.      }
  696.      switch (random_dir) {
  697.         case 0:    /* left */
  698.            break;
  699.         case 1:    /* right */
  700.            new.x = -new.x;
  701.            new.y = -new.y;
  702.            break;
  703.         case 2:    /* random direction */
  704.            new.x = leftright * new.x;
  705.            new.y = leftright * new.y;
  706.            break;
  707.      }
  708.      if (color < colors-1)
  709.         putcolor(newcol, newrow, color+1);
  710.      break;
  711.       case random_walk:
  712.      if (color < colors-1)
  713.         putcolor(newcol, newrow, color+1);
  714.      new.x = leftright * new.x;
  715.      new.y = leftright * new.y;
  716.      break;
  717.    }
  718.    return 1;
  719.  
  720. }
  721.  
  722. int
  723. Linverse_julia_orbit()
  724. {
  725.    static int   random_dir = 0, random_len = 0;
  726.    int    newrow, newcol;
  727.    int    color;
  728.  
  729.    /*
  730.     * First, compute new point
  731.     */
  732.    switch (major_method) {
  733.       case breadth_first:
  734.      if (QueueEmpty())
  735.         return -1;
  736.      lnew = DeQueueLong();
  737.      break;
  738.       case depth_first:
  739.      if (QueueEmpty())
  740.         return -1;
  741.      lnew = PopLong();
  742.      break;
  743.       case random_walk:
  744.      lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  745.      if (RANDOM(2))
  746.      {
  747.         lnew.x = -lnew.x;
  748.         lnew.y = -lnew.y;
  749.      }
  750.      break;
  751.       case random_run:
  752.      lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  753.      if (random_len == 0)
  754.      {
  755.         random_len = RANDOM(run_length);
  756.         random_dir = RANDOM(3);
  757.      }
  758.      switch (random_dir) {
  759.         case 0:    /* left */
  760.            break;
  761.         case 1:    /* right */
  762.            lnew.x = -lnew.x;
  763.            lnew.y = -lnew.y;
  764.            break;
  765.         case 2:    /* random direction */
  766.            if (RANDOM(2))
  767.            {
  768.           lnew.x = -lnew.x;
  769.           lnew.y = -lnew.y;
  770.            }
  771.            break;
  772.      }
  773.    }
  774.  
  775.    /*
  776.     * Next, find its pixel position
  777.     *
  778.     * Note: had to use a bitshift of 21 for this operation because
  779.     * otherwise the values of lcvt were truncated.  Used bitshift
  780.     * of 24 otherwise, for increased precision.
  781.     */
  782.    newcol = (int)((multiply(lcvt.a, lnew.x >> (bitshift - 21), 21) +
  783.          multiply(lcvt.b, lnew.y >> (bitshift - 21), 21) + lcvt.e) >> 21);
  784.    newrow = (int)((multiply(lcvt.c, lnew.x >> (bitshift - 21), 21) +
  785.          multiply(lcvt.d, lnew.y >> (bitshift - 21), 21) + lcvt.f) >> 21);
  786.  
  787.    if (newcol < 1 || newcol >= xdots || newrow < 1 || newrow >= ydots)
  788.    {
  789.       /*
  790.        * MIIM must skip points that are off the screen boundary,
  791.        * since it cannot read their color.
  792.        */
  793.       if (RANDOM(2))
  794.      color =  1;
  795.       else
  796.      color = -1;
  797.       switch (major_method) {
  798.      case breadth_first:
  799.         lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  800.         EnQueueLong(color * lnew.x, color * lnew.y);
  801.         break;
  802.      case depth_first:
  803.         lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  804.         PushLong(color * lnew.x, color * lnew.y);
  805.         break;
  806.      case random_run:
  807.         random_len--;
  808.      case random_walk:
  809.         break;
  810.       }
  811.       return 1;
  812.    }
  813.  
  814.    /*
  815.     * Read the pixel's color:
  816.     * For MIIM, if color >= mxhits, discard the point
  817.     *           else put the point's children onto the queue
  818.     */
  819.    color  = getcolor(newcol, newrow);
  820.    switch (major_method) {
  821.       case breadth_first:
  822.      if (color < mxhits)
  823.      {
  824.         putcolor(newcol, newrow, color+1);
  825.         lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  826.         EnQueueLong( lnew.x,  lnew.y);
  827.         EnQueueLong(-lnew.x, -lnew.y);
  828.      }
  829.      break;
  830.       case depth_first:
  831.      if (color < mxhits)
  832.      {
  833.         putcolor(newcol, newrow, color+1);
  834.         lnew = ComplexSqrtLong(lnew.x - CxLong, lnew.y - CyLong);
  835.         if (minor_method == left_first)
  836.         {
  837.            if (QueueFullAlmost())
  838.           PushLong(-lnew.x, -lnew.y);
  839.            else
  840.            {
  841.           PushLong( lnew.x,  lnew.y);
  842.           PushLong(-lnew.x, -lnew.y);
  843.            }
  844.         }
  845.         else
  846.         {
  847.            if (QueueFullAlmost())
  848.           PushLong( lnew.x,  lnew.y);
  849.            else
  850.            {
  851.           PushLong(-lnew.x, -lnew.y);
  852.           PushLong( lnew.x,  lnew.y);
  853.            }
  854.         }
  855.      }
  856.      break;
  857.       case random_run:
  858.      random_len--;
  859.      /* fall through */
  860.       case random_walk:
  861.      if (color < colors-1)
  862.         putcolor(newcol, newrow, color+1);
  863.      break;
  864.    }
  865.    return 1;
  866. }
  867.  
  868. #if 0
  869. int inverse_julia_orbit(double *x, double *y, double *z)
  870. {
  871.    double r, xo, yo;
  872.    int waste;
  873.    if(*z >= 1.0) /* this assumes intial value is 1.0!!! */
  874.    {
  875.       waste = 20; /* skip these points at first */
  876.       *z = 0;
  877.    }
  878.    else
  879.       waste = 1;
  880.    while(waste--)
  881.    {
  882.       xo = *x - param[0]; 
  883.       yo = *y - param[1];
  884.       r  = sqrt(xo*xo + yo*yo);
  885.       *x  = sqrt((r + xo)/2);
  886.       if (yo < 0)
  887.          *x = - *x;
  888.       *y = sqrt((r - xo)/2);
  889.       if(RANDOM(10) > 4)
  890.       {
  891.           *x = -(*x);
  892.           *y = -(*y);
  893.       }
  894.    }
  895.    return(0);
  896. }
  897. #endif
  898.  
  899. int lorenz3dlongorbit(long *l_x, long *l_y, long *l_z)
  900. {
  901.       l_xdt = multiply(*l_x,l_dt,bitshift);
  902.       l_ydt = multiply(*l_y,l_dt,bitshift);
  903.       l_dx  = -multiply(l_adt,*l_x,bitshift) + multiply(l_adt,*l_y,bitshift);
  904.       l_dy  =  multiply(l_bdt,*l_x,bitshift) -l_ydt -multiply(*l_z,l_xdt,bitshift);
  905.       l_dz  = -multiply(l_cdt,*l_z,bitshift) + multiply(*l_x,l_ydt,bitshift);
  906.  
  907.       *l_x += l_dx;
  908.       *l_y += l_dy;
  909.       *l_z += l_dz;
  910.       return(0);
  911. }
  912.  
  913. int lorenz3d1floatorbit(double *x, double *y, double *z)
  914. {
  915.       double norm;
  916.  
  917.       xdt = (*x)*dt;
  918.       ydt = (*y)*dt;
  919.       zdt = (*z)*dt;
  920.  
  921.       /* 1-lobe Lorenz */
  922.       norm = sqrt((*x)*(*x)+(*y)*(*y));
  923.       dx   = (-adt-dt)*(*x) + (adt-bdt)*(*y) + (dt-adt)*norm + ydt*(*z);
  924.       dy   = (bdt-adt)*(*x) - (adt+dt)*(*y) + (bdt+adt)*norm - xdt*(*z) -
  925.          norm*zdt;
  926.       dz   = (ydt/2) - cdt*(*z);
  927.  
  928.       *x += dx;
  929.       *y += dy;
  930.       *z += dz;
  931.       return(0);
  932. }
  933.  
  934. int lorenz3dfloatorbit(double *x, double *y, double *z)
  935. {
  936.       xdt = (*x)*dt;
  937.       ydt = (*y)*dt;
  938.       zdt = (*z)*dt;
  939.  
  940.       /* 2-lobe Lorenz (the original) */
  941.       dx  = -adt*(*x) + adt*(*y);
  942.       dy  =  bdt*(*x) - ydt - (*z)*xdt;
  943.       dz  = -cdt*(*z) + (*x)*ydt;
  944.  
  945.       *x += dx;
  946.       *y += dy;
  947.       *z += dz;
  948.       return(0);
  949. }
  950.  
  951. int lorenz3d3floatorbit(double *x, double *y, double *z)
  952. {
  953.       double norm;
  954.  
  955.       xdt = (*x)*dt;
  956.       ydt = (*y)*dt;
  957.       zdt = (*z)*dt;
  958.  
  959.       /* 3-lobe Lorenz */
  960.       norm = sqrt((*x)*(*x)+(*y)*(*y));
  961.       dx   = (-(adt+dt)*(*x) + (adt-bdt+zdt)*(*y)) / 3 +
  962.          ((dt-adt)*((*x)*(*x)-(*y)*(*y)) +
  963.          2*(bdt+adt-zdt)*(*x)*(*y))/(3*norm);
  964.       dy   = ((bdt-adt-zdt)*(*x) - (adt+dt)*(*y)) / 3 +
  965.          (2*(adt-dt)*(*x)*(*y) +
  966.          (bdt+adt-zdt)*((*x)*(*x)-(*y)*(*y)))/(3*norm);
  967.       dz   = (3*xdt*(*x)*(*y)-ydt*(*y)*(*y))/2 - cdt*(*z);
  968.  
  969.       *x += dx;
  970.       *y += dy;
  971.       *z += dz;
  972.       return(0);
  973. }
  974.  
  975. int lorenz3d4floatorbit(double *x, double *y, double *z)
  976. {
  977.       xdt = (*x)*dt;
  978.       ydt = (*y)*dt;
  979.       zdt = (*z)*dt;
  980.  
  981.       /* 4-lobe Lorenz */
  982.       dx   = (-adt*(*x)*(*x)*(*x) + (2*adt+bdt-zdt)*(*x)*(*x)*(*y) +
  983.          (adt-2*dt)*(*x)*(*y)*(*y) + (zdt-bdt)*(*y)*(*y)*(*y)) /
  984.          (2 * ((*x)*(*x)+(*y)*(*y)));
  985.       dy   = ((bdt-zdt)*(*x)*(*x)*(*x) + (adt-2*dt)*(*x)*(*x)*(*y) +
  986.          (-2*adt-bdt+zdt)*(*x)*(*y)*(*y) - adt*(*y)*(*y)*(*y)) /
  987.          (2 * ((*x)*(*x)+(*y)*(*y)));
  988.       dz   = (2*xdt*(*x)*(*x)*(*y) - 2*xdt*(*y)*(*y)*(*y) - cdt*(*z));
  989.  
  990.       *x += dx;
  991.       *y += dy;
  992.       *z += dz;
  993.       return(0);
  994. }
  995.  
  996. int henonfloatorbit(double *x, double *y, double *z)
  997. {
  998.       double newx,newy;
  999.       *z = *x; /* for warning only */
  1000.       newx  = 1 + *y - a*(*x)*(*x);
  1001.       newy  = b*(*x);
  1002.       *x = newx;
  1003.       *y = newy;
  1004.       return(0);
  1005. }
  1006.  
  1007. int henonlongorbit(long *l_x, long *l_y, long *l_z)
  1008. {
  1009.       long newx,newy;
  1010.       *l_z = *l_x; /* for warning only */
  1011.       newx = multiply(*l_x,*l_x,bitshift);
  1012.       newx = multiply(newx,l_a,bitshift);
  1013.       newx  = fudge + *l_y - newx;
  1014.       newy  = multiply(l_b,*l_x,bitshift);
  1015.       *l_x = newx;
  1016.       *l_y = newy;
  1017.       return(0);
  1018. }
  1019.  
  1020. int rosslerfloatorbit(double *x, double *y, double *z)
  1021. {
  1022.       xdt = (*x)*dt;
  1023.       ydt = (*y)*dt;
  1024.  
  1025.       dx = -ydt - (*z)*dt;
  1026.       dy = xdt + (*y)*adt;
  1027.       dz = bdt + (*z)*xdt - (*z)*cdt;
  1028.  
  1029.       *x += dx;
  1030.       *y += dy;
  1031.       *z += dz;
  1032.       return(0);
  1033. }
  1034.  
  1035. int pickoverfloatorbit(double *x, double *y, double *z)
  1036. {
  1037.       double newx,newy,newz;
  1038.       newx = sin(a*(*y)) - (*z)*cos(b*(*x));
  1039.       newy = (*z)*sin(c*(*x)) - cos(d*(*y));
  1040.       newz = sin(*x);
  1041.       *x = newx;
  1042.       *y = newy;
  1043.       *z = newz;
  1044.       return(0);
  1045. }
  1046. /* page 149 "Science of Fractal Images" */
  1047. int gingerbreadfloatorbit(double *x, double *y, double *z)
  1048. {
  1049.       double newx;
  1050.       *z = *x; /* for warning only */
  1051.       newx = 1 - (*y) + fabs(*x);
  1052.       *y = *x;
  1053.       *x = newx;
  1054.       return(0);
  1055. }
  1056.  
  1057. int rosslerlongorbit(long *l_x, long *l_y, long *l_z)
  1058. {
  1059.       l_xdt = multiply(*l_x,l_dt,bitshift);
  1060.       l_ydt = multiply(*l_y,l_dt,bitshift);
  1061.  
  1062.       l_dx  = -l_ydt - multiply(*l_z,l_dt,bitshift);
  1063.       l_dy  =  l_xdt + multiply(*l_y,l_adt,bitshift);
  1064.       l_dz  =  l_bdt + multiply(*l_z,l_xdt,bitshift)
  1065.              - multiply(*l_z,l_cdt,bitshift);
  1066.  
  1067.       *l_x += l_dx;
  1068.       *l_y += l_dy;
  1069.       *l_z += l_dz;
  1070.  
  1071.       return(0);
  1072. }
  1073.  
  1074. /* OSTEP  = Orbit Step (and inner orbit value) */
  1075. /* NTURNS = Outside Orbit */
  1076. /* TURN2  = Points per orbit */
  1077. /* a      = Angle */
  1078.  
  1079.  
  1080. int kamtorusfloatorbit(double *r, double *s, double *z)
  1081. {
  1082.    double srr;
  1083.    if(t++ >= l_d)
  1084.    {
  1085.       orbit += b;
  1086.       (*r) = (*s) = orbit/3;
  1087.       t = 0;
  1088.       *z = orbit;
  1089.       if(orbit > c)
  1090.      return(1);
  1091.    }
  1092.    srr = (*s)-(*r)*(*r);
  1093.    (*s)=(*r)*sinx+srr*cosx;
  1094.    (*r)=(*r)*cosx-srr*sinx;
  1095.    return(0);
  1096. }
  1097.  
  1098. int kamtoruslongorbit(long *r, long *s, long *z)
  1099. {
  1100.    long srr;
  1101.    if(t++ >= l_d)
  1102.    {
  1103.       l_orbit += l_b;
  1104.       (*r) = (*s) = l_orbit/3;
  1105.       t = 0;
  1106.       *z = l_orbit;
  1107.       if(l_orbit > l_c)
  1108.      return(1);
  1109.    }
  1110.    srr = (*s)-multiply((*r),(*r),bitshift);
  1111.    (*s)=multiply((*r),l_sinx,bitshift)+multiply(srr,l_cosx,bitshift);
  1112.    (*r)=multiply((*r),l_cosx,bitshift)-multiply(srr,l_sinx,bitshift);
  1113.    return(0);
  1114. }
  1115.  
  1116. int hopalong2dfloatorbit(double *x, double *y, double *z)
  1117. {
  1118.    double tmp;
  1119.    *z = *x; /* for warning only */
  1120.    tmp = *y - sign(*x)*sqrt(fabs(b*(*x)-c));
  1121.    *y = a - *x;
  1122.    *x = tmp;
  1123.    return(0);
  1124. }
  1125.  
  1126. /* from Michael Peters and HOP */
  1127. int chip2dfloatorbit(double *x, double *y, double *z)
  1128. {
  1129.    double tmp;
  1130.    *z = *x; /* for warning only */
  1131.    tmp = *y - sign(*x) * cos(sqr(log(fabs(b*(*x)-c))))
  1132.                        * atan(sqr(log(fabs(c*(*x)-b))));
  1133.    *y = a - *x;
  1134.    *x = tmp;
  1135.    return(0);
  1136. }
  1137.  
  1138. /* from Michael Peters and HOP */
  1139. int quadruptwo2dfloatorbit(double *x, double *y, double *z)
  1140. {
  1141.    double tmp;
  1142.    *z = *x; /* for warning only */
  1143.    tmp = *y - sign(*x) * sin(log(fabs(b*(*x)-c)))   
  1144.                        * atan(sqr(log(fabs(c*(*x)-b))));
  1145.    *y = a - *x;
  1146.    *x = tmp;
  1147.    return(0);
  1148. }
  1149.  
  1150. /* from Michael Peters and HOP */
  1151. int threeply2dfloatorbit(double *x, double *y, double *z)
  1152. {
  1153.    double tmp;
  1154.    *z = *x; /* for warning only */
  1155.    tmp = *y - sign(*x)*(fabs(sin(*x)*COSB+c-(*x)*SINABC));
  1156.    *y = a - *x;
  1157.    *x = tmp;
  1158.    return(0);
  1159. }
  1160.  
  1161. int martin2dfloatorbit(double *x, double *y, double *z)
  1162. {
  1163.    double tmp;
  1164.    *z = *x;  /* for warning only */
  1165.    tmp = *y - sin(*x);
  1166.    *y = a - *x;
  1167.    *x = tmp;
  1168.    return(0);
  1169. }
  1170.  
  1171. int mandelcloudfloat(double *x, double *y, double *z)
  1172. {
  1173.     double newx,newy,x2,y2;
  1174.     newx = *z; /* for warning only */
  1175.     x2 = (*x)*(*x);
  1176.     y2 = (*y)*(*y);
  1177.     if (x2+y2>2) return 1;
  1178.     newx = x2-y2+a;
  1179.     newy = 2*(*x)*(*y)+b;
  1180.     *x = newx;
  1181.     *y = newy;
  1182.     return(0);
  1183. }
  1184.  
  1185. int dynamfloat(double *x, double *y, double *z)
  1186. {
  1187.       _CMPLX cp,tmp;
  1188.       double newx,newy;
  1189.       newx = *z; /* for warning only */
  1190.       cp.x = b* *x;
  1191.       cp.y = 0;
  1192.       CMPLXtrig0(cp, tmp);
  1193.       newy = *y + dt*sin(*x + a*tmp.x);
  1194.       if (euler) {
  1195.       *y = newy;
  1196.       }
  1197.  
  1198.       cp.x = b* *y;
  1199.       cp.y = 0;
  1200.       CMPLXtrig0(cp, tmp);
  1201.       newx = *x - dt*sin(*y + a*tmp.x);
  1202.       *x = newx;
  1203.       *y = newy;
  1204.       return(0);
  1205. }
  1206.  
  1207. /* dmf */
  1208. #undef  LAMBDA
  1209. #define LAMBDA  param[0]
  1210. #define ALPHA   param[1]
  1211. #define BETA    param[2]
  1212. #define GAMMA   param[3]
  1213. #define OMEGA   param[4]
  1214. #define DEGREE  param[5]
  1215.  
  1216. int iconfloatorbit(double *x, double *y, double *z)
  1217. {
  1218.  
  1219.     double oldx, oldy, zzbar, zreal, zimag, za, zb, zn, p;
  1220.     unsigned char i;
  1221.  
  1222.     oldx = *x;
  1223.     oldy = *y;
  1224.  
  1225.     zzbar = oldx * oldx + oldy * oldy;
  1226.     zreal = oldx;
  1227.     zimag = oldy;
  1228.  
  1229.     for(i=1; i <= DEGREE-2; i++) {
  1230.         za = zreal * oldx - zimag * oldy;
  1231.         zb = zimag * oldx + zreal * oldy;
  1232.         zreal = za;
  1233.         zimag = zb;
  1234.     }
  1235.     zn = oldx * zreal - oldy * zimag;
  1236.     p = LAMBDA + ALPHA * zzbar + BETA * zn;
  1237.     *x = p * oldx + GAMMA * zreal - OMEGA * oldy;
  1238.     *y = p * oldy - GAMMA * zimag + OMEGA * oldx;
  1239.  
  1240.     *z = zzbar; 
  1241.     return(0);
  1242. }
  1243. #ifdef LAMBDA  /* Tim says this will make me a "good citizen" */
  1244. #undef LAMBDA  /* Yeah, but you were bad, Dan - LAMBDA was already */
  1245. #undef ALPHA   /* defined! <grin!> TW */
  1246. #undef BETA
  1247. #undef GAMMA
  1248. #endif
  1249.  
  1250. /**********************************************************************/
  1251. /*   Main fractal engines - put in fractalspecific[fractype].calctype */
  1252. /**********************************************************************/
  1253.  
  1254. int inverse_julia_per_image()
  1255. {
  1256.    if (resuming)            /* can't resume */
  1257.       return -1;
  1258.    coloriter = 0;
  1259.  
  1260.    if(maxit > 0x1fffffL)
  1261.       maxct = 0x7fffffffL;
  1262.    else
  1263.       maxct = maxit*1024L;
  1264.    while (coloriter++ <= maxct)       /* generate points */
  1265.    {
  1266.       if (keypressed())
  1267.       {
  1268.      Free_Queue();
  1269.      return -1;
  1270.       }
  1271.       curfractalspecific->orbitcalc();
  1272.       old = new;
  1273.    }
  1274.    Free_Queue();
  1275.    return 0;
  1276. }
  1277.  
  1278. int orbit2dfloat()
  1279. {
  1280.    FILE *fp;
  1281.    double *soundvar;
  1282.    double x,y,z;
  1283.    int color,col,row;
  1284.    int count;
  1285.    int oldrow, oldcol;
  1286.    double *p0,*p1,*p2;
  1287.    struct affine cvt;
  1288.    int ret;
  1289.    soundvar = p0 = p1 = p2 = NULL;
  1290.  
  1291.    fp = open_orbitsave();
  1292.    /* setup affine screen coord conversion */
  1293.    setup_convert_to_screen(&cvt);
  1294.  
  1295.    /* set up projection scheme */
  1296.    if(projection==0)
  1297.    {
  1298.       p0 = &z;
  1299.       p1 = &x;
  1300.       p2 = &y;
  1301.    }
  1302.    else if(projection==1)
  1303.    {
  1304.       p0 = &x;
  1305.       p1 = &z;
  1306.       p2 = &y;
  1307.    }
  1308.    else if(projection==2)
  1309.    {
  1310.       p0 = &x;
  1311.       p1 = &y;
  1312.       p2 = &z;
  1313.    }
  1314.    if(soundflag==1)
  1315.       soundvar = &x;
  1316.    else if(soundflag==2)
  1317.       soundvar = &y;
  1318.    else if(soundflag==3)
  1319.       soundvar = &z;
  1320.  
  1321.    if(inside > 0)
  1322.       color = inside;
  1323.    if(color >= colors)
  1324.       color = 1;
  1325.    oldcol = oldrow = -1;
  1326.    x = initorbitfp[0];
  1327.    y = initorbitfp[1];
  1328.    z = initorbitfp[2];
  1329.    coloriter = 0L;
  1330.    count = ret = 0;
  1331.    if(maxit > 0x1fffffL || maxct)
  1332.       maxct = 0x7fffffffL;
  1333.    else
  1334.       maxct = maxit*1024L;
  1335.  
  1336.    if (resuming)
  1337.    {
  1338.       start_resume();
  1339.       get_resume(sizeof(count),&count,sizeof(color),&color,
  1340.           sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  1341.           sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,sizeof(t),&t,
  1342.           sizeof(orbit),&orbit,sizeof(coloriter),&coloriter,
  1343.           0);
  1344.       end_resume();
  1345.    }
  1346.  
  1347.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  1348.    {
  1349.       if(keypressed())
  1350.       {
  1351.          nosnd();
  1352.          alloc_resume(100,1);
  1353.          put_resume(sizeof(count),&count,sizeof(color),&color,
  1354.              sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  1355.              sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,sizeof(t),&t,
  1356.              sizeof(orbit),&orbit,sizeof(coloriter),&coloriter,
  1357.              0);
  1358.          ret = -1;
  1359.          break;
  1360.       }
  1361.       if (++count > 1000)
  1362.       {        /* time to switch colors? */
  1363.          count = 0;
  1364.          if (++color >= colors)   /* another color to switch to? */
  1365.         color = 1;  /* (don't use the background color) */
  1366.       }
  1367.  
  1368.       col = (int)(cvt.a*x + cvt.b*y + cvt.e);
  1369.       row = (int)(cvt.c*x + cvt.d*y + cvt.f);
  1370.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  1371.       {
  1372.          if (soundflag > 0)
  1373.             snd((int)(*soundvar*100+basehertz));
  1374.          if(fractype!=ICON)
  1375.          {
  1376.          if(oldcol != -1 && connect)
  1377.             draw_line(col,row,oldcol,oldrow,color%colors);
  1378.             else
  1379.             (*plot)(col,row,color%colors);
  1380.          } else {
  1381.             /* should this be using plothist()? */
  1382.             color = getcolor(col,row)+1;
  1383.             if( color < colors ) /* color sticks on last value */
  1384.                (*plot)(col,row,color);
  1385.  
  1386.          }
  1387.  
  1388.          oldcol = col;
  1389.          oldrow = row;
  1390.       }
  1391.       else if((long)abs(row) + (long)abs(col) > BAD_PIXEL) /* sanity check */
  1392.          return(ret);
  1393.       else   
  1394.          oldrow = oldcol = -1;
  1395.  
  1396.       if(FORBIT(p0, p1, p2))
  1397.          break;
  1398.       if(fp)
  1399.          fprintf(fp,orbitsave_format,*p0,*p1,0.0);
  1400.    }
  1401.    if(fp)
  1402.       fclose(fp);
  1403.    return(ret);
  1404. }
  1405.  
  1406. int orbit2dlong()
  1407. {
  1408.    FILE *fp;
  1409.    long *soundvar;
  1410.    long x,y,z;
  1411.    int color,col,row;
  1412.    int count;
  1413.    int oldrow, oldcol;
  1414.    long *p0,*p1,*p2;
  1415.    struct l_affine cvt;
  1416.    int ret,start;
  1417.    start = 1;
  1418.    soundvar = p0 = p1 = p2 = NULL;
  1419.    fp = open_orbitsave();
  1420.  
  1421.    /* setup affine screen coord conversion */
  1422.    l_setup_convert_to_screen(&cvt);
  1423.  
  1424.    /* set up projection scheme */
  1425.    if(projection==0)
  1426.    {
  1427.       p0 = &z;
  1428.       p1 = &x;
  1429.       p2 = &y;
  1430.    }
  1431.    else if(projection==1)
  1432.    {
  1433.       p0 = &x;
  1434.       p1 = &z;
  1435.       p2 = &y;
  1436.    }
  1437.    else if(projection==2)
  1438.    {
  1439.       p0 = &x;
  1440.       p1 = &y;
  1441.       p2 = &z;
  1442.    }
  1443.    if(soundflag==1)
  1444.       soundvar = &x;
  1445.    else if(soundflag==2)
  1446.       soundvar = &y;
  1447.    else if(soundflag==3)
  1448.       soundvar = &z;
  1449.    if(inside > 0)
  1450.       color = inside;
  1451.    if(color >= colors)
  1452.       color = 1;
  1453.    oldcol = oldrow = -1;
  1454.    x = initorbitlong[0];
  1455.    y = initorbitlong[1];
  1456.    z = initorbitlong[2];
  1457.    count = ret = 0;
  1458.    if(maxit > 0x1fffffL || maxct)
  1459.       maxct = 0x7fffffffL;
  1460.    else
  1461.       maxct = maxit*1024L;
  1462.    coloriter = 0L;
  1463.  
  1464.    if (resuming)
  1465.    {
  1466.       start_resume();
  1467.       get_resume(sizeof(count),&count,sizeof(color),&color,
  1468.           sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  1469.           sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,sizeof(t),&t,
  1470.           sizeof(l_orbit),&l_orbit,sizeof(coloriter),&coloriter,
  1471.           0);
  1472.       end_resume();
  1473.    }
  1474.  
  1475.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  1476.    {
  1477.       if(keypressed())
  1478.       {
  1479.          nosnd();
  1480.          alloc_resume(100,1);
  1481.          put_resume(sizeof(count),&count,sizeof(color),&color,
  1482.          sizeof(oldrow),&oldrow,sizeof(oldcol),&oldcol,
  1483.              sizeof(x),&x,sizeof(y),&y,sizeof(z),&z,sizeof(t),&t,
  1484.              sizeof(l_orbit),&l_orbit,sizeof(coloriter),&coloriter,
  1485.              0);
  1486.          ret = -1;
  1487.          break;
  1488.       }
  1489.       if (++count > 1000)
  1490.       {        /* time to switch colors? */
  1491.          count = 0;
  1492.          if (++color >= colors)   /* another color to switch to? */
  1493.             color = 1;  /* (don't use the background color) */
  1494.       }
  1495.  
  1496.       col = (int)((multiply(cvt.a,x,bitshift) + multiply(cvt.b,y,bitshift) + cvt.e) >> bitshift);
  1497.       row = (int)((multiply(cvt.c,x,bitshift) + multiply(cvt.d,y,bitshift) + cvt.f) >> bitshift);
  1498.       if(overflow)
  1499.       {
  1500.          overflow = 0;
  1501.          return(ret);
  1502.       }
  1503.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  1504.       {
  1505.          if (soundflag > 0)
  1506.          {
  1507.             double yy;
  1508.             yy = *soundvar;
  1509.             yy = yy/fudge;
  1510.             snd((int)(yy*100+basehertz));
  1511.          }
  1512.          if(oldcol != -1 && connect)
  1513.             draw_line(col,row,oldcol,oldrow,color%colors);
  1514.          else if(!start)
  1515.             (*plot)(col,row,color%colors);
  1516.          oldcol = col;
  1517.          oldrow = row;
  1518.          start = 0;
  1519.       }
  1520.       else if((long)abs(row) + (long)abs(col) > BAD_PIXEL) /* sanity check */
  1521.          return(ret);
  1522.       else   
  1523.      oldrow = oldcol = -1;
  1524.  
  1525.       /* Calculate the next point */
  1526.       if(LORBIT(p0, p1, p2))
  1527.          break;
  1528.       if(fp)
  1529.          fprintf(fp,orbitsave_format,(double)*p0/fudge,(double)*p1/fudge,0.0);
  1530.    }
  1531.    if(fp)
  1532.       fclose(fp);
  1533.    return(ret);
  1534. }
  1535.  
  1536. static int orbit3dlongcalc(void)
  1537. {
  1538.    FILE *fp;
  1539.    unsigned long count;
  1540.    int oldcol,oldrow;
  1541.    int oldcol1,oldrow1;
  1542.    struct long3dvtinf inf;
  1543.    int color;
  1544.    int ret;
  1545.  
  1546.    /* setup affine screen coord conversion */
  1547.    l_setup_convert_to_screen(&inf.cvt);
  1548.  
  1549.    oldcol1 = oldrow1 = oldcol = oldrow = -1;
  1550.    color = 2;
  1551.    if(color >= colors)
  1552.       color = 1;
  1553.  
  1554.    inf.orbit[0] = initorbitlong[0];
  1555.    inf.orbit[1] = initorbitlong[1];
  1556.    inf.orbit[2] = initorbitlong[2];
  1557.  
  1558.    if(diskvideo)                /* this would KILL a disk drive! */
  1559.       notdiskmsg();
  1560.  
  1561.    fp = open_orbitsave();
  1562.  
  1563.    count = ret = 0;
  1564.    if(maxit > 0x1fffffL || maxct)
  1565.       maxct = 0x7fffffffL;
  1566.    else
  1567.       maxct = maxit*1024L;
  1568.    coloriter = 0L;
  1569.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  1570.    {
  1571.       /* calc goes here */
  1572.       if (++count > 1000)
  1573.       {        /* time to switch colors? */
  1574.          count = 0;
  1575.          if (++color >= colors)   /* another color to switch to? */
  1576.             color = 1;        /* (don't use the background color) */
  1577.       }
  1578.       if(keypressed())
  1579.       {
  1580.          nosnd();
  1581.          ret = -1;
  1582.          break;
  1583.       }
  1584.  
  1585.       LORBIT(&inf.orbit[0],&inf.orbit[1],&inf.orbit[2]);
  1586.       if(fp)
  1587.          fprintf(fp,orbitsave_format,(double)inf.orbit[0]/fudge,(double)inf.orbit[1]/fudge,(double)inf.orbit[2]/fudge);
  1588.       if (long3dviewtransf(&inf))
  1589.       {
  1590.          /* plot if inside window */
  1591.          if (inf.col >= 0)
  1592.          {
  1593.             if(realtime)
  1594.                whichimage=1;
  1595.             if (soundflag > 0)
  1596.             {
  1597.                double yy;
  1598.                yy = inf.viewvect[soundflag-1];
  1599.                yy = yy/fudge;
  1600.                snd((int)(yy*100+basehertz));
  1601.             }
  1602.             if(oldcol != -1 && connect)
  1603.                draw_line(inf.col,inf.row,oldcol,oldrow,color%colors);
  1604.             else
  1605.                (*plot)(inf.col,inf.row,color%colors);
  1606.          }
  1607.          else if (inf.col == -2)
  1608.             return(ret);
  1609.          oldcol = inf.col;
  1610.          oldrow = inf.row;
  1611.          if(realtime)
  1612.          {
  1613.             whichimage=2;
  1614.             /* plot if inside window */
  1615.             if (inf.col1 >= 0)
  1616.             {
  1617.                if(oldcol1 != -1 && connect)
  1618.                   draw_line(inf.col1,inf.row1,oldcol1,oldrow1,color%colors);
  1619.                else
  1620.                   (*plot)(inf.col1,inf.row1,color%colors);
  1621.             }
  1622.             else if (inf.col1 == -2)
  1623.                return(ret);
  1624.             oldcol1 = inf.col1;
  1625.             oldrow1 = inf.row1;
  1626.          }
  1627.       }
  1628.    }
  1629.    if(fp)
  1630.       fclose(fp);
  1631.    return(ret);
  1632. }
  1633.  
  1634.  
  1635. static int orbit3dfloatcalc(void)
  1636. {
  1637.    FILE *fp;
  1638.    unsigned long count;
  1639.    int oldcol,oldrow;
  1640.    int oldcol1,oldrow1;
  1641.    int color;
  1642.    int ret;
  1643.    struct float3dvtinf inf;
  1644.  
  1645.    /* setup affine screen coord conversion */
  1646.    setup_convert_to_screen(&inf.cvt);
  1647.  
  1648.    oldcol = oldrow = -1;
  1649.    oldcol1 = oldrow1 = -1;
  1650.    color = 2;
  1651.    if(color >= colors)
  1652.       color = 1;
  1653.    inf.orbit[0] = initorbitfp[0];
  1654.    inf.orbit[1] = initorbitfp[1];
  1655.    inf.orbit[2] = initorbitfp[2];
  1656.  
  1657.    if(diskvideo)                /* this would KILL a disk drive! */
  1658.       notdiskmsg();
  1659.  
  1660.    fp = open_orbitsave();
  1661.  
  1662.    ret = 0;
  1663.    if(maxit > 0x1fffffL || maxct)
  1664.       maxct = 0x7fffffffL;
  1665.    else
  1666.       maxct = maxit*1024L;
  1667.    count = coloriter = 0L;
  1668.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  1669.    {
  1670.       /* calc goes here */
  1671.       if (++count > 1000)
  1672.       {        /* time to switch colors? */
  1673.          count = 0;
  1674.          if (++color >= colors)   /* another color to switch to? */
  1675.             color = 1;        /* (don't use the background color) */
  1676.       }
  1677.  
  1678.       if(keypressed())
  1679.       {
  1680.          nosnd();
  1681.          ret = -1;
  1682.          break;
  1683.       }
  1684.  
  1685.       FORBIT(&inf.orbit[0],&inf.orbit[1],&inf.orbit[2]);
  1686.       if(fp)
  1687.          fprintf(fp,orbitsave_format,inf.orbit[0],inf.orbit[1],inf.orbit[2]);
  1688.       if (float3dviewtransf(&inf))
  1689.       {
  1690.          /* plot if inside window */
  1691.          if (inf.col >= 0)
  1692.          {
  1693.         if(realtime)
  1694.                whichimage=1;
  1695.             if (soundflag > 0)
  1696.                snd((int)(inf.viewvect[soundflag-1]*100+basehertz));
  1697.             if(oldcol != -1 && connect)
  1698.                draw_line(inf.col,inf.row,oldcol,oldrow,color%colors);
  1699.             else
  1700.                (*plot)(inf.col,inf.row,color%colors);
  1701.          }
  1702.          else if (inf.col == -2)
  1703.             return(ret);
  1704.          oldcol = inf.col;
  1705.          oldrow = inf.row;
  1706.          if(realtime)
  1707.          {
  1708.             whichimage=2;
  1709.             /* plot if inside window */
  1710.             if (inf.col1 >= 0)
  1711.             {
  1712.                if(oldcol1 != -1 && connect)
  1713.                   draw_line(inf.col1,inf.row1,oldcol1,oldrow1,color%colors);
  1714.                else
  1715.                   (*plot)(inf.col1,inf.row1,color%colors);
  1716.             }
  1717.             else if (inf.col1 == -2)
  1718.                return(ret);
  1719.             oldcol1 = inf.col1;
  1720.             oldrow1 = inf.row1;
  1721.          }
  1722.       }
  1723.    }
  1724.    if(fp)
  1725.       fclose(fp);
  1726.    return(ret);
  1727. }
  1728.  
  1729. int dynam2dfloatsetup()
  1730. {
  1731.    connect = 0;
  1732.    euler = 0;
  1733.    d = param[0]; /* number of intervals */
  1734.    if (d<0) {
  1735.       d = -d;
  1736.       connect = 1;
  1737.    } 
  1738.    else if (d==0) {
  1739.       d = 1;
  1740.    }
  1741.    if (fractype==DYNAMICFP) {
  1742.        a = param[2]; /* parameter */
  1743.        b = param[3]; /* parameter */
  1744.        dt = param[1]; /* step size */
  1745.        if (dt<0) {
  1746.       dt = -dt;
  1747.       euler = 1;
  1748.        }
  1749.        if (dt==0) dt = 0.01;
  1750.    }
  1751.    if (outside == -5) {
  1752.        plot = plothist;
  1753.    }
  1754.    return(1);
  1755. }
  1756.  
  1757. /*
  1758.  * This is the routine called to perform a time-discrete dynamical
  1759.  * system image.
  1760.  * The starting positions are taken by stepping across the image in steps
  1761.  * of parameter1 pixels.  maxit differential equation steps are taken, with
  1762.  * a step size of parameter2.
  1763.  */
  1764. int dynam2dfloat()
  1765. {
  1766.    FILE *fp;
  1767.    double *soundvar = NULL;
  1768.    double x,y,z;
  1769.    int color,col,row;
  1770.    long count;
  1771.    int oldrow, oldcol;
  1772.    double *p0,*p1;
  1773.    struct affine cvt;
  1774.    int ret;
  1775.    int xstep, ystep; /* The starting position step number */
  1776.    double xpixel, ypixel; /* Our pixel position on the screen */
  1777.  
  1778.    fp = open_orbitsave();
  1779.    /* setup affine screen coord conversion */
  1780.    setup_convert_to_screen(&cvt);
  1781.  
  1782.    p0 = &x;
  1783.    p1 = &y;
  1784.  
  1785.  
  1786.    if(soundflag==1)
  1787.       soundvar = &x;
  1788.    else if(soundflag==2)
  1789.       soundvar = &y;
  1790.    else if(soundflag==3)
  1791.       soundvar = &z;
  1792.  
  1793.    count = 0;
  1794.    if(inside > 0)
  1795.       color = inside;
  1796.    if(color >= colors)
  1797.       color = 1;
  1798.    oldcol = oldrow = -1;
  1799.  
  1800.    xstep = -1;
  1801.    ystep = 0;
  1802.  
  1803.    if (resuming) {
  1804.        start_resume();
  1805.        get_resume(sizeof(count),&count, sizeof(color),&color,
  1806.          sizeof(oldrow),&oldrow, sizeof(oldcol),&oldcol,
  1807.          sizeof(x),&x, sizeof(y), &y, sizeof(xstep), &xstep,
  1808.          sizeof(ystep), &ystep, 0);
  1809.        end_resume();
  1810.    }
  1811.  
  1812.    ret = 0;
  1813.    for(;;)
  1814.    {
  1815.       if(keypressed())
  1816.       {
  1817.          nosnd();
  1818.          alloc_resume(100,1);
  1819.          put_resume(sizeof(count),&count, sizeof(color),&color,
  1820.              sizeof(oldrow),&oldrow, sizeof(oldcol),&oldcol,
  1821.              sizeof(x),&x, sizeof(y), &y, sizeof(xstep), &xstep,
  1822.              sizeof(ystep), &ystep, 0);
  1823.          ret = -1;
  1824.          break;
  1825.       }
  1826.  
  1827.       xstep ++;
  1828.       if (xstep>=d) {
  1829.       xstep = 0;
  1830.       ystep ++;
  1831.       if (ystep>d) {
  1832.           nosnd();
  1833.           ret = -1;
  1834.           break;
  1835.       }
  1836.       }
  1837.  
  1838.       xpixel = dxsize*(xstep+.5)/d;
  1839.       ypixel = dysize*(ystep+.5)/d;
  1840.       x = (double)((xxmin+delxx*xpixel) + (delxx2*ypixel));
  1841.       y = (double)((yymax-delyy*ypixel) + (-delyy2*xpixel));
  1842.       if (fractype==MANDELCLOUD) {
  1843.       a = x;
  1844.       b = y;
  1845.       }
  1846.       oldcol = -1;
  1847.  
  1848.       if (++color >= colors)   /* another color to switch to? */
  1849.       color = 1;    /* (don't use the background color) */
  1850.  
  1851.       for (count=0;count<maxit;count++) {
  1852.  
  1853.           if (count % 2048L == 0)
  1854.              if (keypressed())
  1855.                  break;
  1856.  
  1857.       col = (int)(cvt.a*x + cvt.b*y + cvt.e);
  1858.       row = (int)(cvt.c*x + cvt.d*y + cvt.f);
  1859.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  1860.       {
  1861.          if (soundflag > 0)
  1862.            snd((int)(*soundvar*100+basehertz));
  1863.  
  1864.          if (count>=orbit_delay) {
  1865.          if(oldcol != -1 && connect)
  1866.             draw_line(col,row,oldcol,oldrow,color%colors);
  1867.          else if(count > 0 || fractype != MANDELCLOUD)
  1868.             (*plot)(col,row,color%colors);
  1869.          }
  1870.          oldcol = col;
  1871.          oldrow = row;
  1872.       }
  1873.       else if((long)abs(row) + (long)abs(col) > BAD_PIXEL) /* sanity check */
  1874.             return(ret);
  1875.       else
  1876.          oldrow = oldcol = -1;
  1877.  
  1878.       if(FORBIT(p0, p1, NULL))
  1879.          break;
  1880.       if(fp)
  1881.           fprintf(fp,orbitsave_format,*p0,*p1,0.0);
  1882.     }
  1883.    }
  1884.    if(fp)
  1885.       fclose(fp);
  1886.    return(ret);
  1887. }
  1888.  
  1889. /* this function's only purpose is to manage funnyglasses related */
  1890. /* stuff so the code is not duplicated for ifs3d() and lorenz3d() */
  1891. int funny_glasses_call(int (*calc)(void))
  1892. {
  1893.    int status;
  1894.    status = 0;
  1895.    if(glassestype)
  1896.       whichimage = 1;
  1897.    else
  1898.       whichimage = 0;
  1899.    plot_setup();
  1900.    plot = standardplot;
  1901.    status = calc();
  1902.    if(realtime && glassestype != 3)
  1903.    {
  1904.       realtime = 0;
  1905.       return(status);
  1906.    }
  1907.    if(glassestype && status == 0 && display3d)
  1908.    {
  1909.       if(glassestype==3) /* photographer's mode */
  1910.      if(active_system == 0) { /* dos version */
  1911.         int i;
  1912. static FCODE firstready[]={"\
  1913. First image (left eye) is ready.  Hit any key to see it,\n\
  1914. then hit <s> to save, hit any other key to create second image."};
  1915.         stopmsg(16,firstready);
  1916.         while ((i = getakey()) == 's' || i == 'S') {
  1917.            diskisactive = 1;
  1918.            savetodisk(savename);
  1919.            diskisactive = 0;
  1920.            }
  1921.         /* is there a better way to clear the screen in graphics mode? */
  1922.         setvideomode(videoentry.videomodeax,
  1923.         videoentry.videomodebx,
  1924.         videoentry.videomodecx,
  1925.         videoentry.videomodedx);
  1926.      }
  1927.      else {           /* Windows version */
  1928. static FCODE firstready2[]={"First (Left Eye) image is complete"};
  1929.         stopmsg(0,firstready2);
  1930.         clear_screen();
  1931.         }
  1932.       whichimage = 2;
  1933.       plot_setup();
  1934.       plot = standardplot;
  1935.       /* is there a better way to clear the graphics screen ? */
  1936.       if((status = calc()) != 0)
  1937.      return(status);
  1938.       if(glassestype==3) /* photographer's mode */
  1939.      if(active_system == 0) { /* dos version */
  1940. static FCODE secondready[]={"Second image (right eye) is ready"};
  1941.         stopmsg(16,secondready);
  1942.      }
  1943.    }
  1944.    return(status);
  1945. }
  1946.  
  1947. /* double version - mainly for testing */
  1948. static int ifs3dfloat(void)
  1949. {
  1950.    int color_method;
  1951.    FILE *fp;
  1952.    int color;
  1953.  
  1954.    double newx,newy,newz,r,sum;
  1955.  
  1956.    int k;
  1957.    int ret;
  1958.  
  1959.    struct float3dvtinf inf;
  1960.  
  1961.    float far *ffptr;
  1962.  
  1963.    /* setup affine screen coord conversion */
  1964.    setup_convert_to_screen(&inf.cvt);
  1965.    srand(1);
  1966.    color_method = (int)param[0];
  1967.    if(diskvideo)                /* this would KILL a disk drive! */
  1968.       notdiskmsg();
  1969.  
  1970.    inf.orbit[0] = 0;
  1971.    inf.orbit[1] = 0;
  1972.    inf.orbit[2] = 0;
  1973.  
  1974.    fp = open_orbitsave();
  1975.  
  1976.    ret = 0;
  1977.    if(maxit > 0x1fffffL)
  1978.       maxct = 0x7fffffffL;
  1979.    else
  1980.       maxct = maxit*1024;
  1981.    coloriter = 0L;
  1982.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  1983.    {
  1984.       if( keypressed() )  /* keypress bails out */
  1985.       {
  1986.      ret = -1;
  1987.      break;
  1988.       }
  1989.       r = rand15();     /* generate fudged random number between 0 and 1 */
  1990.       r /= 32767;
  1991.  
  1992.       /* pick which iterated function to execute, weighted by probability */
  1993.       sum = ifs_defn[12]; /* [0][12] */
  1994.       k = 0;
  1995.       while ( sum < r && ++k < numaffine*IFS3DPARM)
  1996.       {
  1997.      sum += ifs_defn[k*IFS3DPARM+12];
  1998.      if (ifs_defn[(k+1)*IFS3DPARM+12] == 0) break; /* for safety */
  1999.       }
  2000.  
  2001.       /* calculate image of last point under selected iterated function */
  2002.       ffptr = ifs_defn + k*IFS3DPARM; /* point to first parm in row */
  2003.       newx = *ffptr * inf.orbit[0] +
  2004.          *(ffptr+1) * inf.orbit[1] +
  2005.          *(ffptr+2) * inf.orbit[2] + *(ffptr+9);
  2006.       newy = *(ffptr+3) * inf.orbit[0] +
  2007.          *(ffptr+4) * inf.orbit[1] +
  2008.          *(ffptr+5) * inf.orbit[2] + *(ffptr+10);
  2009.       newz = *(ffptr+6) * inf.orbit[0] +
  2010.          *(ffptr+7) * inf.orbit[1] +
  2011.          *(ffptr+8) * inf.orbit[2] + *(ffptr+11);
  2012.  
  2013.       inf.orbit[0] = newx;
  2014.       inf.orbit[1] = newy;
  2015.       inf.orbit[2] = newz;
  2016.       if(fp)
  2017.       fprintf(fp,orbitsave_format,newx,newy,newz);
  2018.       if (float3dviewtransf(&inf))
  2019.       {
  2020.      /* plot if inside window */
  2021.      if (inf.col >= 0)
  2022.      {
  2023.         if(realtime)
  2024.            whichimage=1;
  2025.             if(color_method)
  2026.                color = (k%colors)+1;
  2027.             else
  2028.         color = getcolor(inf.col,inf.row)+1;
  2029.         if( color < colors ) /* color sticks on last value */
  2030.            (*plot)(inf.col,inf.row,color);
  2031.      }
  2032.          else if (inf.col == -2)
  2033.             return(ret);
  2034.      if(realtime)
  2035.      {
  2036.         whichimage=2;
  2037.         /* plot if inside window */
  2038.         if (inf.col1 >= 0)
  2039.         {
  2040.               if(color_method)
  2041.                  color = (k%colors)+1;
  2042.               else
  2043.             color = getcolor(inf.col1,inf.row1)+1;
  2044.             if( color < colors ) /* color sticks on last value */
  2045.           (*plot)(inf.col1,inf.row1,color);
  2046.         }
  2047.         else if (inf.col1 == -2)
  2048.                return(ret);
  2049.      }
  2050.       }
  2051.    } /* end while */
  2052.    if(fp)
  2053.       fclose(fp);
  2054.    return(ret);
  2055. }
  2056.  
  2057. int ifs()            /* front-end for ifs2d and ifs3d */
  2058. {
  2059.    if (ifs_defn == NULL && ifsload() < 0)
  2060.       return(-1);
  2061.    if(diskvideo)                /* this would KILL a disk drive! */
  2062.       notdiskmsg();
  2063.    return((ifs_type == 0) ? ifs2d() : ifs3d());
  2064. }
  2065.  
  2066.  
  2067. /* IFS logic shamelessly converted to integer math */
  2068. static int ifs2d(void)
  2069. {
  2070.    int color_method;
  2071.    FILE *fp;
  2072.    int col;
  2073.    int row;
  2074.    int color;
  2075.    int ret;
  2076.    long far *localifs;
  2077.    long far *lfptr;
  2078.    long x,y,newx,newy,r,sum, tempr;
  2079.  
  2080.    int i,j,k;
  2081.    struct l_affine cvt;
  2082.    /* setup affine screen coord conversion */
  2083.    l_setup_convert_to_screen(&cvt);
  2084.  
  2085.    srand(1);
  2086.    color_method = (int)param[0];
  2087.    if((localifs=(long far *)farmemalloc((long)numaffine*IFSPARM*sizeof(long)))==NULL)
  2088.    {
  2089.       stopmsg(0,insufficient_ifs_mem);
  2090.       return(-1);
  2091.    }
  2092.  
  2093.    for (i = 0; i < numaffine; i++)    /* fill in the local IFS array */
  2094.       for (j = 0; j < IFSPARM; j++)
  2095.      localifs[i*IFSPARM+j] = (long)(ifs_defn[i*IFSPARM+j] * fudge);
  2096.  
  2097.    tempr = fudge / 32767;     /* find the proper rand() fudge */
  2098.  
  2099.    fp = open_orbitsave();
  2100.  
  2101.    x = y = 0;
  2102.    ret = 0;
  2103.    if(maxit > 0x1fffffL)
  2104.       maxct = 0x7fffffffL;
  2105.    else
  2106.       maxct = maxit*1024L;
  2107.    coloriter = 0L;
  2108.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  2109.    {
  2110.       if( keypressed() )  /* keypress bails out */
  2111.       {
  2112.      ret = -1;
  2113.      break;
  2114.       }
  2115.       r = rand15();     /* generate fudged random number between 0 and 1 */
  2116.       r *= tempr;
  2117.  
  2118.       /* pick which iterated function to execute, weighted by probability */
  2119.       sum = localifs[6];  /* [0][6] */
  2120.       k = 0;
  2121.       while ( sum < r && k < numaffine-1) /* fixed bug of error if sum < 1 */
  2122.      sum += localifs[++k*IFSPARM+6];
  2123.       /* calculate image of last point under selected iterated function */
  2124.       lfptr = localifs + k*IFSPARM; /* point to first parm in row */
  2125.       newx = multiply(lfptr[0],x,bitshift) + 
  2126.              multiply(lfptr[1],y,bitshift) + lfptr[4];
  2127.       newy = multiply(lfptr[2],x,bitshift) + 
  2128.              multiply(lfptr[3],y,bitshift) + lfptr[5];
  2129.       x = newx;
  2130.       y = newy;
  2131.       if(fp)
  2132.      fprintf(fp,orbitsave_format,(double)newx/fudge,(double)newy/fudge,0.0);
  2133.  
  2134.       /* plot if inside window */
  2135.       col = (int)((multiply(cvt.a,x,bitshift) + multiply(cvt.b,y,bitshift) + cvt.e) >> bitshift);
  2136.       row = (int)((multiply(cvt.c,x,bitshift) + multiply(cvt.d,y,bitshift) + cvt.f) >> bitshift);
  2137.       if ( col >= 0 && col < xdots && row >= 0 && row < ydots )
  2138.       {
  2139.      /* color is count of hits on this pixel */
  2140.          if(color_method)
  2141.             color = (k%colors)+1;
  2142.          else
  2143.      color = getcolor(col,row)+1;
  2144.      if( color < colors ) /* color sticks on last value */
  2145.         (*plot)(col,row,color);
  2146.       }
  2147.       else if((long)abs(row) + (long)abs(col) > BAD_PIXEL) /* sanity check */
  2148.             return(ret);
  2149.    }
  2150.    if(fp)
  2151.       fclose(fp);
  2152.    farmemfree(localifs);
  2153.    return(ret);
  2154. }
  2155.  
  2156. static int ifs3dlong(void)
  2157. {
  2158.    int color_method;   
  2159.    FILE *fp;
  2160.    int color;
  2161.    int ret;
  2162.  
  2163.    long far *localifs;
  2164.    long far *lfptr;
  2165.    long newx,newy,newz,r,sum, tempr;
  2166.  
  2167.    int i,j,k;
  2168.  
  2169.    struct long3dvtinf inf;
  2170.    srand(1);
  2171.    color_method = (int)param[0];
  2172.    if((localifs=(long far *)farmemalloc((long)numaffine*IFS3DPARM*sizeof(long)))==NULL)
  2173.    {
  2174.       stopmsg(0,insufficient_ifs_mem);
  2175.       return(-1);
  2176.    }
  2177.  
  2178.    /* setup affine screen coord conversion */
  2179.    l_setup_convert_to_screen(&inf.cvt);
  2180.  
  2181.    for (i = 0; i < numaffine; i++)    /* fill in the local IFS array */
  2182.       for (j = 0; j < IFS3DPARM; j++)
  2183.      localifs[i*IFS3DPARM+j] = (long)(ifs_defn[i*IFS3DPARM+j] * fudge);
  2184.  
  2185.    tempr = fudge / 32767;     /* find the proper rand() fudge */
  2186.  
  2187.    inf.orbit[0] = 0;
  2188.    inf.orbit[1] = 0;
  2189.    inf.orbit[2] = 0;
  2190.  
  2191.    fp = open_orbitsave();
  2192.  
  2193.    ret = 0;
  2194.    if(maxit > 0x1fffffL)
  2195.       maxct = 0x7fffffffL;
  2196.    else
  2197.       maxct = maxit*1024L;
  2198.    coloriter = 0L;
  2199.    while(coloriter++ <= maxct) /* loop until keypress or maxit */
  2200.    {
  2201.       if( keypressed() )  /* keypress bails out */
  2202.       {
  2203.      ret = -1;
  2204.      break;
  2205.       }
  2206.       r = rand15();     /* generate fudged random number between 0 and 1 */
  2207.       r *= tempr;
  2208.  
  2209.       /* pick which iterated function to execute, weighted by probability */
  2210.       sum = localifs[12];  /* [0][12] */
  2211.       k = 0;
  2212.       while ( sum < r && ++k < numaffine*IFS3DPARM)
  2213.       {
  2214.      sum += localifs[k*IFS3DPARM+12];
  2215.      if (ifs_defn[(k+1)*IFS3DPARM+12] == 0) break; /* for safety */
  2216.       }
  2217.       
  2218.       /* calculate image of last point under selected iterated function */
  2219.       lfptr = localifs + k*IFS3DPARM; /* point to first parm in row */
  2220.  
  2221.       /* calculate image of last point under selected iterated function */
  2222.       newx = multiply(lfptr[0], inf.orbit[0], bitshift) +
  2223.              multiply(lfptr[1], inf.orbit[1], bitshift) +
  2224.          multiply(lfptr[2], inf.orbit[2], bitshift) + lfptr[9];
  2225.       newy = multiply(lfptr[3], inf.orbit[0], bitshift) +
  2226.          multiply(lfptr[4], inf.orbit[1], bitshift) +
  2227.          multiply(lfptr[5], inf.orbit[2], bitshift) + lfptr[10];
  2228.       newz = multiply(lfptr[6], inf.orbit[0], bitshift) +
  2229.          multiply(lfptr[7], inf.orbit[1], bitshift) +
  2230.          multiply(lfptr[8], inf.orbit[2], bitshift) + lfptr[11];
  2231.  
  2232.       inf.orbit[0] = newx;
  2233.       inf.orbit[1] = newy;
  2234.       inf.orbit[2] = newz;
  2235.       if(fp)
  2236.      fprintf(fp,orbitsave_format,(double)newx/fudge,(double)newy/fudge,(double)newz/fudge);
  2237.  
  2238.       if (long3dviewtransf(&inf))
  2239.       {
  2240.      if((long)abs(inf.row) + (long)abs(inf.col) > BAD_PIXEL) /* sanity check */
  2241.             return(ret);
  2242.      /* plot if inside window */
  2243.      if (inf.col >= 0)
  2244.      {
  2245.         if(realtime)
  2246.            whichimage=1;
  2247.             if(color_method)
  2248.                color = (k%colors)+1;
  2249.             else
  2250.         color = getcolor(inf.col,inf.row)+1;
  2251.         if( color < colors ) /* color sticks on last value */
  2252.            (*plot)(inf.col,inf.row,color);
  2253.      }
  2254.      if(realtime)
  2255.      {
  2256.         whichimage=2;
  2257.         /* plot if inside window */
  2258.         if (inf.col1 >= 0)
  2259.         {
  2260.                if(color_method)
  2261.                   color = (k%colors)+1;
  2262.                else
  2263.            color = getcolor(inf.col1,inf.row1)+1;
  2264.            if( color < colors ) /* color sticks on last value */
  2265.           (*plot)(inf.col1,inf.row1,color);
  2266.         }
  2267.      }
  2268.       }
  2269.    }
  2270.    if(fp)
  2271.       fclose(fp);
  2272.    farmemfree(localifs);
  2273.    return(ret);
  2274. }
  2275.  
  2276. static void setupmatrix(MATRIX doublemat)
  2277. {
  2278.    /* build transformation matrix */
  2279.    identity (doublemat);
  2280.  
  2281.    /* apply rotations - uses the same rotation variables as line3d.c */
  2282.    xrot ((double)XROT / 57.29577,doublemat);
  2283.    yrot ((double)YROT / 57.29577,doublemat);
  2284.    zrot ((double)ZROT / 57.29577,doublemat);
  2285.  
  2286.    /* apply scale */
  2287. /*   scale((double)XSCALE/100.0,(double)YSCALE/100.0,(double)ROUGH/100.0,doublemat);*/
  2288.  
  2289. }
  2290.  
  2291. int orbit3dfloat()
  2292. {
  2293.    display3d = -1;
  2294.    if(0 < glassestype && glassestype < 3)
  2295.       realtime = 1;
  2296.    else
  2297.       realtime = 0;
  2298.    return(funny_glasses_call(orbit3dfloatcalc));
  2299. }
  2300.  
  2301. int orbit3dlong()
  2302. {
  2303.    display3d = -1;
  2304.    if(0 < glassestype && glassestype < 3)
  2305.       realtime = 1;
  2306.    else
  2307.       realtime = 0;
  2308.    return(funny_glasses_call(orbit3dlongcalc));
  2309. }
  2310.  
  2311. static int ifs3d(void)
  2312. {
  2313.    display3d = -1;
  2314.  
  2315.    if(0 < glassestype && glassestype < 3)
  2316.       realtime = 1;
  2317.    else
  2318.       realtime = 0;
  2319.    if(floatflag)
  2320.       return(funny_glasses_call(ifs3dfloat)); /* double version of ifs3d */
  2321.    else
  2322.       return(funny_glasses_call(ifs3dlong));  /* long version of ifs3d     */
  2323. }
  2324.  
  2325.  
  2326.  
  2327. static int long3dviewtransf(struct long3dvtinf *inf)
  2328. {
  2329.    int i,j;
  2330.    double tmpx, tmpy, tmpz;
  2331.    long tmp;
  2332.  
  2333.    if (coloriter == 1)    /* initialize on first call */
  2334.    {
  2335.       for(i=0;i<3;i++)
  2336.       {
  2337.      inf->minvals[i] =  1L << 30;
  2338.      inf->maxvals[i] = -inf->minvals[i];
  2339.       }
  2340.       setupmatrix(inf->doublemat);
  2341.       if(realtime)
  2342.      setupmatrix(inf->doublemat1);
  2343.       /* copy xform matrix to long for for fixed point math */
  2344.       for (i = 0; i < 4; i++)
  2345.      for (j = 0; j < 4; j++)
  2346.      {
  2347.         inf->longmat[i][j] = (long)(inf->doublemat[i][j] * fudge);
  2348.         if(realtime)
  2349.            inf->longmat1[i][j] = (long)(inf->doublemat1[i][j] * fudge);
  2350.      }
  2351.    }
  2352.  
  2353.    /* 3D VIEWING TRANSFORM */
  2354.    longvmult(inf->orbit,inf->longmat,inf->viewvect,bitshift);
  2355.    if(realtime)
  2356.       longvmult(inf->orbit,inf->longmat1,inf->viewvect1,bitshift);
  2357.  
  2358.    if(coloriter <= waste) /* waste this many points to find minz and maxz */
  2359.    {
  2360.       /* find minz and maxz */
  2361.       for(i=0;i<3;i++)
  2362.      if ((tmp = inf->viewvect[i]) < inf->minvals[i])
  2363.         inf->minvals[i] = tmp;
  2364.      else if (tmp > inf->maxvals[i])
  2365.         inf->maxvals[i] = tmp;
  2366.  
  2367.       if(coloriter == waste) /* time to work it out */
  2368.       {
  2369.      inf->iview[0] = inf->iview[1] = 0L; /* center viewer on origin */
  2370.  
  2371.      /* z value of user's eye - should be more negative than extreme
  2372.             negative part of image */
  2373.      inf->iview[2] = (long)((inf->minvals[2]-inf->maxvals[2])*(double)ZVIEWER/100.0);
  2374.  
  2375.      /* center image on origin */
  2376.      tmpx = (-inf->minvals[0]-inf->maxvals[0])/(2.0*fudge); /* center x */
  2377.      tmpy = (-inf->minvals[1]-inf->maxvals[1])/(2.0*fudge); /* center y */
  2378.  
  2379.      /* apply perspective shift */
  2380.      tmpx += ((double)xshift*(xxmax-xxmin))/(xdots);
  2381.      tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  2382.      tmpz = -((double)inf->maxvals[2]) / fudge;
  2383.      trans(tmpx,tmpy,tmpz,inf->doublemat);
  2384.  
  2385.      if(realtime)
  2386.      {
  2387.         /* center image on origin */
  2388.         tmpx = (-inf->minvals[0]-inf->maxvals[0])/(2.0*fudge); /* center x */
  2389.         tmpy = (-inf->minvals[1]-inf->maxvals[1])/(2.0*fudge); /* center y */
  2390.  
  2391.         tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  2392.         tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  2393.         tmpz = -((double)inf->maxvals[2]) / fudge;
  2394.         trans(tmpx,tmpy,tmpz,inf->doublemat1);
  2395.      }
  2396.      for(i=0;i<3;i++)
  2397.         view[i] = (double)inf->iview[i] / fudge;
  2398.  
  2399.      /* copy xform matrix to long for for fixed point math */
  2400.      for (i = 0; i < 4; i++)
  2401.         for (j = 0; j < 4; j++)
  2402.         {
  2403.            inf->longmat[i][j] = (long)(inf->doublemat[i][j] * fudge);
  2404.            if(realtime)
  2405.           inf->longmat1[i][j] = (long)(inf->doublemat1[i][j] * fudge);
  2406.         }
  2407.       }
  2408.       return(0);
  2409.    }
  2410.  
  2411.    /* apply perspective if requested */
  2412.    if(ZVIEWER)
  2413.    {
  2414.       if(debugflag==22 || ZVIEWER < 100) /* use float for small persp */
  2415.       {
  2416.      /* use float perspective calc */
  2417.      VECTOR tmpv;
  2418.      for(i=0;i<3;i++)
  2419.         tmpv[i] = (double)inf->viewvect[i] / fudge;
  2420.      perspective(tmpv);
  2421.      for(i=0;i<3;i++)
  2422.         inf->viewvect[i] = (long)(tmpv[i]*fudge);
  2423.      if(realtime)
  2424.      {
  2425.         for(i=0;i<3;i++)
  2426.            tmpv[i] = (double)inf->viewvect1[i] / fudge;
  2427.         perspective(tmpv);
  2428.         for(i=0;i<3;i++)
  2429.            inf->viewvect1[i] = (long)(tmpv[i]*fudge);
  2430.      }
  2431.       }
  2432.       else
  2433.       {
  2434.      longpersp(inf->viewvect,inf->iview,bitshift);
  2435.      if(realtime)
  2436.         longpersp(inf->viewvect1,inf->iview,bitshift);
  2437.       }
  2438.    }
  2439.  
  2440.    /* work out the screen positions */
  2441.    inf->row = (int)(((multiply(inf->cvt.c,inf->viewvect[0],bitshift) +
  2442.         multiply(inf->cvt.d,inf->viewvect[1],bitshift) + inf->cvt.f)
  2443.         >> bitshift)
  2444.           + yyadjust);
  2445.    inf->col = (int)(((multiply(inf->cvt.a,inf->viewvect[0],bitshift) +
  2446.         multiply(inf->cvt.b,inf->viewvect[1],bitshift) + inf->cvt.e)
  2447.         >> bitshift)
  2448.           + xxadjust);
  2449.    if (inf->col < 0 || inf->col >= xdots || inf->row < 0 || inf->row >= ydots)
  2450.    {
  2451.       if((long)abs(inf->col)+(long)abs(inf->row) > BAD_PIXEL)
  2452.         inf->col= inf->row = -2;
  2453.       else
  2454.         inf->col= inf->row = -1;
  2455.    }    
  2456.    if(realtime)
  2457.    {
  2458.       inf->row1 = (int)(((multiply(inf->cvt.c,inf->viewvect1[0],bitshift) +
  2459.             multiply(inf->cvt.d,inf->viewvect1[1],bitshift) +
  2460.             inf->cvt.f) >> bitshift)
  2461.           + yyadjust1);
  2462.       inf->col1 = (int)(((multiply(inf->cvt.a,inf->viewvect1[0],bitshift) +
  2463.             multiply(inf->cvt.b,inf->viewvect1[1],bitshift) +
  2464.             inf->cvt.e) >> bitshift)
  2465.           + xxadjust1);
  2466.       if (inf->col1 < 0 || inf->col1 >= xdots || inf->row1 < 0 || inf->row1 >= ydots)
  2467.       {
  2468.          if((long)abs(inf->col1)+(long)abs(inf->row1) > BAD_PIXEL)
  2469.            inf->col1= inf->row1 = -2;
  2470.          else
  2471.            inf->col1= inf->row1 = -1;
  2472.       }    
  2473.    }
  2474.    return(1);
  2475. }
  2476.  
  2477. static int float3dviewtransf(struct float3dvtinf *inf)
  2478. {
  2479.    int i;
  2480.    double tmpx, tmpy, tmpz;
  2481.    double tmp;
  2482.  
  2483.    if (coloriter == 1)    /* initialize on first call */
  2484.    {
  2485.       for(i=0;i<3;i++)
  2486.       {
  2487.      inf->minvals[i] =  100000.0; /* impossible value */
  2488.      inf->maxvals[i] = -100000.0;
  2489.       }
  2490.       setupmatrix(inf->doublemat);
  2491.       if(realtime)
  2492.      setupmatrix(inf->doublemat1);
  2493.    }
  2494.  
  2495.    /* 3D VIEWING TRANSFORM */
  2496.    vmult(inf->orbit,inf->doublemat,inf->viewvect );
  2497.    if(realtime)
  2498.       vmult(inf->orbit,inf->doublemat1,inf->viewvect1);
  2499.  
  2500.    if(coloriter <= waste) /* waste this many points to find minz and maxz */
  2501.    {
  2502.       /* find minz and maxz */
  2503.       for(i=0;i<3;i++)
  2504.      if ((tmp = inf->viewvect[i]) < inf->minvals[i])
  2505.         inf->minvals[i] = tmp;
  2506.      else if (tmp > inf->maxvals[i])
  2507.         inf->maxvals[i] = tmp;
  2508.       if(coloriter == waste) /* time to work it out */
  2509.       {
  2510.      view[0] = view[1] = 0; /* center on origin */
  2511.      /* z value of user's eye - should be more negative than extreme
  2512.                negative part of image */
  2513.      view[2] = (inf->minvals[2]-inf->maxvals[2])*(double)ZVIEWER/100.0;
  2514.  
  2515.      /* center image on origin */
  2516.      tmpx = (-inf->minvals[0]-inf->maxvals[0])/(2.0); /* center x */
  2517.      tmpy = (-inf->minvals[1]-inf->maxvals[1])/(2.0); /* center y */
  2518.  
  2519.      /* apply perspective shift */
  2520.      tmpx += ((double)xshift*(xxmax-xxmin))/(xdots);
  2521.      tmpy += ((double)yshift*(yymax-yymin))/(ydots);
  2522.      tmpz = -(inf->maxvals[2]);
  2523.      trans(tmpx,tmpy,tmpz,inf->doublemat);
  2524.  
  2525.      if(realtime)
  2526.      {
  2527.         /* center image on origin */
  2528.         tmpx = (-inf->minvals[0]-inf->maxvals[0])/(2.0); /* center x */
  2529.         tmpy = (-inf->minvals[1]-inf->maxvals[1])/(2.0); /* center y */
  2530.  
  2531.         tmpx += ((double)xshift1*(xxmax-xxmin))/(xdots);
  2532.         tmpy += ((double)yshift1*(yymax-yymin))/(ydots);
  2533.         tmpz = -(inf->maxvals[2]);
  2534.         trans(tmpx,tmpy,tmpz,inf->doublemat1);
  2535.         }
  2536.      }
  2537.       return(0);
  2538.       }
  2539.  
  2540.    /* apply perspective if requested */
  2541.    if(ZVIEWER)
  2542.    {
  2543.       perspective(inf->viewvect);
  2544.       if(realtime)
  2545.      perspective(inf->viewvect1);
  2546.    }
  2547.    inf->row = (int)(inf->cvt.c*inf->viewvect[0] + inf->cvt.d*inf->viewvect[1]
  2548.         + inf->cvt.f + yyadjust);
  2549.    inf->col = (int)(inf->cvt.a*inf->viewvect[0] + inf->cvt.b*inf->viewvect[1]
  2550.         + inf->cvt.e + xxadjust);
  2551.    if (inf->col < 0 || inf->col >= xdots || inf->row < 0 || inf->row >= ydots)
  2552.    {
  2553.       if((long)abs(inf->col)+(long)abs(inf->row) > BAD_PIXEL)
  2554.         inf->col= inf->row = -2;
  2555.       else
  2556.         inf->col= inf->row = -1;
  2557.    }    
  2558.    if(realtime)
  2559.    {
  2560.       inf->row1 = (int)(inf->cvt.c*inf->viewvect1[0] + inf->cvt.d*inf->viewvect1[1]
  2561.         + inf->cvt.f + yyadjust1);
  2562.       inf->col1 = (int)(inf->cvt.a*inf->viewvect1[0] + inf->cvt.b*inf->viewvect1[1]
  2563.         + inf->cvt.e + xxadjust1);
  2564.       if (inf->col1 < 0 || inf->col1 >= xdots || inf->row1 < 0 || inf->row1 >= ydots)
  2565.       {
  2566.          if((long)abs(inf->col1)+(long)abs(inf->row1) > BAD_PIXEL)
  2567.            inf->col1= inf->row1 = -2;
  2568.          else
  2569.            inf->col1= inf->row1 = -1;
  2570.       }    
  2571.    }
  2572.    return(1);
  2573. }
  2574.  
  2575. static FILE *open_orbitsave(void)
  2576. {
  2577.    FILE *fp;
  2578.    if (orbitsave && (fp = fopen(orbitsavename,"w")) != NULL)
  2579.    {
  2580.       fprintf(fp,"pointlist x y z color\n");
  2581.       return fp;
  2582.    }
  2583.    return NULL;
  2584. }
  2585.  
  2586. /* Plot a histogram by incrementing the pixel each time it it touched */
  2587. static void _fastcall plothist(int x, int y, int color)
  2588. {
  2589.     color = getcolor(x,y)+1;
  2590.     if (color<colors) 
  2591.     putcolor(x,y,color);
  2592. }
  2593.