
// =============================================================
//                  PlotF Sample Equations
// =============================================================

// Several of these equations were obtained from the internet
//   http://www.uib.no/people/nfytn/surfaces.htm  (as of Jan 2000)


// ======================== Torus (Donut) ==============================

// "Torus",-10, 10,   -10, 10,   -3., 3.,   30., 20.,
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	R1	 (7.)	// radius of the hole
	#define	R2	 (3.)	// radius of the ring
	#define	R1SQ	(R1*R1)
	#define	R2SQ	(R2*R2)
	double  f,zsq,c;
	zsq = z * z;
	c = (x*x)+(y*y)+(zsq)-(R1SQ)-(R2SQ);
	f = (c*c) + 4.*R1SQ*(zsq-R2SQ);
	return(f);
}


// ======================== Twisting Pretzel ==============================

// "Pretzel",-7.1, 7.1,   -7.1, 7.1,   -2.1, 2.1,   30., 20.,
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	TURN_RATIO		4.
	#define	R1	 (5.)
	#define	R2	 (1.)
	#define	R3	 (1.)
	double	f;
	double	obj1,obj2,val1,val2,theta,phi,cos_theta,sin_phi,cos_phi;
	theta = atan2(y,x);
	cos_theta = cos(theta);
	phi = TURN_RATIO * theta;
	sin_phi   = sin(phi);
	cos_phi   = cos(phi);
	val1 = (x-cos_theta*(R1+R2*cos_phi));
	val2 = (z-R2*sin_phi);
	obj1 = (val1*val1) + cos_theta*cos_theta*(val2*val2-R3*R3);
	phi += PI;
	sin_phi   = sin(phi);
	cos_phi   = cos(phi);
	val1 = (x-cos_theta*(R1+R2*cos_phi));
	val2 = (z-R2*sin_phi);
	obj2 = (val1*val1) + cos_theta*cos_theta*(val2*val2-R3*R3);
	f = obj1*obj2;
	return(f)
}

// ======================== Mobius Torus ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define R	(7.)
	#define	A	(1.)
	#define	B	(4.)

	double f,theta,phi,sint,cost,sinp,cosp,x1,y1,dx,dy,u,v;
	theta = atan2(y,x);
	phi = theta/2.;
	sint = sin(theta);
	cost = cos(theta);
	sinp = sin(phi);
	cosp = cos(phi);
	x1 = R*cost;
	y1 = R*sint;
	dx = x - x1;
	dy = y - y1;
	u =  dx*cost*cosp + dy*sint*cosp + z*sinp;
	v = -dx*cost*sinp - dy*sint*sinp + z*cosp;
	f = ((u*u)/(A*A)) + ((v*v)/(B*B)) - 1.;
	return(f);	
}

// ======================== Mobius Figure 8 ==============================

// xmin:-10 xmax:10 ymin:-10 ymax:10 zmin:-10 zmax:10 xy:40 zrot:160
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	R1 	(7.)
	#define	A  	(1.)
	#define	B 	(7.)
	double f,theta,phi,sint,cost,sinp,cosp,u,v,w,x1,y1,dx,dy;
	theta = atan2(y,x);
	sint = sin(theta);
	cost = cos(theta);
	phi = -theta/2.;
	sinp = sin(phi);
	cosp = cos(phi);
	x1 = R1*cost;
	y1 = R1*sint;
	dx = x - x1;
	dy = y - y1;
	u =  dx*cost*cosp + dy*sint*cosp + z*sinp;
	v = -dx*cost*sinp - dy*sint*sinp + z*cosp;
	w = u*u + v*v;
	f = (w*w) - B*B*(u*u-v*v);
	return(f);
}

// ======================== Mobius Four Leaf Clover ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	R1 	(6.)
	#define	A  	(1.8)
	double f,theta,phi,sint,cost,sinp,cosp,u,v,w,x1,y1,dx,dy;
	theta = atan2(y,x);
	sint = sin(theta);
	cost = cos(theta);
	phi = -theta/2.;
	sinp = sin(phi);
	cosp = cos(phi);
	x1 = R1*cost;
	y1 = R1*sint;
	dx = x - x1;
	dy = y - y1;
	u =  dx*cost*cosp + dy*sint*cosp + z*sinp;
	v = -dx*cost*sinp - dy*sint*sinp + z*cosp;
	w = u*u + v*v;
	f = (w*w*w) - 4.*A*A*u*u*v*v;
	return(f);
}

// ======================== Toilet Seat ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define R1	(9.)
	#define	A	(.5)
	#define	B	(5.)
	double theta,phi,sinp,cosp,sinp2,cosp2,t,u,v,w,f;
	theta = atan2(y,x);
	phi = theta/2.;
	sinp = sin(phi);
	cosp = cos(phi);
	sinp2 = sinp*sinp;
	cosp2 = cosp*cosp;
	t = x*x+y*y+R1*R1;
	u = A*A*sinp2 + B*B*cosp2;
	w = A*A+B*B - A*A*z*z*cosp2 - B*B*z*z*sinp2;
	v = u*t-w;
	f = v*v-4.*u*u*(x*x+y*y)*R1*R1;
	return(f);	
}

// ======================== Barth Sextic ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	T	(1.247674391)	// .5(1+sqrt(5))
	#define	T2	(T*T)
	double	x2,y2,z2,u,v,f;

	x2 = x*x;
	y2 = y*y;
	z2 = z*z;

	u = 4.*(T2*x2-y2)*(T2*y2-z2)*(T2*z2-x2);
	v = x2+y2+z2-1.;
	f = u - (1.+2.*T)*(v*v);
	return(f);
}


// ======================== Barth Decic (Cactus) ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	T (1.6180339)	// (1+Sqrt(5))/2
	#define	T4	(T*T*T*T)
	#define	W	(1.)
	#define	W2	(W*W)
	double	x2,y2,z2,x4,y4,z4,u,v,f;

	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	x4 = x2*x2;
	y4 = y2*y2;
	z4 = z2*z2;

	u = x2+y2+z2-W2;
	v = x2+y2+z2-(2.-T)*W2;
	f = 8.*(x2-T4*y2)*(y2-T4*z2)*(z2-T4*x2)*
		(x4+y4+z4-2.*x2*y2-2.*x2*z2-2.*y2*z2)+
		+(3.+5.*T)*(u*u)*(v*v)*W2; 
	return(f);
}

// ======================== Bohemian Dome ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	A	(.5)
	#define	B	(1.5)
	#define	C	(1.)

	double	x2,y2,z2,u,v,f;
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	u = C*C*(x2+y2-A*A-B*B)+B*B*z2;
	f = u*u - 4.*(A*A-x2)*(C*C-z2)*B*B*C*C;
	return(f);
}

// ======================== Hunt's Surface ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	A	(.5)
	#define	B	(1.5)
	#define	C	(1.)

	double	x2,y2,z2,u,v,f;
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;

	u = x2+y2+z2-13.;
	v = 3.*x2+y2-4.*z2-12.;
	f = 4.*(u*u*u) + 27.*(v*v);
	return(f);
}

// ======================== Devil's Curve in 3D Space ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	A	(.45)
	#define	B	(.5)
	#define	C	(16.)

	double	x2,y2,z2,u,v,f;
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	f = x2*x2 + 2.*x2*z2 - 0.36*x2 - y2*y2 + 0.25*y2 + z2*z2;
	return(f);
}

// ======================== Tangle Cube ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	double f,x2,y2,z2,u,v;

	// TangleCube
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	f = x2*x2 - 5.*x2 + y2*y2 - 5*y2 + z2*z2 - 5.*z2 + 11.8;
	return(f);	
}

// ======================== Heart ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	double f,x2,y2,z2,u,v;
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	u = 2.*x2 + y2 + z2 - 1.;
	v = (x2/10. + y2)*(z2*z);
	f = (u*u*u) - v;
	return(f);	
}

// ======================== Chair (Tetrahedral) ==============================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	A	(.95)
	#define	B	(.8)
	#define	K	(5.)
	double f,x2,y2,z2,u,v,w;
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	u = x2+y2+z2-A*K*K;
	v = z-K;
	w = z+K;
	f = (u*u) - B*(v*v-2.*x2)*(w*w-2.*y2);
	return(f);	
}


// =================== Boy's Surface (Propeller) ==========================

double WinPlot3DF::Func(double x,double y,double z)
{
	#define	SQ2		(1.414213562)
	double f,x2,y2,z2,u,v,z4;

	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	z4 = z2*z2;

	u = 1.-z;
	v = x2+y2;
	f = 64.*u*u*u*z2*z -
		48.*u*u*z2*(3.*v+2.*z2)+
		12.*u*z*(27.*v*v-24.*z2*v+36.*SQ2*y*z*(y2-3.*x2)+4.*z4)+
		(9.*v-2.*z2)*(-81.*v*v-72.*z2*v+108.*SQ2*x*z*(x2-3.*y2)+4.*z4);
	return(f);	
}


// =================== Ugly Klein Bottle ==========================

double WinPlot3DF::Func(double x,double y,double z)
{
	double f,x2,y2,z2,u,v,w;

	x2 = x*x;
	y2 = y*y;
	z2 = z*z;

	u = x2+y2+z2;
	v = u-2.*y-1.;
	w = 2.*y;
	f = (u+w-1.)*((v*v)-8.*z2) + 16.*x*z*(u-w-1.);
	return(f);	
}

// =================== Five Star With Point ==========================

// xmin:-2.5 xmax:2.5 ymin:-2.5 ymax:2.5 zmin:-2.5 zmax:2.5 xy:30 zrot:50
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	PI	(3.141592654)
	double f,x2,y2,z2,u,v,w,h1,h2,h3,h4,h5;
	static double a,c,r,c1,c2,c3,c4,c5,c6,c7,c8;
	static int first=1;

	if (first)
	{
		first = 0;
		a = -(8./5.)*(1.+1./sqrt(5.))*sqrt(5.-sqrt(5.)); // -3.849606112048
		c = sqrt(5.-sqrt(5.))/2.; // .831253875555
		c1 = cos(2.*PI/5.); //  .309016994219
		c2 = sin(2.*PI/5.); //  .951056516346
		c3 = cos(4.*PI/5.); // -.809016994568
		c4 = sin(4.*PI/5.); //  .587785252027
		c5 = cos(6.*PI/5.); // -.809016994086
		c6 = sin(6.*PI/5.); // -.587785252691
		c7 = cos(8.*PI/5.); //  .309016994999
		c8 = sin(8.*PI/5.); // -.951056516092
		r  = (1.+3.*sqrt(5.))/4.; // 1.927050983125
	}

	x2 = x*x;
	y2 = y*y;
	z2 = z*z;

	h1 = x-z;
	h2 = c1*x - c2*y-z;
	h3 = c3*x - c4*y-z;
	h4 = c5*x - c6*y-z;
	h5 = c7*x - c8*y-z;
	u  = x2+y2-1.+r*z2;
	v  = (1.-c*z)*u*u;
	w = h1*h2*h3*h4*h5;
	f = a*w + v;
	return(f);
}

// --------------------------------------------------------------
int WinPlot3DF::Within(double x,double y,double z)
{
	return( z>-2.8 && z<.29 && (x*x+y*y<(2.3*2.3)) );
}

// ======================== Paper Mobius Strip ==============================

// "Mobius Strip",-7., 10.,   -10, 10.,   -3., 3.,   60., 335.,
#define	MOBIUSR1	(7.)
#define	MOBIUSR2	(3.)
#define	MOBIUSR1S	(MOBIUSR1*MOBIUSR1)

double WinPlot3DF::Func(double x,double y,double z)
{
	double	f;
	r = sqrt(x2+y2);
	phi = theta/2.;
	sinphi  = sin(phi);
	sinphi2 = sinphi*sinphi;
	if (sinphi==0.) tanphi=1.e-10; // avoid division by zero
	tanphi = tan(phi);
	if (tanphi==0.) tanphi=1.e-10;
	f = x2 + y2 + z2 - MOBIUSR1S - z2/sinphi2 - 2.*MOBIUSR1*z/tanphi;
	return(f);
}

int WinPlot3DF::Within(double x,double y,double z)
{
	double	r,d;
	if (x>0.0 && (2.*z+y)*(z+2.*y)<0.) return(0); // clip the intesection wings
	r = sqrt(x*x+y*y);
	d = r - MOBIUSR1;
	return((d*d+z*z) <= MOBIUSR2*MOBIUSR2);
}

void WinPlot3DF::PlotMobiusEdge()
{
	double t,p,r,d,dr,dt,tend;
	double xp,yp,zp;
	double x,y,z;
	double cosp;
	int xv,yv,first;
	int vis1,vis2;

	tend = 4.*PI;
	dt = tend / 1000.;
	dr = MOBIUSR1 / 30.;
	tend += 2.*dt;
	r = MOBIUSR1;
 	for (t=0.,first=1; t<=tend; t+=dt)
 	{
 		p = t/2.;
 		cosp = cos(p);
 		d = MOBIUSR1 + r*cosp;
 		x = cos(t) * d;
 		y = sin(t) * d;
 		z = r * sin(p);
 		xp = xpf(x,y,z);
 		yp = ypf(x,y,z);
 		zp = zpf(x,y,z);
 		xv = xvf(xp);
 		yv = yvf(yp);

 		// zearch for a zero crossing outward from screen
 		vis2 = IsVisible(xp,yp,zp);
 		if (first)
 		{
 			MoveTo(xv,yv);
 			first=0;
 		}
 		else
 		{
 			if (vis2)
 			{
 				if (!vis1) MoveTo(xv,yv);
 				DrawTo(xv,yv);
 			}
 		}
 		vis1 = vis2;
 	} // for t
}

// ======================== Interlocking Torus Rings ==============================

// torus is parallel to an axis
// plane; 0=x, 1=y, 2=z
static double PlaneTorus(int plane,double x,double y,double z,double dx,double dy,double dz,double r1,double r2)
{
	double xsq,ysq,zsq,r1sq,r2sq,d,f,e;
	x = x - dx;
	y = y - dy;
	z = z - dz;
	xsq = x * x;
	ysq = y * y;
	zsq = z * z;
	r1sq = r1 * r1;
	r2sq = r2 * r2;
	if (plane==0)
		e = xsq;
	else if (plane==1)
		e = ysq;
	else
		e = zsq;
	d = xsq+ysq+zsq-r1sq-r2sq;
	f = (d*d) + 4.*r1sq*(e-r2sq);
	return(f);
}

static double Toruses(double x,double y,double z,double* f)
{
	#define A	 (5.)
	#define	R1	 (3.)
	#define	R2	 (1.)
	f[1] = PlaneTorus(2,x,y,z, A,  A, 0.,R1,R2);
	f[2] = PlaneTorus(2,x,y,z,-A,  A, 0.,R1,R2);
	f[3] = PlaneTorus(2,x,y,z, A, -A, 0.,R1,R2);
	f[4] = PlaneTorus(2,x,y,z,-A, -A, 0.,R1,R2);
	f[5] = PlaneTorus(0,x,y,z,-A, 0., 0.,A, R2);
	f[6] = PlaneTorus(0,x,y,z, A, 0., 0.,A, R2);
	f[0] = f[1]*f[2]*f[3]*f[4]*f[5]*f[6];
	return(f[0]);
}

// the mathematical function to be plotted
double WinPlot3DF::Func(double x,double y,double z)
{
	double  f[7];
	return(Toruses(x,y,z,f));
}

// The mathematical equation used to define the "color" of the surface.
long WinPlot3DF::Color(double x,double y,double z)
{
	unsigned i,imin;
	double  f[7],fmin,ftest;
	static long torus_colors[8] = {
		(long)RGB(  0,  0,  0),	// filler
		(long)RGB(  0,  0,  0),	// black
		(long)RGB(255,  0,  0),
		(long)RGB(  0,255,  0),
		(long)RGB(  0,  0,255),
		(long)RGB(255,255,  0),
		(long)RGB(  0,255,255),
		(long)RGB(255,  0,255),
	};
	if (!m_is_color) return(1);
	Toruses(x,y,z,f);
	fmin = fabs(f[1]);
	imin = 1;
	for (i=2;i<8;i++)
	{
		ftest = fabs(f[i]);
		if (ftest<fmin) { fmin=ftest; imin=i; }
	}
	return(torus_colors[imin]);
}

// ======================== Bracelet ==============================

// the mathematical function to be plotted
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	A	 .5.
	#define	B	 3.
	#define	R1	 7.
	#define	R1SQ	(R1*R1)
	double  f,x2,y2,z2,r0,r,r2,u,c;

	u = atan2(y,x);
	x2 = x*x;
	y2 = y*y;
	z2 = z*z;
	r0 = cos(16.*u);
	r  = ((B-A)/2.)*(r0+1.)+A;
	r2 = r*r;
	c = x2+y2+z2+R1SQ-r2;
	f = (c*c) - 4.*(x2+y2)*R1SQ;
	return(f);
}

// ======================== Sin Wave Torus ==============================

// the mathematical function to be plotted
double WinPlot3DF::Func(double x,double y,double z)
{
	#define	PI	(3.141592654)
	#define	R1	 7.
	#define	R2	 2.
	#define	R3	 2.
	double  f,x1,y1,z1,dx,dy,dz,r1,r2,t,p,sint,cost,sinp,cosp;

	r1 = R1;
	r2 = R2;
	t = atan2(y,x);
	p = R3*sin(9.*t)/(2.*PI);
	sint = sin(t);
	cost = cos(t);
	sinp = sin(p);
	cosp = cos(p);
	x1 = r1*cosp*cost;
	y1 = r1*cosp*sint;
	z1 = r1*sinp;
	dx = x - x1;
	dy = y - y1;
	dz = z - z1;
	f = dx*dx + dy*dy + dz*dz - r2*r2;;
	return(f);
}


// --------------------------------------------------------------
// General equation of a torus
// axis 0=x,1=y,2=z
// r1 is radius of the torus hole
// r2 is radius of the torus
// xc,yc,zc - center location of torus
double Torus(int axis,double r1,double r2,double x,double y,double z,
			 double xc,double yc,double zc)
{
	double  f,b,c,r1sq,r2sq;
	r1sq = r1*r1;
	r2sq = r2*r2;
	x = x - xc;
	y = y - yc;
	z = z - zc;
	switch (axis)
	{
		default:
		case 0:
			b = x * x;
			c = y*y + z*z + b - r1sq - r2sq;
			break;
		case 1:
			b = y * y;
			c = x*x + z*z + b - r1sq - r2sq;
			break;
		case 2:
			b = z * z;
			c = x*x + y*y + b - r1sq - r2sq;
			break;
	}
	f = c*c + 4.*r1sq*(b-r2sq);
	return(f);
}

/*
	#define PI	 (3.141592654)
	// Torus A
	#define	R1A	 (8.)
	#define	R2A	 (2.)
	#define XCA	 (0.)	// center location
	#define YCA	 (0.)
	#define ZCA	 (0.)
	// Torus B
	#define	R1B	 (8.)
	#define	R2B	 (2.)
	#define XCB	 (6.)	// center location
	#define YCB	 (0.)
	#define ZCB	 (0.)

	double f, u, v, w, a, b, c;
	a = 1.;
	b = 1.;
	c = 1.;

	u = x*x + y*y + z*z;
	v = x*y + y*z + z*x;
	w = x   + y   + z;
	f = u - a*v - b*w - c;

	double f, torus1, torus2, r1a, r2a, r1b, r2b;
	torus1 = Torus(2, r1a, r2a, x, y, z, XCA, YCA, ZCA);
	torus2 = Torus(1, r1b, r2b, x, y, z, XCB, YCB, ZCB);
	f = torus1 * torus2;
	return(f);
*/




//	<><><><><><><><><><><><><>  PlotFsamp.txt  <><><><><><><><><><><><><><> //
