
#include "bits/bit-dragon3.h"

#include <cmath>  // sqrt(), cos(), sin()

#include "fxtiomanip.h"

#include "jjassert.h"

#include "demo/nextarg.h"
#include "fxttypes.h"  // ulong


//% TeX picture of the terdragon curve.


//#define TIMING // uncomment to disable printing

ulong style = 0;

const ulong csn = 3;
double C[csn], S[csn];  // direction vectors

double chop0(double x)  { if ( fabs(x)<0.001 )  x=0.0;  return x; }

void line(double x0, double y0, double x1, double y1)
// For \line(dx,dy){length} and \vector(dx,dy}{length}
// NOTE: The argument 'length' is the VERTICAL coordinate for
// vertical line segments, else the HORIZONTAL coordinate.
{
    double dx = x1 - x0,  dy = y1 - y0;

    // length:
    double len = sqrt( dx*dx + dy*dy );

//    jjassert( len > 0.0001 );

    // slopes:
    long sx = (long)round( 99.0 * dx/len );
    long sy = (long)round( 99.0 * dy/len );
    // simplify for purely horiz/vert case:
//    if ( sx==0 )  sy = 1;
//    if ( sy==0 )  sx = 1;

    // "length" to be used with \vector or \line:
    double vlen = fabs( dx );
    if ( fabs(vlen)<1e-4 )  vlen = 1;

    x0 = chop0(x0);  y0 = chop0(y0);

    cout << "\\put(" << x0 << "," << y0 << ")"
         << "{\\vector(" << sx <<","<< sy << ")"
         << "{" << vlen << "}}"
         << endl;
}
// -------------------------


void draw_turn(double x, double y, double dx, double dy, double ndx, double ndy)
/*
//
//           NX
//          /  \
//         * X2 * X3
//        /      \
//       * X1     \
//    X /          \
//
//
*/
{
    cout.precision(4);
    double nx = x + dx,  ny = y + dy;  // next (x,y)

    double m = 0.25,  m2 = 0.75;
    double x1 = x+m*dx,  y1 = y+m*dy;
    double x2 = x+m2*dx,  y2 = y+m2*dy;
    double x3 = nx+m*ndx,  y3 = ny+m*ndy;

    double x12 = x+0.5*dx,  y12 = y+0.5*dy;
    double x23 = nx+0.5*ndx,  y23 = ny+0.5*ndy;

    switch ( style )
    {
    case 0:  // as in fxtbook (roundish corners, default)
        line(x1,y1, x2,y2);
        line(x2,y2, x3,y3);
        break;

    default:  // edgy (second figure in fxtbook)
        line(x12,y12, x23,y23);
        break;

//    x = chop0(x);  y = chop0(y);
//    x1 = chop0(x1);  y1 = chop0(y1);
//    nx = chop0(nx);  ny = chop0(ny);
//    x2 = chop0(x2);  y2 = chop0(y2);
//    x3 = chop0(x3);  y3 = chop0(y3);
//
//    double nnx = nx + ndx,  nny = ny + ndy;  // next next (x,y)
//    double x4 = nx + m2*ndx,  y4 = ny+m2*ndy;
//    nnx = chop0(nnx);  nny = chop0(nny);
//    x4 = chop0(x4);  y4 = chop0(y4);
//    cout << "\\qbezier"
//         <<"(" << x1 <<","<< y1 << ")"
////         <<"(" << x2 <<","<< y2 << ")"
//         <<"(" << nx <<","<< ny << ")"
////         <<"(" << x3 <<","<< y3 << ")"
//         <<"(" << x4 <<","<< y4 << ")"
//         << ""
//         << endl;
    }
}
// -------------------------


int
main(int argc, char **argv)
{
    ulong n = 27 + 1;
    NXARG(n,"Number of moves (fxtbook uses n=729)");

#ifdef TIMING
    ulong rx3 = 1;
    bool t = 0;
    for (ulong k=1; k<=n; ++k)  t ^= bit_dragon3_turn(rx3);
    cout << " rx3=" << rx3 << "  t=" << t << endl;

#else // TIMING
    NXARG(style,"Drawing style (fxtbook uses style=0)");
    cout << "%% style=" << style << endl;

    for (ulong j=0; j<csn; ++j)
    {
        const double p2 = 6.28318530717959;
        const double ph = p2/csn * j;
        C[j] = cos(ph);  S[j] = sin(ph);
    }

    double x = 0, y = 0;
    cout << "\\put(" << x << "," << y << ")" << "{\\circle{0.5}}" << endl;
    cout << "\\put(" << x << "," << y << ")" << "{\\circle{0.25}}" << endl;

    double ix=0, ax=0, iy=0, ay=0;  //  min/max  x/y
    ulong rx3 = 1;
    ulong dir = 0;
    for (ulong k=1; k<=n; ++k)  // note: start with k=1
    {
        double dx = C[dir],  dy = S[dir];

        const bool f = bit_dragon3_turn(rx3);
        if ( f )
        {
            ++dir;
            if ( dir==csn )  dir=0;
        }
        else
        {
            if ( dir==0 )  dir=csn;
            --dir;
        }
        double ndx = C[dir],  ndy = S[dir];
        draw_turn(x,y, dx,dy, ndx,ndy);

//        if ( t > n/3 )
//        {
//            cout << ""
//        }

        x += dx;  y += dy;  // move


        // update max/min:
        if ( x<ix )  ix = x;  if ( x>ax )  ax = x;
        if ( y<iy )  iy = y;  if ( y>ay )  ay = y;
    }

//    cout << "% ix = " << ix << endl;
//    cout << "% ax = " << ax << endl;
//    cout << "% iy = " << iy << endl;
//    cout << "% ay = " << ay << endl;
    double wd = ax-ix, hg = ay-iy;
    double xo = ix, yo = iy;
//    cout << "% width = " << wd << endl;
//    cout << "% height = " << hg << endl;
//    cout << "% xoff = " << xo << endl;
//    cout << "% yoff = " << yo << endl;

    cout << "%% Put next line (un-commented) on top of pic:" << endl;
    cout << "%\\begin{picture}("
         << wd+1 <<"," << hg+1 << ")"
         <<"("<< xo-0.5 <<"," << yo-0.5 << ")" << endl;

#endif // TIMING
    return 0;
}
// -------------------------

/*
Embedding LaTeX code is:

\begin{figure}
\begin{center}
\setlength{\unitlength}{7mm} % fxtbook 729 moves
%%\begin{picture}(width,height)(x offset,y offset)
\begin{picture}(17.5,29.58)(-1.5,-27.35)% fxtbook 729 moves
  \thicklines
 [OUTPUT of the program HERE] <--= there!
\end{picture}
\end{center}
\caption{\jjlabel{fig:dragon3}
The terdragon curve.}
\end{figure}
*/

/*
Timing:
 time ./bin 1000000000
arg 1: 1000000000 == n  [Number of moves (fxtbook uses n=729)]  default=28
 rx3=163754053890  t=1
./bin 1000000000  4.51s user 0.00s system 99% cpu 4.518 total
 ==> 1000000000/4.51 == 221,729,490 per second
*/


/// Emacs:
/// Local Variables:
/// MyRelDir: "demo/bits"
/// makefile-dir: "../../"
/// make-target: "1demo DSRC=demo/bits/dragon3-curve-texpic-demo.cc"
/// make-target2: "1demo DSRC=demo/bits/dragon3-curve-texpic-demo.cc DEMOFLAGS=-DTIMING"
/// End:

