#!/usr/bin/perl 
use Math::Trig;

# EarthTile perl script by Arlene Ducao (arlduc@amnh.org)
#
# The Math::Trig library is implemented so that the tan (tangent) function may be used.
# This script takes any section of the Earth Mercator map (outputted from a GIS) and
# creates a Maya MEL script which will apply it to the appropriate section of a sphere. 
# In our workgroup, this allows us to apply super-hi-res images only to the specific areas
# of geographic focus-- making for nicer renders!
#
#
# For the Earth set up in Maya:
# the x-axis cuts west to east along the equator. 
# The y-axis cuts north to south. 
# The z-axis cuts from earth's center to its crust.

my ($EarthRadiusX, $EarthRadiusY, $EarthRadiusZ, $x, $y, $z, $line, $pi, $piover180, $UL_lat, $UL_long, $LR_lat, $LR_long);

#set up output file
open ( EARTH_OUT, ">EarthTile01.mel" );
print STDOUT ("what should the MEL file be called? \n ");
chop ($EARTH_OUT2 = <STDIN>);

#rename message
if (rename "EarthTile01.mel", $EARTH_OUT2) {
	print STDOUT "OK, file was renamed.\n";
}
else {print STDOUT "Rename not successful.\n";}
$EARTH_OUT2 = join '', split /.mel/, $EARTH_OUT2;


#set up pi and radius
$pi = atan2(1,1) * 4;
printf ("pi= %s \n", $pi); 
print STDOUT ("what should the earth-radius be? \n ");
chop ($radius = <STDIN>);


#make the earth sphere
#printf STDOUT ("please enter the X-radius for Earth.\n");  
#chop($EarthRadiusY = <STDIN>);
#printf STDOUT ("please enter the Y-radius for Earth.\n"); 
#chop($EarthRadiusZ = <STDIN>);
#printf STDOUT ("please enter the Z-radius for Earth.\n"); 
#chop($EarthRadiusX = <STDIN>);


# NOTE: the x,y,z calculations below assume that Earth's radius 
#   is a constant for all three axes.
printf EARTH_OUT ("sphere -p 0 0 0 -ax 0 1 0 -ssw 0 -esw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 10 -nsp 10 -ch 0;objectMoveCommand;\n");
printf EARTH_OUT ("scale -r %s %s %s ;\n", $radius, $radius, $radius);
printf EARTH_OUT ("select -r nurbsSphere1 ;\n");
printf EARTH_OUT ("rename \"nurbsSphere1\" \"%sGlobe\";\n", $EARTH_OUT2);
printf EARTH_OUT ("select -r %sGlobe;\n", $EARTH_OUT2);

# A 90-degree offset is needed
printf EARTH_OUT ("rotate -r -os 0 90 0 ;\n");


# just for fun: make a cylinder?
#printf EARTH_OUT ("cylinder -p 0 0 0 -ax 0 1 0 -ssw 0 -esw 360 -r 1 -hr 2 -d 3 -ut 0 -tol 0.01 -s 30 -nsp 1 -ch 1; nurbsPrimitiveCap 3 0 0; objectMoveCommand;\n");
#printf EARTH_OUT ("setAttr \"nurbsCylinder1.scaleX\" %s;\n", $EarthRadiusX);
#printf EARTH_OUT ("setAttr \"nurbsCylinder1.scaleY\" %s;\n", $EarthRadiusY);
#printf EARTH_OUT ("setAttr \"nurbsCylinder1.scaleZ\" %s;\n", $EarthRadiusZ);



#input 4 latitude, longitude coordinates
printf ("Please enter the name of the file containing points ordered and formatted in the following way. Each number should be on its own line, with no commas!\n");
printf ("   NW latitude\n   NW longitude\n   SE latitude\n   SE longitude\n");

#printf ("Please enter NW coordinate latitude and longitude (in that order).\n");
chop($file_in = <STDIN>);
open ( POINTS_IN, $file_in );

#input Upper Left latitude and longitude
	chop($line = <POINTS_IN>);
	$line =~ s/^\s+//;
	($UL_lat) = split(/\s+/, $line);
	chop($line = <POINTS_IN>);
	$line =~ s/^\s+//;
	($UL_lon) = split(/\s+/, $line);
	printf ("NW %s %s \n", $UL_lat, $UL_lon);
	

#input Lower Right latitude and longitude
	chop($line = <POINTS_IN>);
	$line =~ s/^\s+//;
	($LR_lat) = split(/\s+/, $line);
	chop($line = <POINTS_IN>);
	$line =~ s/^\s+//;
	($LR_lon) = split(/\s+/, $line);
	printf ("SE %s %s \n", $LR_lat, $LR_lon);
	

#subroutine to take the line from the origin to the lat/long coordinate, then find a point on this same line. 
#Note that it is NOT a direct conversion!!
#to allow the line to intersect with the globe, the outputted point is outside the globe.
sub latLong_To_XYZ {

    # z is positive, so a right triangle can be drawn on the z-axis
	if (($lon > -90) && ($lon < 90)) 		
	{	
		$phi = deg2rad($lat); 		# a degree-to-radian conversion is needed because the trig functions take radian input
		$lambda = deg2rad($lon);
		$x = $radius * (tan($lambda));
		$z = $radius;
	} 

	# x is positive, z is negative
	elsif (($lon <= 180) && ($lon >= 90)) 			
	{
		$phi = deg2rad($lat); 	# a degree-to-radian conversion is needed because the trig functions take radian input
		$lambda = deg2rad($lon-90);
		$x = $radius;
		$z = -$radius * (tan($lambda));
	}
	
	# x and z are negative
	elsif (($lon >= -180) && ($lon <= -90)) { 	
		$phi = deg2rad($lat); 	# a degree-to-radian conversion is needed because the trig functions take radian input
		$lambda = deg2rad($lon + 90); 		
		$x = -$radius;
		$z = $radius * (tan($lambda));
	} 
	
	$y = ($radius / (cos($lambda))) * (tan($phi));
	
	printf ("phi %s lambda %s \n", $phi, $lambda);
	printf EARTH_OUT ("curve -d 1 -p 0 0 0 -p %s %s %s -k 0 -k 1 ;\n", $x, $y, $z);
	printf EARTH_OUT ("select -r curve1 ;\n");
}





#print NW corner
	$lat = $UL_lat; 
	$lon = $UL_lon;
	latLong_To_XYZ();
	printf EARTH_OUT ("rename \"curve1\" \"%sCurveNW\";\n", $EARTH_OUT2);

	
#print NE corner
	$lat = $UL_lat;
	$lon = $LR_lon;
	latLong_To_XYZ();
	printf EARTH_OUT ("rename \"curve1\" \"%sCurveNE\";\n", $EARTH_OUT2);
	
#print SE corner
	$lat = $LR_lat;
	$lon = $LR_lon;
	latLong_To_XYZ();
	printf EARTH_OUT ("rename \"curve1\" \"%sCurveSE\";\n", $EARTH_OUT2);
	
#print SW corner
	$lat = $LR_lat;
	$lon = $UL_lon;
	latLong_To_XYZ();
	printf EARTH_OUT ("rename \"curve1\" \"%sCurveSW\";\n", $EARTH_OUT2);





#loft
printf EARTH_OUT ("select -r \"%sCurveNW\" \"%sCurveNE\" \"%sCurveSE\" \"%sCurveSW\";\n", $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2);
printf EARTH_OUT ("loft -ch 0 -u 0 -c 1 -ar 1 -d 1 -ss 1 -rn 0 -po 0 -rsn true \"%sCurveNW\" \"%sCurveNE\" \"%sCurveSE\" \"%sCurveSW\";\n", $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2);

#scale and rename the lofted cone
$scaleScalar = $radius * 3;
printf EARTH_OUT ("scale -r $s $s $s ;\n", $scaleScalar, $scaleScalar, $scaleScalar);
printf EARTH_OUT ("select -r loftedSurface1 ;\n");
printf EARTH_OUT ("rename \"loftedSurface1\" \"%sLoftedSurface\";\n", $EARTH_OUT2);

#convert sphere to polygons
printf EARTH_OUT ("select -r %sGlobe ;\n", $EARTH_OUT2); 
printf EARTH_OUT ("nurbsToPoly -mnd 1  -ch 0 -f 0 -pt 1 -pc 10000 -chr 0.1 -ft 0.01 -mel 0.2014 -d 0.1 -ut 1 -un 12 -vt 1 -vn 16 -uch 0 -ucr 0 -cht 0.2 -es 0 -ntr 0 -mrt 0 -uss 1 \"%sGlobe\";\n", $EARTH_OUT2);
printf EARTH_OUT ("select -r nurbsToPoly1 ;\n");
printf EARTH_OUT ("rename \"nurbsToPoly1\" \"%sPolyGlobe\";\n", $EARTH_OUT2);

#make a second polygon
printf EARTH_OUT ("nurbsToPoly -mnd 1  -ch 0 -f 0 -pt 1 -pc 10000 -chr 0.1 -ft 0.01 -mel 0.2014 -d 0.1 -ut 1 -un 12 -vt 1 -vn 16 -uch 0 -ucr 0 -cht 0.2 -es 0 -ntr 0 -mrt 0 -uss 1 \"%sGlobe\";\n", $EARTH_OUT2);
printf EARTH_OUT ("select -r nurbsToPoly1 ;\n");
printf EARTH_OUT ("rename \"nurbsToPoly1\" \"%sPolyGlobe1\";\n", $EARTH_OUT2);

#convert lofted cone to polygons
printf EARTH_OUT ("select -r %sLoftedSurface ;\n", $EARTH_OUT2); 
printf EARTH_OUT ("nurbsToPoly -mnd 1  -ch 0 -f 0 -pt 1 -pc 2 -chr 0.1 -ft 0.01 -mel 0.2014 -d 0.1 -ut 1 -un 12 -vt 1 -vn 16 -uch 0 -ucr 0 -cht 0.2 -es 0 -ntr 0 -mrt 0 -uss 1 \"%sLoftedSurface\";\n", $EARTH_OUT2);
printf EARTH_OUT ("select -r nurbsToPoly1 ;\n");
printf EARTH_OUT ("rename \"nurbsToPoly1\" \"%sPolyLoft\";\n", $EARTH_OUT2);

#group Preparation Components
printf EARTH_OUT ("select -r %sCurveNW %sCurveNE %sCurveSE %sCurveSW ;\n", $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2);
printf EARTH_OUT ("group; xform -os -piv 0 0 0;\n");
printf EARTH_OUT ("select -r group1 ;\n");
printf EARTH_OUT ("rename \"group1\" \"PreparationComponents\";\n");
printf EARTH_OUT ("setAttr \"PreparationComponents.visibility\" 0;\n");

#group FinalPolygons
printf EARTH_OUT ("select -r %sPolyGlobe %sPolyGlobe1 %sPolyLoft;\n", $EARTH_OUT2, $EARTH_OUT2, $EARTH_OUT2);
printf EARTH_OUT ("group; xform -os -piv 0 0 0;\n");
printf EARTH_OUT ("select -r group1 ;\n");
printf EARTH_OUT ("rename \"group1\" \"FinalPolygons\";\n");

#group FinalNURBS
printf EARTH_OUT ("select -r %sGlobe %sLoftedSurface;\n", $EARTH_OUT2, $EARTH_OUT2);
printf EARTH_OUT ("group; xform -os -piv 0 0 0;\n");
printf EARTH_OUT ("select -r group1 ;\n");
printf EARTH_OUT ("rename \"group1\" \"FinalNURBS\";\n");

printf STDOUT ("written to specified MEL file.\n");
