blob: 5b22fc4dbdc6576b6a78e5c91de3effba0b72746 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.lucene.spatial3d.geom;
/**
* Combination of a plane, and a sign value indicating what evaluation values are on the correct
* side of the plane.
*
* @lucene.experimental
*/
public class SidedPlane extends Plane implements Membership {
/** The sign value for evaluation of a point on the correct side of the plane */
public final double sigNum;
/**
* Construct a SidedPlane identical to an existing one, but reversed.
*
* @param sidedPlane is the existing plane.
*/
public SidedPlane(final SidedPlane sidedPlane) {
super(sidedPlane, sidedPlane.D);
this.sigNum = -sidedPlane.sigNum;
}
/**
* Construct a sided plane from a pair of vectors describing points, and including
* origin, plus a point p which describes the side.
*
* @param pX point X to evaluate
* @param pY point Y to evaluate
* @param pZ point Z to evaluate
* @param A is the first in-plane point
* @param B is the second in-plane point
*/
public SidedPlane(final double pX, final double pY, final double pZ, final Vector A, final Vector B) {
super(A, B);
sigNum = Math.signum(evaluate(pX, pY, pZ));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane from a pair of vectors describing points, and including
* origin, plus a point p which describes the side.
*
* @param p point to evaluate
* @param A is the first in-plane point
* @param B is the second in-plane point
*/
public SidedPlane(final Vector p, final Vector A, final Vector B) {
super(A, B);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane from a pair of vectors describing points, and including
* origin. Choose the side arbitrarily.
*
* @param A is the first in-plane point
* @param B is the second in-plane point
*/
public SidedPlane(final Vector A, final Vector B) {
super(A, B);
sigNum = 1.0;
}
/**
* Construct a sided plane from a pair of vectors describing points, and including
* origin, plus a point p which describes the side.
*
* @param p point to evaluate
* @param A is the first in-plane point
* @param BX is the X value of the second in-plane point
* @param BY is the Y value of the second in-plane point
* @param BZ is the Z value of the second in-plane point
*/
public SidedPlane(final Vector p, final Vector A, final double BX, final double BY, final double BZ) {
super(A, BX, BY, BZ);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane from a pair of vectors describing points, and including
* origin, plus a point p which describes the side.
*
* @param p point to evaluate
* @param onSide is true if the point is on the correct side of the plane, false otherwise.
* @param A is the first in-plane point
* @param B is the second in-plane point
*/
public SidedPlane(final Vector p, final boolean onSide, final Vector A, final Vector B) {
super(A, B);
sigNum = onSide?Math.signum(evaluate(p)):-Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane from a point and a Z coordinate.
*
* @param p point to evaluate.
* @param planetModel is the planet model.
* @param sinLat is the sin of the latitude of the plane.
*/
public SidedPlane(Vector p, final PlanetModel planetModel, double sinLat) {
super(planetModel, sinLat);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided vertical plane from a point and specified x and y coordinates.
*
* @param p point to evaluate.
* @param x is the specified x.
* @param y is the specified y.
*/
public SidedPlane(Vector p, double x, double y) {
super(x, y);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane with a normal vector and offset.
*
* @param p point to evaluate.
* @param vX is the normal vector X.
* @param vY is the normal vector Y.
* @param vZ is the normal vector Z.
* @param D is the origin offset for the plan.
*/
public SidedPlane(Vector p, double vX, double vY, double vZ, double D) {
super(vX, vY, vZ, D);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane with a normal vector and offset.
*
* @param p point to evaluate.
* @param v is the normal vector.
* @param D is the origin offset for the plan.
*/
public SidedPlane(Vector p, Vector v, double D) {
super(v, D);
sigNum = Math.signum(evaluate(p));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/**
* Construct a sided plane with a normal vector and offset.
*
* @param pX X coord of point to evaluate.
* @param pY Y coord of point to evaluate.
* @param pZ Z coord of point to evaluate.
* @param v is the normal vector.
* @param D is the origin offset for the plan.
*/
public SidedPlane(double pX, double pY, double pZ, Vector v, double D) {
super(v, D);
sigNum = Math.signum(evaluate(pX,pY,pZ));
if (sigNum == 0.0)
throw new IllegalArgumentException("Cannot determine sidedness because check point is on plane.");
}
/** Construct a sided plane from two points and a third normal vector.
*/
public static SidedPlane constructNormalizedPerpendicularSidedPlane(final Vector insidePoint,
final Vector normalVector, final Vector point1, final Vector point2) {
final Vector pointsVector = new Vector(point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
final Vector newNormalVector = new Vector(normalVector, pointsVector);
try {
// To construct the plane, we now just need D, which is simply the negative of the evaluation of the circle normal vector at one of the points.
return new SidedPlane(insidePoint, newNormalVector, -newNormalVector.dotProduct(point1));
} catch (IllegalArgumentException e) {
return null;
}
}
/** Construct a sided plane from three points.
*/
public static SidedPlane constructNormalizedThreePointSidedPlane(final Vector insidePoint,
final Vector point1, final Vector point2, final Vector point3) {
SidedPlane rval = null;
if (rval == null) {
try {
final Vector planeNormal = new Vector(
point1.x - point2.x, point1.y - point2.y, point1.z - point2.z,
point2.x - point3.x, point2.y - point3.y, point2.z - point3.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point2));
} catch (IllegalArgumentException e) {
}
}
if (rval == null) {
try {
final Vector planeNormal = new Vector(
point1.x - point3.x, point1.y - point3.y, point1.z - point3.z,
point3.x - point2.x, point3.y - point2.y, point3.z - point2.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point3));
} catch (IllegalArgumentException e) {
}
}
if (rval == null) {
try {
final Vector planeNormal = new Vector(
point3.x - point1.x, point3.y - point1.y, point3.z - point1.z,
point1.x - point2.x, point1.y - point2.y, point1.z - point2.z);
rval = new SidedPlane(insidePoint, planeNormal, -planeNormal.dotProduct(point1));
} catch (IllegalArgumentException e) {
}
}
return rval;
}
@Override
public boolean isWithin(double x, double y, double z) {
double evalResult = evaluate(x, y, z);
//System.out.println(Math.abs(evalResult));
if (Math.abs(evalResult) < MINIMUM_RESOLUTION)
return true;
double sigNum = Math.signum(evalResult);
return sigNum == this.sigNum;
}
/**
* Check whether a point is strictly within a plane.
* @param v is the point.
* @return true if within.
*/
public boolean strictlyWithin(final Vector v) {
double evalResult = evaluate(v.x, v.y, v.z);
double sigNum = Math.signum(evalResult);
return sigNum == 0.0 || sigNum == this.sigNum;
}
/**
* Check whether a point is strictly within a plane.
* @param x is the point x value.
* @param y is the point y value.
* @param z is the point z value.
* @return true if within.
*/
public boolean strictlyWithin(double x, double y, double z) {
double evalResult = evaluate(x, y, z);
double sigNum = Math.signum(evalResult);
return sigNum == 0.0 || sigNum == this.sigNum;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SidedPlane)) return false;
if (!super.equals(o)) return false;
SidedPlane that = (SidedPlane) o;
return Double.compare(that.sigNum, sigNum) == 0;
}
@Override
public int hashCode() {
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(sigNum);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public String toString() {
return "[A=" + x + ", B=" + y + ", C=" + z + ", D=" + D + ", side=" + sigNum + "]";
}
}