/*
* ConicalImageProjection.java 1.0 98/06/03 Carl Burke
*
* Provides an conical projection of data on a sphere.
*
* Copyright (c) 1998 Carl Burke.
*
* Derived from code in planet.c Copyright 1998 Torben AE. Mogensen
*/
public class ConicalImageProjection extends ImageProjection
{
public ConicalImageProjection(int w, int h, SolidNoiseGenerator sng)
{
super(w, h, sng);
}
double ymin;
double ymax;
public void renderTerrain()
{
double k1,c,y2,x,y,z,zz,x1,y1,z1,theta1,theta2,cos2;
int i,j;
ymin = 2.0;
ymax = -2.0;
SNG.setScaling(scale, Width, Height);
k1 = 1.0/sla;
c = k1*k1;
y2 = Math.sqrt(c*(1.0-Math.sin(lat/k1))/(1.0+Math.sin(lat/k1)));
if (lat>0)
{
for (j = 0; j < Height; j++) {
y = (2.0*j-Height)/Height/scale+y2;
for (i = 0; i < Width ; i++) {
x = (2.0*i-Width)/Height/scale;
zz = x*x+y*y;
if (zz==0.0) theta1 = 0.0; else theta1 = k1*Math.atan2(x,y);
if (theta1<-Math.PI || theta1>Math.PI) pixels[j*Width+i] = SNG.background();
else {
theta1 += longi-0.5*Math.PI; /* theta1 is longitude */
theta2 = k1*Math.asin((zz-c)/(zz+c));
/* theta2 is latitude */
if (theta2 > 0.5*Math.PI || theta2 < -0.5*Math.PI) pixels[j*Width+i] = SNG.background();
else {
cos2 = Math.cos(theta2);
y = Math.sin(theta2);
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
pixels[j*Width+i] = SNG.color(Math.cos(theta1)*cos2,y,-Math.sin(theta1)*cos2);
}
}
}
}
}
else {
for (j = 0; j < Height; j++) {
for (i = 0; i < Width ; i++) {
x = (2.0*i-Width)/Height/scale;
y = (2.0*j-Height)/Height/scale-y2;
zz = x*x+y*y;
if (zz==0.0) theta1 = 0.0; else theta1 = -k1*Math.atan2(x,-y);
if (theta1<-Math.PI || theta1>Math.PI) pixels[j*Width+i] = SNG.background();
else {
theta1 += longi-0.5*Math.PI; /* theta1 is longitude */
theta2 = k1*Math.asin((zz-c)/(zz+c));
/* theta2 is latitude */
if (theta2 > 0.5*Math.PI || theta2 < -0.5*Math.PI) pixels[j*Width+i] = SNG.background();
else {
cos2 = Math.cos(theta2);
y = Math.sin(theta2);
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
pixels[j*Width+i] = SNG.color(Math.cos(theta1)*cos2,y,-Math.sin(theta1)*cos2);
}
}
}
}
}
}
public void renderLatitudes()
{
double c,k1,x,y,z,x1,y1,z1,y2,zz,theta1,theta2;
int i,j,k;
k1 = 1.0/Math.sin(lat);
c = k1*k1;
y2 = Math.sqrt(c*(1.0-Math.sin(lat/k1))/(1.0+Math.sin(lat/k1)));
if (lat>0)
{
for (theta1 = 0.0; theta1>-90.0; theta1-=hgrid);
for (theta1 = theta1; theta1<90.0; theta1+=hgrid)
{
y = Math.sin(DEG2RAD*theta1);
if (ymin <= y && y <= ymax)
{
zz = Math.sqrt(c*(1.0+Math.sin(DEG2RAD*theta1/k1))
/(1.0-Math.sin(DEG2RAD*theta1/k1)));
for (theta2=-Math.PI+longi; theta2-90.0; theta1-=hgrid);
for (theta1 = theta1; theta1<90.0; theta1+=hgrid)
{
y = Math.sin(DEG2RAD*theta1);
if (ymin <= y && y <= ymax)
{
zz = Math.sqrt(c*(1.0+Math.sin(DEG2RAD*theta1/k1))
/(1.0-Math.sin(DEG2RAD*theta1/k1)));
for (theta2=-Math.PI+longi; theta20)
{
for (theta1=-0.5*Math.PI; theta1<0.5*Math.PI; theta1+=0.5/Width/scale)
{
y = Math.sin(theta1);
if (ymin <= y && y <= ymax)
{
zz = Math.sqrt(c*(1.0+Math.sin(theta1/k1)) /(1.0-Math.sin(theta1/k1)));
for (theta2 = 0.0; theta2>-180.0+longi/DEG2RAD; theta2-=vgrid);
for (theta2 = theta2; theta2<180.0+longi/DEG2RAD; theta2+=vgrid)
{
z1 = DEG2RAD*theta2-longi;
x1 = -zz*Math.sin(z1/k1);
y1 = -zz*Math.cos(z1/k1);
i = (int)(0.5*(Height*scale*x1+Width));
j = (int)(0.5*(Height*scale*(y1+y2)+Height));
if (0<=i && i-180.0+longi/DEG2RAD; theta2-=vgrid);
for (theta2 = theta2; theta2<180.0+longi/DEG2RAD; theta2+=vgrid)
{
z1 = DEG2RAD*theta2-longi;
x1 = zz*Math.sin(z1/k1);
y1 = zz*Math.cos(z1/k1);
i = (int)(0.5*(Height*scale*x1+Width));
j = (int)(0.5*(Height*scale*(y1-y2)+Height));
if (0<=i && i