//$Header:$

/*
POVSAVE.CPP - POV-Ray File Save Module for Geodesic Class

	Copyright (C) 1995 - 2002 Richard J. Bono

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	 Please direct inquiries, comments and modifications to:
	 Richard J. Bono
	 44 Augusta Rd.
	 Brownsville, TX 78521

	 email: rjbono@applied-synergetics.com

Revision history:

$Log:$
*/

#include "Geodesic.h"

//----------------------------------------POV File member Functions
//-------------------save POV-Ray file
void CGeodesic::save_POV(char *filename)
{
	double sX, sY, sZ, eX, eY, eZ, cX, cY, cZ;
	long end_face;

	//save chord data for symmetry triangle to POV file
	//filename should include .POV extension on MS-DOS systems

	ofstream POV(filename);
	ofstream DOME("dome.inc");
	//Set field widths
	POV << setiosflags(ios::fixed) << setw(8) << setprecision(6);

	//set up file header
	POV << "//POV-Ray script --- generated by DOME 4.80" << '\n';
	POV << "#include" << '"' << "colors.inc" << '"' << '\n';
	POV << "#include" << '"' << "shapes.inc" << '"' << '\n';
	POV << "#include" << '"' << "textures.inc" << '"' << '\n';
	POV << "#include" << '"' << "dome.inc" << '"' << '\n';

	POV << "#declare Cam_factor = 2.5" << '\n';
	POV << "#declare Camera_X = 1 * Cam_factor" << '\n';
	POV << "#declare Camera_Y = 0.04 * Cam_factor" << '\n';
	POV << "#declare Camera_Z = 0.1 * Cam_factor" << '\n';

	POV << "camera { location  <Camera_X, Camera_Y, Camera_Z>" << '\n';
	POV << "         sky <0,0,1>" << '\n';
	POV << "         look_at   <0, 0, 0> }" << '\n' << '\n';

	POV << "object { light_source { <Camera_X + 1, Camera_Y + 1 , Camera_Z + 1> color White } }" << '\n';

	POV << '\n';
	POV << "#declare EdgeTexture=" << '\n';
	POV << "texture{" << '\n';
	POV << "        pigment{Silver}" << '\n';
	POV << "        finish{" << '\n';
	POV << "               specular 1" << '\n';
	POV << "               roughness .00002" << '\n';
	POV << "               ambient .3" << '\n';
	POV << "               diffuse .5" << '\n';
	POV << "               crand .0005" << '\n';
	POV << "               reflection .15" << '\n';
	POV << "        }" << '\n';
	POV << "}" << '\n';

	POV << "#declare PointTexture=" << '\n';
	POV << "texture{" << '\n';
	POV << "        pigment{Silver}" << '\n';
	POV << "        finish{" << '\n';
	POV << "               specular 1" << '\n';
	POV << "               roughness .00001" << '\n';
	POV << "               ambient .3" << '\n';
	POV << "               diffuse .5" << '\n';
	POV << "               crand .0005" << '\n';
	POV << "               reflection .15" << '\n';
	POV << "        }" << '\n';
	POV << "}" << '\n';

	POV << "#declare FaceTexture=" << '\n';
	POV << "texture{" << '\n';
	POV << "        pigment{Turquoise filter .250}" << '\n';
	POV << "        finish{" << '\n';
	POV << "               specular 1" << '\n';
	POV << "               roughness .00005" << '\n';
	POV << "               ambient .3" << '\n';
	POV << "               diffuse .7" << '\n';
	POV << "               crand .005" << '\n';
	POV << "               reflection .15" << '\n';
	POV << "        }" << '\n';
	POV << "}" << '\n';

	POV << "object { sphere { <0, 0, 0>,50000 }" << '\n';
	POV << "       hollow" << '\n';
	POV << "       texture {" << '\n';
	POV << "               Blue_Sky3" << '\n';
	POV << "               scale <80000, 50000, 30000>" << '\n';
	POV << "               finish { crand .05 ambient .7 }" << '\n';
	POV << "       }" << '\n';
	POV <<"}" << '\n';

	POV << "declare Dome=" << '\n';
	POV << "union{" << '\n';
	POV << "object {DomeEdges no_shadow texture{EdgeTexture}}" << '\n';
	POV << "object {DomePoints no_shadow texture{PointTexture}}" << '\n';
	POV << "object {DomeFaces no_shadow texture{FaceTexture}}" << '\n';
	POV << "}" << '\n';

	POV << "object{Dome rotate <0, 0, 0> }" << '\n' << '\n';

	POV << "//End Pov Script" << '\n';
	POV.close();

	//determine the number of faces required (first face = 0)
	if(sphere_flg)
		end_face = face_quantity(classtype, polytype);
	else
		end_face = 0;

	if(!show_status){
		cout << "Saving Data to File... ";
		status_count = 0;
	}

	DOME << "//Dome Povray Include file generated by DOME 4.80" << '\n' << '\n';
	DOME << "#declare DomePoints=" << '\n';
	DOME << "union {" << '\n';

	//output POV data...start with spheres at vertexia points...
	for(j=0; j<=end_face; j++){

		if(polytype == 1)
			icosa_sphere(j);
		else if(polytype == 2)
			octa_sphere(j);
		else if(polytype == 3)
			tetra_sphere(j);

		DOME << "//Sphere Face #" << (j+1) << '\n';
		for(i=1; i<=vertex_calc; i++){
			if(!show_status){
				time_passage(status_count);
				status_count++;
				if(status_count > 3)
					status_count = 0;
			}

			//convert spherical to cartesian
			sX = sphere_pnt[i].radius * clean_float(cos(sphere_pnt[i].phi * DEG_TO_RAD) *
																 sin(sphere_pnt[i].theta * DEG_TO_RAD));
			sY = sphere_pnt[i].radius * clean_float(sin(sphere_pnt[i].phi * DEG_TO_RAD) *
																 sin(sphere_pnt[i].theta * DEG_TO_RAD));
			sZ = sphere_pnt[i].radius * clean_float(cos(sphere_pnt[i].theta * DEG_TO_RAD));

			//Save data
			DOME << "sphere{<" << sX << ", " << sY << ", " << sZ << ">,0.015}" << '\n';
		}
	}
	DOME << "}" << '\n' << '\n';

	DOME << "#declare DomeEdges=" << '\n';
	DOME << "union {" << '\n';

	//Now do the chords
	for(j=0; j<=end_face; j++){

		if(polytype == 1)
			icosa_sphere(j);
		else if(polytype == 2)
			octa_sphere(j);
		else if(polytype == 3)
			tetra_sphere(j);

		DOME << "//Sphere Face #" << (j+1) << '\n';
		for(i=1; i<=edges_calc; i++){
			if(!show_status){
				time_passage(status_count);
				status_count++;
				if(status_count > 3)
					status_count = 0;
			}

	
			//convert spherical to cartesian
			sX = sphere_pnt[edgepts[i].start].radius *
					clean_float(cos(sphere_pnt[edgepts[i].start].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));
			sY = sphere_pnt[edgepts[i].start].radius *
					clean_float(sin(sphere_pnt[edgepts[i].start].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));
			sZ = sphere_pnt[edgepts[i].start].radius *
					clean_float(cos(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));

			eX = sphere_pnt[edgepts[i].end].radius *
					clean_float(cos(sphere_pnt[edgepts[i].end].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));
			eY = sphere_pnt[edgepts[i].end].radius *
					clean_float(sin(sphere_pnt[edgepts[i].end].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));
			eZ = sphere_pnt[edgepts[i].end].radius *
					clean_float(cos(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));

			//save data
			DOME << "cylinder{<" << sX << ", " << sY << ", " << sZ << ">, ";
			DOME << "<" << eX << ", " << eY << ", " << eZ << ">,0.01 }" << '\n';
		}
	}
	DOME << "}" << '\n' << '\n';

	DOME << "#declare DomeFaces=" << '\n';
	DOME << "union {" << '\n';

	//Now do the faces
	for(j=0; j<=end_face; j++){

		if(polytype == 1)
			icosa_sphere(j);
		else if(polytype == 2)
			octa_sphere(j);
		else if(polytype == 3)
			tetra_sphere(j);

		DOME << "//Sphere Face #" << (j+1) << '\n';
		for(i=1; i<=face_calc; i++){
			if(!show_status){
				time_passage(status_count);
				status_count++;
				if(status_count > 3)
					status_count = 0;
			}

	
			//convert spherical to cartesian
			sX = sphere_pnt[polyface[i].cornerA].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerA].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerA].theta * DEG_TO_RAD));
			sY = sphere_pnt[polyface[i].cornerA].radius *
					clean_float(sin(sphere_pnt[polyface[i].cornerA].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerA].theta * DEG_TO_RAD));
			sZ = sphere_pnt[polyface[i].cornerA].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerA].theta * DEG_TO_RAD));

			eX = sphere_pnt[polyface[i].cornerB].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerB].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerB].theta * DEG_TO_RAD));
			eY = sphere_pnt[polyface[i].cornerB].radius *
					clean_float(sin(sphere_pnt[polyface[i].cornerB].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerB].theta * DEG_TO_RAD));
			eZ = sphere_pnt[polyface[i].cornerB].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerB].theta * DEG_TO_RAD));

			cX = sphere_pnt[polyface[i].cornerC].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerC].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerC].theta * DEG_TO_RAD));
			cY = sphere_pnt[polyface[i].cornerC].radius *
					clean_float(sin(sphere_pnt[polyface[i].cornerC].phi * DEG_TO_RAD) *
									sin(sphere_pnt[polyface[i].cornerC].theta * DEG_TO_RAD));
			cZ = sphere_pnt[polyface[i].cornerC].radius *
					clean_float(cos(sphere_pnt[polyface[i].cornerC].theta * DEG_TO_RAD));


			//save data
			DOME << "triangle{<" << sX << ", " << sY << ", " << sZ << ">, " << '\n';
			DOME << "         <" << eX << ", " << eY << ", " << eZ << ">, " << '\n';
			DOME << "         <" << cX << ", " << cY << ", " << cZ << "> "  << '\n';
			DOME << "}" << '\n';
		}
	}
	DOME << "}" << '\n' << '\n';
	DOME << "//End DOME include file" << '\n';
	DOME.close();
}

//-------------------save POV-Ray file
void CGeodesic::save_buckypov(char *filename)
{
	double sX, sY, sZ, eX, eY, eZ;
	long end_face;

	//save Buckyball chord data to POV file
	//filename should include .POV extension on MS-DOS systems

	ofstream POV(filename);
	ofstream DOME("dome.inc");
	//Set field widths
	POV << setiosflags(ios::fixed) << setw(8) << setprecision(6);

	//set up file header
	POV << "//POV-Ray script --- generated by DOME 4.80" << '\n';
	POV << "#include" << '"' << "colors.inc" << '"' << '\n';
	POV << "#include" << '"' << "shapes.inc" << '"' << '\n';
	POV << "#include" << '"' << "textures.inc" << '"' << '\n';
	POV << "#include" << '"' << "dome.inc" << '"' << '\n';

	POV << "#declare Cam_factor = 2.5" << '\n';
	POV << "#declare Camera_X = 1 * Cam_factor" << '\n';
	POV << "#declare Camera_Y = 0.04 * Cam_factor" << '\n';
	POV << "#declare Camera_Z = 0.1 * Cam_factor" << '\n';

	POV << "camera { location  <Camera_X, Camera_Y, Camera_Z>" << '\n';
	POV << "         sky <0,0,1>" << '\n';
	POV << "         look_at   <0, 0, 0> }" << '\n' << '\n';

	POV << "object { light_source { <Camera_X + 1, Camera_Y + 1 , Camera_Z + 1> color White } }" << '\n';

	POV << '\n';
	POV << "#declare EdgeTexture=" << '\n';
	POV << "texture{" << '\n';
	POV << "        pigment{Silver}" << '\n';
	POV << "        finish{" << '\n';
	POV << "               specular 1" << '\n';
	POV << "               roughness .00002" << '\n';
	POV << "               ambient .3" << '\n';
	POV << "               diffuse .5" << '\n';
	POV << "               crand .0005" << '\n';
	POV << "               reflection .15" << '\n';
	POV << "        }" << '\n';
	POV << "}" << '\n';

	POV << "#declare PointTexture=" << '\n';
	POV << "texture{" << '\n';
	POV << "        pigment{Silver}" << '\n';
	POV << "        finish{" << '\n';
	POV << "               specular 1" << '\n';
	POV << "               roughness .00001" << '\n';
	POV << "               ambient .3" << '\n';
	POV << "               diffuse .5" << '\n';
	POV << "               crand .0005" << '\n';
	POV << "               reflection .15" << '\n';
	POV << "        }" << '\n';
	POV << "}" << '\n';

	POV << "object { sphere { <0, 0, 0>,50000 }" << '\n';
	POV << "       hollow" << '\n';
	POV << "       texture {" << '\n';
	POV << "               Blue_Sky3" << '\n';
	POV << "               scale <80000, 50000, 30000>" << '\n';
	POV << "               finish { crand .05 ambient .7 }" << '\n';
	POV << "       }" << '\n';
	POV <<"}" << '\n';

	POV << "declare Dome=" << '\n';
	POV << "union{" << '\n';
	POV << "object {DomeEdges no_shadow texture{EdgeTexture}}" << '\n';
	POV << "object {DomePoints no_shadow texture{PointTexture}}" << '\n';
	POV << "}" << '\n';

	POV << "object{Dome rotate <0, 0, 0> }" << '\n' << '\n';

	POV << "//End Pov Script" << '\n';
	POV.close();

	//determine the number of faces required (first face = 0)
	if(sphere_flg)
		end_face = face_quantity(classtype, polytype);
	else
		end_face = 0;

	edges_calc = bucky_edges;

	if(!show_status){
		cout << "Saving Data to File... ";
		status_count = 0;
	}

	DOME << "//Dome Povray Include file generated by DOME 4.80" << '\n' << '\n';
	DOME << "#declare DomePoints=" << '\n';
	DOME << "union {" << '\n';

	//output POV data...start with spheres at vertexia points...
	for(j=0; j<=end_face; j++){

		if(polytype == 1)
			icosa_sphere(j);
		else if(polytype == 2)
			octa_sphere(j);
		else if(polytype == 3)
			tetra_sphere(j);

		DOME << "//Sphere Face #" << (j+1) << '\n';
		for(i=1; i<=vertex_calc; i++){
			if(!show_status){
				time_passage(status_count);
				status_count++;
				if(status_count > 3)
					status_count = 0;
			}

			//convert spherical to cartesian
			if(fmod((pnt_label[i].A + pnt_label[i].B), 3.0) != 0.0){
				sX = sphere_pnt[i].radius * clean_float(cos(sphere_pnt[i].phi * DEG_TO_RAD) *
																 sin(sphere_pnt[i].theta * DEG_TO_RAD));
				sY = sphere_pnt[i].radius * clean_float(sin(sphere_pnt[i].phi * DEG_TO_RAD) *
																 sin(sphere_pnt[i].theta * DEG_TO_RAD));
				sZ = sphere_pnt[i].radius * clean_float(cos(sphere_pnt[i].theta * DEG_TO_RAD));
				//Save data
				DOME << "sphere{<" << sX << ", " << sY << ", " << sZ << ">,0.015}" << '\n';
			}
		}
	}
	DOME << "}" << '\n' << '\n';

	DOME << "#declare DomeEdges=" << '\n';
	DOME << "union {" << '\n';

	//Now do the chords
	for(j=0; j<=end_face; j++){

		if(polytype == 1)
			icosa_sphere(j);
		else if(polytype == 2)
			octa_sphere(j);
		else if(polytype == 3)
			tetra_sphere(j);

		DOME << "//Sphere Face #" << (j+1) << '\n';
		for(i=1; i<=edges_calc; i++){
			if(!show_status){
				time_passage(status_count);
				status_count++;
				if(status_count > 3)
					status_count = 0;
			}
			//convert spherical to cartesian
			sX = sphere_pnt[edgepts[i].start].radius *
					clean_float(cos(sphere_pnt[edgepts[i].start].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));
			sY = sphere_pnt[edgepts[i].start].radius *
					clean_float(sin(sphere_pnt[edgepts[i].start].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));
			sZ = sphere_pnt[edgepts[i].start].radius *
					clean_float(cos(sphere_pnt[edgepts[i].start].theta * DEG_TO_RAD));

			eX = sphere_pnt[edgepts[i].end].radius *
					clean_float(cos(sphere_pnt[edgepts[i].end].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));
			eY = sphere_pnt[edgepts[i].end].radius *
					clean_float(sin(sphere_pnt[edgepts[i].end].phi * DEG_TO_RAD) *
									sin(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));
			eZ = sphere_pnt[edgepts[i].end].radius *
					clean_float(cos(sphere_pnt[edgepts[i].end].theta * DEG_TO_RAD));

			//save data
			DOME << "cylinder{<" << sX << ", " << sY << ", " << sZ << ">, ";
			DOME << "<" << eX << ", " << eY << ", " << eZ << ">,0.01 }" << '\n';
		}
	}
	DOME << "}" << '\n' << '\n';
	DOME << "//End DOME include file" << '\n';
	DOME.close();
}

