/* $Id: plwind.c,v 1.17 2005/04/27 06:44:25 rlaboiss Exp $

	Routines for setting up world coordinates of the current viewport.

   Copyright (C) 2004  Alan W. Irwin

   This file is part of PLplot.

   PLplot is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Library Public License as published
   by the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   PLplot 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 Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with PLplot; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "plplotP.h"

#define  dtr   0.01745329252

/*--------------------------------------------------------------------------*\
 * void plwind()
 *
 * Set up world coordinates of the viewport boundaries (2d plots).
\*--------------------------------------------------------------------------*/

void
c_plwind(PLFLT xmin, PLFLT xmax, PLFLT ymin, PLFLT ymax)
{
    PLFLT dx, dy, mmxmi, mmxma, mmymi, mmyma;
    PLWindow w;

    if (plsc->level < 2) {
	plabort("plwind: Please set up viewport first");
	return;
    }

/* Best to just warn and recover on bounds errors */

    if (xmin == xmax) {
	plwarn("plwind: Invalid window limits in x.");
	xmin--; xmax++;
    }
    if (ymin == ymax) {
	plwarn("plwind: Invalid window limits in y.");
	ymin--; ymax++;
    }

    dx = (xmax - xmin) * 1.0e-5;
    dy = (ymax - ymin) * 1.0e-5;

/* The true plot window is made slightly larger than requested so that */
/* the end limits will be on the graph  */

    plsc->vpwxmi = xmin - dx;
    plsc->vpwxma = xmax + dx;
    plsc->vpwymi = ymin - dy;
    plsc->vpwyma = ymax + dy;

/* Compute the scaling between coordinate systems */

    dx = plsc->vpwxma - plsc->vpwxmi;
    dy = plsc->vpwyma - plsc->vpwymi;

    plsc->wpxscl = (plsc->vppxma - plsc->vppxmi) / dx;
    plsc->wpxoff = (xmax * plsc->vppxmi - xmin * plsc->vppxma) / dx;
    plsc->wpyscl = (plsc->vppyma - plsc->vppymi) / dy;
    plsc->wpyoff = (ymax * plsc->vppymi - ymin * plsc->vppyma) / dy;

    mmxmi = plP_dcmmx(plsc->vpdxmi);
    mmxma = plP_dcmmx(plsc->vpdxma);
    mmymi = plP_dcmmy(plsc->vpdymi);
    mmyma = plP_dcmmy(plsc->vpdyma);

/* Set transformation variables for world coordinates to mm */

    plsc->wmxscl = (mmxma - mmxmi) / dx;
    plsc->wmxoff = (xmax * mmxmi - xmin * mmxma) / dx;
    plsc->wmyscl = (mmyma - mmymi) / dy;
    plsc->wmyoff = (ymax * mmymi - ymin * mmyma) / dy;

/* Set transformation variables for world coordinates to device coords */

    plsc->wdxscl = plsc->wmxscl * plsc->xpmm / (plsc->phyxma - plsc->phyxmi);
    plsc->wdxoff = plsc->wmxoff * plsc->xpmm / (plsc->phyxma - plsc->phyxmi);
    plsc->wdyscl = plsc->wmyscl * plsc->ypmm / (plsc->phyyma - plsc->phyymi);
    plsc->wdyoff = plsc->wmyoff * plsc->ypmm / (plsc->phyyma - plsc->phyymi);

/* Register plot window attributes */

    w.dxmi = plsc->vpdxmi;
    w.dxma = plsc->vpdxma;
    w.dymi = plsc->vpdymi;
    w.dyma = plsc->vpdyma;

    w.wxmi = plsc->vpwxmi;
    w.wxma = plsc->vpwxma;
    w.wymi = plsc->vpwymi;
    w.wyma = plsc->vpwyma;

    plP_swin(&w);

/* Go to level 3 */

    plsc->level = 3;
}

/*--------------------------------------------------------------------------*\
 * void plw3d()
 *
 * Set up a window for three-dimensional plotting. The data are mapped
 * into a box with world coordinate size "basex" by "basey" by "height",
 * with the base being symmetrically positioned about zero. Thus
 * the mapping between data 3-d and world 3-d coordinates is given by:
 *
 *   x = xmin   =>   wx = -0.5*basex
 *   x = xmax   =>   wx =  0.5*basex
 *   y = ymin   =>   wy = -0.5*basey
 *   y = ymax   =>   wy =  0.5*basey
 *   z = zmin   =>   wz =  0.0
 *   z = zmax   =>   wz =  height
 *
 * The world coordinate box is then viewed from position "alt"-"az",
 * measured in degrees. For proper operation, 0 <= alt <= 90 degrees,
 * but az can be any value.
\*--------------------------------------------------------------------------*/

void
c_plw3d(PLFLT basex, PLFLT basey, PLFLT height, PLFLT xmin0,
	PLFLT xmax0, PLFLT ymin0, PLFLT ymax0, PLFLT zmin0,
	PLFLT zmax0, PLFLT alt, PLFLT az)
{
    PLFLT xmin, xmax, ymin, ymax, zmin, zmax, d;
    PLFLT cx, cy, saz, caz, salt, calt, zscale;

    if (plsc->level < 3) {
	plabort("plw3d: Please set up 2-d window first");
	return;
    }
    if (basex <= 0.0 || basey <= 0.0 || height <= 0.0) {
	plabort("plw3d: Invalid world coordinate boxsize");
	return;
    }
    if (xmin0 == xmax0 || ymin0 == ymax0 || zmin0 == zmax0) {
	plabort("plw3d: Invalid axis range");
	return;
    }
    if (alt < 0.0 || alt > 90.0) {
	plabort("plw3d: Altitude must be between 0 and 90 degrees");
	return;
    }

    d = 1.0e-5 * (xmax0 - xmin0);
    xmax = xmax0 + d;
    xmin = xmin0 - d;
    d = 1.0e-5 * (ymax0 - ymin0);
    ymax = ymax0 + d;
    ymin = ymin0 - d;
    d = 1.0e-5 * (zmax0 - zmin0);
    zmax = zmax0 + d;
    zmin = zmin0 - d;
    cx = basex / (xmax - xmin);
    cy = basey / (ymax - ymin);
    zscale = height / (zmax - zmin);
    saz = sin(dtr * az);
    caz = cos(dtr * az);
    salt = sin(dtr * alt);
    calt = cos(dtr * alt);

    plsc->domxmi = xmin;
    plsc->domxma = xmax;
    plsc->domymi = ymin;
    plsc->domyma = ymax;
    plsc->zzscl = zscale;
    plsc->ranmi = zmin;
    plsc->ranma = zmax;

    plsc->base3x = basex;
    plsc->base3y = basey;
    plsc->basecx = 0.5 * (xmin + xmax);
    plsc->basecy = 0.5 * (ymin + ymax);
/* Mathematical explanation of the 3 transformations of coordinates:
 * (I) Scaling:
 *     x' = cx*(x-x_mid) = cx*(x-plsc->basecx)
 *     y' = cy*(y-y_mid) = cy*(y-plsc->basecy)
 *     z' = zscale*(z-zmin) = zscale*(z-plsc->ranmi)
 * (II) Rotation about z' axis clockwise by the angle of the azimut when 
 *      looking from the top in a right-handed coordinate system.
 *     x''          x'
 *     y'' =  M_1 * y'
 *     z''          z'
 *    where the rotation matrix M_1 (see any mathematical physics book such
 *    as Mathematical Methods in the Physical Sciences by Boas) is
 *    caz          -saz       0
 *    saz           caz       0
 *     0             0        1 
 * (III) Rotation about x'' axis by 90 deg - alt to bring z''' axis 
 *      coincident with line of sight and x''' and y''' corresponding to
 *      x and y coordinates in the 2D plane of the plot.
 *     x'''          x''
 *     y''' =  M_2 * y''
 *     z'''          z''
 *    where the rotation matrix M_2 is
 *     1            0         0
 *     0           salt      calt
 *     0          -calt      salt
 * Note
 *     x'''          x'
 *     y''' =  M *   y'
 *     z'''          z'
 * where M = M_2*M_1 is given by
 *          caz      -saz     0
 *     salt*saz  salt*caz    calt
 *    -calt*saz -calt*caz    salt
 * plP_w3wcx and plP_w3wcy take the combination of the plsc->basecx,
 * plsc->basecy, plsc->ranmi, plsc->cxx, plsc->cxy, plsc->cyx, plsc->cyy, and
 * plsc->cyz data stored here to implement the combination of the 3 
 * transformations to determine x''' and y''' from x, y, and z.
 */   
    plsc->cxx = cx * caz;
    plsc->cxy = -cy * saz;
    plsc->cyx = cx * saz * salt;
    plsc->cyy = cy * caz * salt;
    plsc->cyz = zscale * calt;
}


syntax highlighted by Code2HTML, v. 0.9.1