/*******************************************************************************
* Copyright 2010 Simon Mieth
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.kabeja.math;
public class ParametricPlane {
protected Point3D base;
protected Vector directionX;
protected Vector directionY;
protected Vector normal;
/**
*
* @param basePoint
* The base point of this plane
* @param directionX
* the x direction of this plane
* @param directionY
* the y direction of this plane
* @param normal
* the normal direction of this plane
*/
public ParametricPlane(Point3D basePoint, Vector directionX,
Vector directionY, Vector normal) {
this.base = basePoint;
this.directionX = directionX;
this.directionY = directionY;
this.normal = normal;
}
/**
*
* @param basePoint
* The base point of this plane
* @param directionX
* the x direction of this plane
* @param directionY
* the y direction of this plane
*/
public ParametricPlane(Point3D basePoint, Vector directionX, Vector directionY) {
this(basePoint, directionX, directionY,
MathUtils.normalize(MathUtils.crossProduct(directionX, directionY)));
}
/**
* Generates a plane with the base point and uses the vector from base point
* to b as x direction. The y direction is generated with the cross product
* of the normal with the x direction.
*
* @param basePoint
* @param b
* @param normal
*/
public ParametricPlane(Point3D basePoint, Point3D b, Vector normal) {
this(basePoint, MathUtils.normalize(MathUtils.getVector(basePoint, b)),
MathUtils.normalize(MathUtils.crossProduct(normal,
MathUtils.normalize(MathUtils.getVector(basePoint, b)))),
normal);
}
public ParametricPlane(Point3D basePoint, Point3D b, Point3D c) {
this(basePoint, MathUtils.normalize(MathUtils.getVector(basePoint, b)),
MathUtils.normalize(MathUtils.getVector(basePoint, c)));
}
public ParametricPlane(Extrusion e) {
this(new Point3D(0.0, 0.0, 0.0), e.getDirectionX(), e.getDirectionY(),
e.getNormal());
}
/**
* Calculate the point in world coordinates for the given parameters
*
* @param x
* @param y
* @return
*/
public Point3D getPoint(double x, double y) {
Point3D p = new Point3D();
p.setX(this.base.getX() + (this.directionX.getX() * x) +
(this.directionY.getX() * y));
p.setY(this.base.getY() + (this.directionX.getY() * x) +
(this.directionY.getY() * y));
p.setZ(this.base.getZ() + (this.directionX.getZ() * x) +
(this.directionY.getZ() * y));
return p;
}
public Point3D getPoint(Point3D point) {
return getPoint(point.getX(), point.getY());
}
/**
* Calculates the plane parameters of the given point relative to the base
* point of the plane
*
* @param p
* @return double[]{parameter x direction, parameter y direction}
*/
public double[] getParameter(Point3D p) {
double u = 0.0;
double v = (this.directionX.getY() * this.directionY.getX()) -
(this.directionX.getX() * this.directionY.getY());
if (v != 0.0) {
v = ((p.getY() * this.directionY.getX()) -
(this.base.getY() * this.directionY.getX()) -
(this.directionY.getY() * p.getX()) +
(this.base.getX() * this.directionY.getY())) / v;
}
if (this.directionY.getX() != 0.0) {
u = (p.getX() - this.base.getX() - (this.directionX.getX() * v)) / this.directionY.getX();
} else if (this.directionY.getY() != 0.0) {
u = (p.getY() - this.base.getY() - (this.directionX.getY() * v)) / this.directionY.getY();
} else if (this.directionY.getY() != 0.0) {
u = (p.getZ() - this.base.getZ() - (this.directionX.getZ() * v)) / this.directionY.getZ();
}
return new double[] { v, u };
}
/**
* Determines if the given point lies on the plane.
*
* @param p
* the point to determine
* @return true if the point lies on the plane, otherwise false.
*/
public boolean isOnPlane(Point3D p) {
double[] para = this.getParameter(p);
double v = this.base.getZ() + (this.directionX.getZ() * para[0]) +
(this.directionY.getZ() * para[1]);
if (!(Math.abs((p.getZ() - v)) < MathUtils.DISTANCE_DELTA)) {
return false;
}
v = this.base.getY() + (this.directionX.getY() * para[0]) +
(this.directionY.getY() * para[1]);
if (!(Math.abs((p.getY() - v)) < MathUtils.DISTANCE_DELTA)) {
return false;
}
v = this.base.getX() + (this.directionX.getX() * para[0]) +
(this.directionY.getX() * para[1]);
if (!(Math.abs((p.getX() - v)) < MathUtils.DISTANCE_DELTA)) {
return false;
}
return true;
}
public Point3D getBasePoint() {
return base;
}
public void setBasePoint(Point3D base) {
this.base = base;
}
public Vector getDirectionX() {
return directionX;
}
public void setDirectionX(Vector directionX) {
this.directionX = directionX;
this.normal = MathUtils.crossProduct(this.directionX, this.directionY);
this.normal.normalize();
}
public Vector getDirectionY() {
return directionY;
}
public void setDirectionY(Vector directionY) {
this.directionY = directionY;
this.normal = MathUtils.crossProduct(this.directionX, this.directionY);
this.normal.normalize();
}
public Vector getNormal() {
return normal;
}
}