![JAR search and dependency download from the Maven repository](/logo.png)
org.meteoinfo.chart.plot3d.Projector Maven / Gradle / Ivy
/*----------------------------------------------------------------------------------------*
* Projector.java version 1.7 Nov 8 1996 *
* Projector.java version 1.71 May 14 1997 *
* *
* Copyright (c) Yanto Suryono *
* *
* This program 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 of the License, or (at your option) *
* any later version. *
* *
* This program 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 org.meteoinfo.chart.plot3d;
import org.meteoinfo.data.DataMath;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* The class Projector
projects points in 3D space to 2D space.
*
* @author Yanto Suryono
*/
public final class Projector {
private float scale_x, scale_y, scale_z; // 3D scaling factor
private float distance; // distance to object
private float _2D_scale_x, _2D_scale_y; // 2D scaling factor
private float rotation, elevation; // rotation and elevation angle
private float sin_rotation, cos_rotation; // sin and cos of rotation angle
private float 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 float factor_x, factor_y;
private float sx_cos, sy_cos, sz_cos;
private float sx_sin, sy_sin, sz_sin;
private final float DEGTORAD = (float) Math.PI / 180;
//was static in SurfaceVertex ! now Dynamic in Projector
float zmin, zmax;
float zfactor;
/**
* The constructor of Projector
.
*/
public Projector() {
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;
this.update2DScaling();
}
/**
* Sets the rotation angle.
*
* @param angle the rotation angle in degrees
*/
public void setRotationAngle(float angle) {
rotation = angle;
sin_rotation = (float) Math.sin(angle * DEGTORAD);
cos_rotation = (float) 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 float getRotationAngle() {
return rotation;
}
/**
* Gets the sine of rotation angle.
*
* @return the sine of rotation angle
*/
public float getSinRotationAngle() {
return sin_rotation;
}
/**
* Gets the cosine of rotation angle.
*
* @return the cosine of rotation angle
*/
public float getCosRotationAngle() {
return cos_rotation;
}
/**
* Sets the elevation angle.
*
* @param angle the elevation angle in degrees
*/
public void setElevationAngle(float angle) {
elevation = angle;
sin_elevation = (float) Math.sin(angle * DEGTORAD);
cos_elevation = (float) 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 float getElevationAngle() {
return elevation;
}
/**
* Gets the sine of elevation angle.
*
* @return the sine of elevation angle
*/
public float getSinElevationAngle() {
return sin_elevation;
}
/**
* Gets the cosine of elevation angle.
*
* @return the cosine of elevation angle
*/
public float getCosElevationAngle() {
return cos_elevation;
}
/**
* Sets the projector distance.
*
* @param new_distance the new distance
*/
public void setDistance(float new_distance) {
distance = new_distance;
factor_x = distance * _2D_scale_x;
}
/**
* Gets the projector distance.
*
* @return the projector distance
*/
public float getDistance() {
return distance;
}
/**
* Sets the scaling factor in x direction.
*
* @param scaling the scaling factor
*/
public void setXScaling(float 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 float getXScaling() {
return scale_x;
}
/**
* Sets the scaling factor in y direction.
*
* @param scaling the scaling factor
*/
public void setYScaling(float 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 float getYScaling() {
return scale_y;
}
/**
* Sets the scaling factor in z direction.
*
* @param scaling the scaling factor
*/
public void setZScaling(float 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 float 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(float x, float y, float 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(float 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(float scaling) {
_2D_scale_x = scaling;
_2D_scale_y = scaling;
factor_x = distance * _2D_scale_x;
factor_y = distance * _2D_scale_y;
}
/**
* Sets the x 2D scaling factor.
*
* @param scaling the x scaling factor
*/
public void setX2DScaling(float scaling) {
_2D_scale_x = scaling;
factor_x = distance * _2D_scale_x;
}
/**
* Sets the 2D scaling factor.
*
* @param scaling the scaling factor
*/
public void setY2DScaling(float scaling) {
_2D_scale_y = scaling;
factor_y = distance * _2D_scale_y;
}
/**
* Gets the x 2D scaling factor.
*
* @return the x scaling factor
*/
public float getX2DScaling() {
return _2D_scale_x;
}
/**
* Gets the x 2D scaling factor.
*
* @return the x scaling factor
*/
public float getY2DScaling() {
return _2D_scale_y;
}
/**
* 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
* @return Projected point
*/
public final Point project(float x, float y, float z) {
float temp;
// rotates
temp = x;
x = x * sx_cos + y * sy_sin;
y = temp * sx_sin + y * sy_cos;
// elevates and projects
//float temp_x = factor_x / (x * sin_elevation - z * sz_sin + distance);
float temp_x = factor_x / (y * cos_elevation - z * sz_sin + distance);
float temp_y = factor_y / (y * cos_elevation - z * sz_sin + distance);
return new Point((int) (Math.round(x * temp_x) + trans_x),
(int) (Math.round((y * sin_elevation + z * sz_cos) * -temp_y) + trans_y));
}
/**
* Project angle and length from two points
* @param x1 Point 1 x
* @param y1 Point 1 y
* @param z1 Point 1 z
* @param x2 Point 2 x
* @param y2 Point 2 y
* @param z2 Point 2 z
* @return Angle and length
*/
public double[] projectAL(float x1, float y1, float z1, float x2, float y2, float z2){
Point p1 = project(x1, y1, z1);
Point p2 = project(x2, y2, z2);
float u = p2.x - p1.x;
float v = p2.y - p1.y;
return DataMath.getDSFromUV(u, v);
}
/**
* Projects 3D points without scaling.
*
* @param x the x coordinate
* @param y the y coordinate
* @param z the z coordinate
* @return Projected point
*/
public final Point project_noScale(float x, float y, float z) {
float temp;
// rotates
temp = x;
x = x * sx_cos + y * sy_sin;
y = temp * sx_sin + y * sy_cos;
// elevates and projects
return new Point((int) (Math.round(x) + trans_x),
(int) (Math.round((y * sin_elevation + z * sz_cos)) + trans_y));
}
public void setZRange(float zmin, float zmax) {
this.zmin = zmin;
this.zmax = zmax;
this.zfactor = 20 / (zmax - zmin);
}
/**
* Get bounds
* @return Bounds rectangle
*/
public Rectangle getBounds(){
List ps = new ArrayList<>();
ps.add(this.project(10, 10, 10));
ps.add(this.project(-10, 10, 10));
ps.add(this.project(10, -10, 10));
ps.add(this.project(-10, -10, 10));
ps.add(this.project(10, 10, -10));
ps.add(this.project(-10, -10, -10));
ps.add(this.project(-10, 10, -10));
ps.add(this.project(10, -10, -10));
int i = 0;
int minx =0, miny = 0, maxx = 0, maxy = 0;
for (Point p : ps){
if (i == 0){
minx = p.x;
maxx = p.x;
miny = p.y;
maxy = p.y;
} else {
if (minx > p.x)
minx = p.x;
else if (maxx < p.x)
maxx = p.x;
if (miny > p.y)
miny = p.y;
else if (maxy < p.y)
maxy = p.y;
}
i += 1;
}
return new Rectangle(minx, miny, maxx - minx, maxy - miny);
}
/**
* Get bounds without scale
* @return Bounds rectangle
*/
public Rectangle getBounds_noScale(){
List ps = new ArrayList<>();
ps.add(this.project_noScale(10, 10, 10));
ps.add(this.project_noScale(-10, 10, 10));
ps.add(this.project_noScale(10, -10, 10));
ps.add(this.project_noScale(-10, -10, 10));
ps.add(this.project_noScale(10, 10, -10));
ps.add(this.project_noScale(-10, -10, -10));
ps.add(this.project_noScale(-10, 10, -10));
ps.add(this.project_noScale(10, -10, -10));
int i = 0;
int minx =0, miny = 0, maxx = 0, maxy = 0;
for (Point p : ps){
if (i == 0){
minx = p.x;
maxx = p.x;
miny = p.y;
maxy = p.y;
} else {
if (minx > p.x)
minx = p.x;
else if (maxx < p.x)
maxx = p.x;
if (miny > p.y)
miny = p.y;
else if (maxy < p.y)
maxy = p.y;
}
i += 1;
}
return new Rectangle(minx, miny, maxx - minx, maxy - miny);
}
/**
* Update 2D scaling
*/
public void update2DScaling(){
Rectangle rect = this.getBounds();
float s1 = (float)((x2 - x1) / rect.getWidth());
float s2 = (float)((y2 - y1) / rect.getHeight());
s1 = s1 * this._2D_scale_x;
s2 = s2 * this._2D_scale_y;
this.setX2DScaling(s1);
this.setY2DScaling(s2);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy