/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.display2d;
/*----------------------------------------------------------------------------------------*
* Projector.java version 1.7 Nov 8 1996 *
* Projector.java version 1.71 May 14 1997 *
* *
* Copyright (c) 1996 Yanto Suryono. All Rights Reserved. *
* *
* Permission to use, copy, and distribute this software for NON-COMMERCIAL purposes *
* and without fee is hereby granted provided that this copyright notice appears in all *
* copies and this software is not modified in any way *
* *
* Please send bug reports and/or corrections/suggestions to *
* Yanto Suryono <d0771@cranesv.egg.kushiro-ct.ac.jp> *
*----------------------------------------------------------------------------------------*/
import java.awt.Point;
import java.awt.Rectangle;
/**
* The class <code>Projector</code> projects points in 3D space to 2D space.
*
* @author Yanto Suryono
* @version 1.71, 17 May 1997
*/
public final class SurfacePlotProjector {
private double scale_x, scale_y, scale_z; // 3D scaling factor
private double distance; // distance to object
private double _2D_scale; // 2D scaling factor
private double rotation, elevation; // rotation and elevation angle
private double sin_rotation, cos_rotation; // sin and cos of rotation angle
private double sin_elevation, cos_elevation; // sin and cos of elevation angle
private int _2D_trans_x, _2D_trans_y; // 2D translation
private int x1, x2, y1, y2; // projection area
private int center_x, center_y; // center of projection area
private int trans_x, trans_y;
private double factor;
private double sx_cos, sy_cos, sz_cos;
private double sx_sin, sy_sin, sz_sin;
private final double DEGTORAD = Math.PI/180;
/**
* The constructor of <code>Projector</code>.
*/
SurfacePlotProjector() {
setScaling(1);
setRotationAngle(0);
setElevationAngle(0);
setDistance(10);
set2DScaling(1);
set2DTranslation(0, 0);
}
/**
* Sets the projection area.
*
* @param r the projection area
*/
public void setProjectionArea(Rectangle r) {
x1 = r.x;
x2 = x1+r.width;
y1 = r.y;
y2 = y1+r.height;
center_x = (x1+x2)/2;
center_y = (y1+y2)/2;
trans_x = center_x+_2D_trans_x;
trans_y = center_y+_2D_trans_y;
}
/**
* Sets the rotation angle.
*
* @param angle the rotation angle in degrees
*/
public void setRotationAngle(double angle) {
rotation = angle;
sin_rotation = Math.sin(angle*DEGTORAD);
cos_rotation = Math.cos(angle*DEGTORAD);
sx_cos = -scale_x*cos_rotation;
sx_sin = -scale_x*sin_rotation;
sy_cos = -scale_y*cos_rotation;
sy_sin = scale_y*sin_rotation;
}
/**
* Gets current rotation angle.
*
* @return the rotation angle in degrees.
*/
public double getRotationAngle() {
return rotation;
}
/**
* Gets the sine of rotation angle.
*
* @return the sine of rotation angle
*/
public double getSinRotationAngle() {
return sin_rotation;
}
/**
* Gets the cosine of rotation angle.
*
* @return the cosine of rotation angle
*/
public double getCosRotationAngle() {
return cos_rotation;
}
/**
* Sets the elevation angle.
*
* @param angle the elevation angle in degrees
*/
public void setElevationAngle(double angle) {
elevation = angle;
sin_elevation = Math.sin(angle*DEGTORAD);
cos_elevation = Math.cos(angle*DEGTORAD);
sz_cos = scale_z*cos_elevation;
sz_sin = scale_z*sin_elevation;
}
/**
* Gets current elevation angle.
*
* @return the elevation angle in degrees.
*/
public double getElevationAngle() {
return elevation;
}
/**
* Gets the sine of elevation angle.
*
* @return the sine of elevation angle
*/
public double getSinElevationAngle() {
return sin_elevation;
}
/**
* Gets the cosine of elevation angle.
*
* @return the cosine of elevation angle
*/
public double getCosElevationAngle() {
return cos_elevation;
}
/**
* Sets the projector distance.
*
* @param new_distance the new distance
*/
public void setDistance(double new_distance) {
distance = new_distance;
factor = distance*_2D_scale;
}
/**
* Gets the projector distance.
*
* @return the projector distance
*/
public double getDistance() {
return distance;
}
/**
* Sets the scaling factor in x direction.
*
* @param scaling the scaling factor
*/
public void setXScaling(double scaling) {
scale_x = scaling;
sx_cos = -scale_x*cos_rotation;
sx_sin = -scale_x*sin_rotation;
}
/**
* Gets the scaling factor in x direction.
*
* @return the scaling factor
*/
public double getXScaling() {
return scale_x;
}
/**
* Sets the scaling factor in y direction.
*
* @param scaling the scaling factor
*/
public void setYScaling(double scaling) {
scale_y = scaling;
sy_cos = -scale_y*cos_rotation;
sy_sin = scale_y*sin_rotation;
}
/**
* Gets the scaling factor in y direction.
*
* @return the scaling factor
*/
public double getYScaling() {
return scale_y;
}
/**
* Sets the scaling factor in z direction.
*
* @param scaling the scaling factor
*/
public void setZScaling(double scaling) {
scale_z = scaling;
sz_cos = scale_z*cos_elevation;
sz_sin = scale_z*sin_elevation;
}
/**
* Gets the scaling factor in z direction.
*
* @return the scaling factor
*/
public double getZScaling() {
return scale_z;
}
/**
* Sets the scaling factor in all direction.
*
* @param x the scaling factor in x direction
* @param y the scaling factor in y direction
* @param z the scaling factor in z direction
*/
public void setScaling(double x, double y, double z) {
scale_x = x;
scale_y = y;
scale_z = z;
sx_cos = -scale_x*cos_rotation;
sx_sin = -scale_x*sin_rotation;
sy_cos = -scale_y*cos_rotation;
sy_sin = scale_y*sin_rotation;
sz_cos = scale_z*cos_elevation;
sz_sin = scale_z*sin_elevation;
}
/**
* Sets the same scaling factor for all direction.
*
* @param scaling the scaling factor
*/
public void setScaling(double scaling) {
scale_x = scale_y = scale_z = scaling;
sx_cos = -scale_x*cos_rotation;
sx_sin = -scale_x*sin_rotation;
sy_cos = -scale_y*cos_rotation;
sy_sin = scale_y*sin_rotation;
sz_cos = scale_z*cos_elevation;
sz_sin = scale_z*sin_elevation;
}
/**
* Sets the 2D scaling factor.
*
* @param scaling the scaling factor
*/
public void set2DScaling(double scaling) {
_2D_scale = scaling;
factor = distance*_2D_scale;
}
/**
* Gets the 2D scaling factor.
*
* @return the scaling factor
*/
public double get2DScaling() {
return _2D_scale;
}
/**
* Sets the 2D translation.
*
* @param x the x translation
* @param y the y translation
*/
public void set2DTranslation(int x, int y) {
_2D_trans_x = x;
_2D_trans_y = y;
trans_x = center_x+_2D_trans_x;
trans_y = center_y+_2D_trans_y;
}
/**
* Sets the 2D x translation.
*
* @param x the x translation
*/
public void set2D_xTranslation(int x) {
_2D_trans_x = x;
trans_x = center_x+_2D_trans_x;
}
/**
* Gets the 2D x translation.
*
* @return the x translation
*/
public int get2D_xTranslation() {
return _2D_trans_x;
}
/**
* Sets the 2D y translation.
*
* @param y the y translation
*/
public void set2D_yTranslation(int y) {
_2D_trans_y = y;
trans_y = center_y+_2D_trans_y;
}
/**
* Gets the 2D y translation.
*
* @return the y translation
*/
public int get2D_yTranslation() {
return _2D_trans_y;
}
/**
* Projects 3D points.
*
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
*/
public final Point project(double x, double y, double z) {
double temp;
// rotates
temp = x;
x = x*sx_cos+y*sy_sin;
y = temp*sx_sin+y*sy_cos;
// elevates and projects
temp = factor/(y*cos_elevation-z*sz_sin+distance);
return new Point((int) (Math.round(x*temp)+trans_x), (int) (Math.round((y*sin_elevation+z*sz_cos)*-temp)+trans_y));
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/