/*
* (C) 2004 - Geotechnical Software Services
*
* This code is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This code 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
package no.geosoft.cc.graphics;
import no.geosoft.cc.geometry.Geometry;
/**
* This class represent a client 3D plane world extent. The world extent
* is defined by three points as follows:
*
* <pre>
* w2 o
* |
* |
* |
* w0 o-------o w1
* </pre>
*
* Each point is a 3D coordinate [x,y,z]. A typical world extent will have
* w0[y] == w1[y], w0[x] == w2[x] and all z coordinates == 0, but the
* definition makes it possible to use any planar suerface in 3D space
* as world extent.
* <p>
* Clients sets world extent on a scene through the
* <tt>GScene.setWorldExtent()</tt> methods.
*
* @see GScene#setWorldExtent (double[], double[], double[]).
* @see GScene#setWorldExtent (double, double, double, double).
*
* @author <a href="mailto:info@geosoft.no">GeoSoft</a>
*/
public class GWorldExtent
{
// To enhance indexing readability
private static final int X = 0;
private static final int Y = 1;
private static final int Z = 2;
double w0_[], w1_[], w2_[]; // [x,y,z]
/**
* Create a world extent specified by three coordinates as follows:
*
* <pre>
* w2 o
* |
* |
* |
* w0 o-------o w1
* </pre>
*
* @param w0 First world extent coordinate [x,y,z].
* @param w1 Second world extent coordinate [x,y,z].
* @param w2 Third world extent coordinate [x,y,z].
*/
GWorldExtent (double w0[], double w1[], double w2[])
{
w0_ = new double[3];
w1_ = new double[3];
w2_ = new double[3];
set (w0, w1, w2);
}
/**
* Create a default (normalized) world extent. The normalized
* world extent is in the Z=0 plane with X/Y extents [0.0 - 1.0].
*/
GWorldExtent()
{
this (new double[] {0.0, 0.0, 0.0},
new double[] {1.0, 0.0, 0.0},
new double[] {0.0, 1.0, 0.0});
}
/**
* Create a world extent as a copy of the specified world extent.
*
* @param worldExtent World extent to copy.
*/
GWorldExtent (GWorldExtent worldExtent)
{
this (worldExtent.get(0), worldExtent.get(1), worldExtent.get(2));
}
/**
* Set the three world extent coordinates.
*
* @param w0 Coordinate 0 of world extent [x,y,z].
* @param w1 Coordinate 1 of world extent [x,y,z].
* @param w2 Coordinate 2 of world extent [x,y,z].
*/
void set (double w0[], double w1[], double w2[])
{
for (int i = 0; i < 3; i++) {
w0_[i] = w0[i];
w1_[i] = w1[i];
w2_[i] = w2[i];
}
}
/**
* Return world extent coordinate of specified index.
*
* @param index index of coordinate to get.
* @return Coordinate of point at index [x,y,z].
*/
public double[] get (int index)
{
switch (index) {
case 0 : return w0_;
case 1 : return w1_;
case 2 : return w2_;
}
throw new ArrayIndexOutOfBoundsException (index);
}
/**
* Resize this viewport a specified fraction in X and Y direction.
*
* @param dx Fraction to resize in X direction.
* @param dy Fraction to resize in Y direction.
*/
void resize (double dx, double dy)
{
double newWidth = getWidth() * dx;
double newHeight = getHeight() * dy;
extendWidth (newWidth);
extendHeight (newHeight);
}
/**
* Check if this world extent is in an XY plane (i.e. all Z coordinates
* are the same).
*
* @return True if this world extent is in the XY plane, false otherwise.
*/
boolean isXyPlane()
{
return w0_[Z] == w1_[Z] && w0_[Z] == w2_[Z];
}
/**
* Check if this world extent is in an XZ plane (i.e. all Y coordinates
* are the same).
*
* @return True if this world extent is in the XZ plane, false otherwise.
*/
boolean isXzPlane()
{
return w0_[Y] == w1_[Y] && w0_[Y] == w2_[Y];
}
/**
* Check if this world extent is in an YZ plane (i.e. all X coordinates
* are the same).
*
* @return True if this world extent is in the YZ plane, false otherwise.
*/
boolean isYzPlane()
{
return w0_[X] == w1_[X] && w0_[X] == w2_[X];
}
/**
* Return width of this world extent.
*
* @return Width of this world extent.
*/
public double getWidth()
{
return Geometry.length (w0_, w1_);
}
/**
* Return height of this world extent.
*
* @return Height of this world extent.
*/
public double getHeight()
{
return Geometry.length (w0_, w2_);
}
/**
* Recompute this world extent to the specified width. Width is defined
* as the length between w0 and w1.
* The world extent is resized equally in each direction.
*
* @param newWidth New width of this world extent.
*/
void extendWidth (double newWidth)
{
double oldW0[] = new double[3];
oldW0[X] = w0_[X];
oldW0[Y] = w0_[Y];
oldW0[Z] = w0_[Z];
Geometry.extendLine (w0_, w1_, newWidth, 0.5);
double dx = w0_[X] - oldW0[X];
double dy = w0_[Y] - oldW0[Y];
double dz = w0_[Z] - oldW0[Z];
w2_[X] += dx;
w2_[Y] += dy;
w2_[Z] += dz;
}
/**
* Recompute this world extent to the specified height. Height is defined
* as the length between w0 and w2.
* The world extent is resized equally in each direction.
*
* @param newHeight New height of this world extent.
*/
void extendHeight (double newHeight)
{
double oldW0[] = new double[3];
oldW0[X] = w0_[X];
oldW0[Y] = w0_[Y];
oldW0[Z] = w0_[Z];
Geometry.extendLine (w0_, w2_, newHeight, 0.5);
double dx = w0_[X] - oldW0[X];
double dy = w0_[Y] - oldW0[Y];
double dz = w0_[Z] - oldW0[Z];
w1_[X] += dx;
w1_[Y] += dy;
w1_[Z] += dz;
}
}