Added Ray2 and Ray3.
This commit is contained in:
+125
-134
@@ -366,54 +366,45 @@ public class Box implements IBox, Serializable
|
||||
_maxExtent.z >= omin.z() && _minExtent.z <= omax.z();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines whether the specified ray intersects this box.
|
||||
// */
|
||||
// public boolean intersects (Ray3D ray) {
|
||||
// Vector3 dir = ray.direction();
|
||||
// return
|
||||
// Math.abs(dir.x) > MathUtil.EPSILON &&
|
||||
// (intersectsX(ray, _minExtent.x) || intersectsX(ray, _maxExtent.x)) ||
|
||||
// Math.abs(dir.y) > MathUtil.EPSILON &&
|
||||
// (intersectsY(ray, _minExtent.y) || intersectsY(ray, _maxExtent.y)) ||
|
||||
// Math.abs(dir.z) > MathUtil.EPSILON &&
|
||||
// (intersectsZ(ray, _minExtent.z) || intersectsZ(ray, _maxExtent.z));
|
||||
// }
|
||||
@Override // from IBox
|
||||
public boolean intersects (IRay3 ray) {
|
||||
IVector3 dir = ray.direction();
|
||||
return
|
||||
Math.abs(dir.x()) > MathUtil.EPSILON &&
|
||||
(intersectsX(ray, _minExtent.x) || intersectsX(ray, _maxExtent.x)) ||
|
||||
Math.abs(dir.y()) > MathUtil.EPSILON &&
|
||||
(intersectsY(ray, _minExtent.y) || intersectsY(ray, _maxExtent.y)) ||
|
||||
Math.abs(dir.z()) > MathUtil.EPSILON &&
|
||||
(intersectsZ(ray, _minExtent.z) || intersectsZ(ray, _maxExtent.z));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Finds the location of the (first) intersection between the specified ray and this box.
|
||||
// * This will be the ray origin if the ray starts inside the box.
|
||||
// *
|
||||
// * @param result a vector to hold the location of the intersection.
|
||||
// * @return true if the ray intersects the box (in which case the result vector will be
|
||||
// * populated with the location of the intersection), false if not.
|
||||
// */
|
||||
// public boolean intersection (Ray3D ray, Vector3 result) {
|
||||
// Vector3 origin = ray.origin();
|
||||
// if (contains(origin)) {
|
||||
// result.set(origin);
|
||||
// return true;
|
||||
// }
|
||||
// Vector3 dir = ray.direction();
|
||||
// float t = Float.MAX_VALUE;
|
||||
// if (Math.abs(dir.x) > MathUtil.EPSILON) {
|
||||
// t = Math.min(t, intersectionX(ray, _minExtent.x));
|
||||
// t = Math.min(t, intersectionX(ray, _maxExtent.x));
|
||||
// }
|
||||
// if (Math.abs(dir.y) > MathUtil.EPSILON) {
|
||||
// t = Math.min(t, intersectionY(ray, _minExtent.y));
|
||||
// t = Math.min(t, intersectionY(ray, _maxExtent.y));
|
||||
// }
|
||||
// if (Math.abs(dir.z) > MathUtil.EPSILON) {
|
||||
// t = Math.min(t, intersectionZ(ray, _minExtent.z));
|
||||
// t = Math.min(t, intersectionZ(ray, _maxExtent.z));
|
||||
// }
|
||||
// if (t == Float.MAX_VALUE) {
|
||||
// return false;
|
||||
// }
|
||||
// origin.addScaled(dir, t, result);
|
||||
// return true;
|
||||
// }
|
||||
@Override // from IBox
|
||||
public boolean intersection (IRay3 ray, Vector3 result) {
|
||||
IVector3 origin = ray.origin();
|
||||
if (contains(origin)) {
|
||||
result.set(origin);
|
||||
return true;
|
||||
}
|
||||
IVector3 dir = ray.direction();
|
||||
float t = Float.MAX_VALUE;
|
||||
if (Math.abs(dir.x()) > MathUtil.EPSILON) {
|
||||
t = Math.min(t, intersectionX(ray, _minExtent.x));
|
||||
t = Math.min(t, intersectionX(ray, _maxExtent.x));
|
||||
}
|
||||
if (Math.abs(dir.y()) > MathUtil.EPSILON) {
|
||||
t = Math.min(t, intersectionY(ray, _minExtent.y));
|
||||
t = Math.min(t, intersectionY(ray, _maxExtent.y));
|
||||
}
|
||||
if (Math.abs(dir.z()) > MathUtil.EPSILON) {
|
||||
t = Math.min(t, intersectionZ(ray, _minExtent.z));
|
||||
t = Math.min(t, intersectionZ(ray, _maxExtent.z));
|
||||
}
|
||||
if (t == Float.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
origin.addScaled(dir, t, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public String toString () {
|
||||
@@ -434,98 +425,98 @@ public class Box implements IBox, Serializable
|
||||
return _minExtent.equals(obox._minExtent) && _maxExtent.equals(obox._maxExtent);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersects(Ray3D)}. Determines whether the ray intersects the box
|
||||
// * at the plane where x equals the value specified.
|
||||
// */
|
||||
// protected boolean intersectsX (Ray3D ray, float x) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (x - origin.x) / dir.x;
|
||||
// if (t < 0f) {
|
||||
// return false;
|
||||
// }
|
||||
// float iy = origin.y + t*dir.y, iz = origin.z + t*dir.z;
|
||||
// return iy >= _minExtent.y && iy <= _maxExtent.y &&
|
||||
// iz >= _minExtent.z && iz <= _maxExtent.z;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersects(Ray3)}. Determines whether the ray intersects the box
|
||||
* at the plane where x equals the value specified.
|
||||
*/
|
||||
protected boolean intersectsX (IRay3 ray, float x) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (x - origin.x()) / dir.x();
|
||||
if (t < 0f) {
|
||||
return false;
|
||||
}
|
||||
float iy = origin.y() + t*dir.y(), iz = origin.z() + t*dir.z();
|
||||
return iy >= _minExtent.y && iy <= _maxExtent.y &&
|
||||
iz >= _minExtent.z && iz <= _maxExtent.z;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersects(Ray3D)}. Determines whether the ray intersects the box
|
||||
// * at the plane where y equals the value specified.
|
||||
// */
|
||||
// protected boolean intersectsY (Ray3D ray, float y) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (y - origin.y) / dir.y;
|
||||
// if (t < 0f) {
|
||||
// return false;
|
||||
// }
|
||||
// float ix = origin.x + t*dir.x, iz = origin.z + t*dir.z;
|
||||
// return ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
// iz >= _minExtent.z && iz <= _maxExtent.z;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersects(Ray3)}. Determines whether the ray intersects the box
|
||||
* at the plane where y equals the value specified.
|
||||
*/
|
||||
protected boolean intersectsY (IRay3 ray, float y) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (y - origin.y()) / dir.y();
|
||||
if (t < 0f) {
|
||||
return false;
|
||||
}
|
||||
float ix = origin.x() + t*dir.x(), iz = origin.z() + t*dir.z();
|
||||
return ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
iz >= _minExtent.z && iz <= _maxExtent.z;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersects(Ray3D)}. Determines whether the ray intersects the box
|
||||
// * at the plane where z equals the value specified.
|
||||
// */
|
||||
// protected boolean intersectsZ (Ray3D ray, float z) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (z - origin.z) / dir.z;
|
||||
// if (t < 0f) {
|
||||
// return false;
|
||||
// }
|
||||
// float ix = origin.x + t*dir.x, iy = origin.y + t*dir.y;
|
||||
// return ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
// iy >= _minExtent.y && iy <= _maxExtent.y;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersects(Ray3)}. Determines whether the ray intersects the box
|
||||
* at the plane where z equals the value specified.
|
||||
*/
|
||||
protected boolean intersectsZ (IRay3 ray, float z) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (z - origin.z()) / dir.z();
|
||||
if (t < 0f) {
|
||||
return false;
|
||||
}
|
||||
float ix = origin.x() + t*dir.x(), iy = origin.y() + t*dir.y();
|
||||
return ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
iy >= _minExtent.y && iy <= _maxExtent.y;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
// * intersects the box at the plane where x equals the value specified, or returns
|
||||
// * {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
// */
|
||||
// protected float intersectionX (Ray3D ray, float x) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (x - origin.x) / dir.x;
|
||||
// if (t < 0f) {
|
||||
// return Float.MAX_VALUE;
|
||||
// }
|
||||
// float iy = origin.y + t*dir.y, iz = origin.z + t*dir.z;
|
||||
// return (iy >= _minExtent.y && iy <= _maxExtent.y &&
|
||||
// iz >= _minExtent.z && iz <= _maxExtent.z) ? t : Float.MAX_VALUE;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
* intersects the box at the plane where x equals the value specified, or returns
|
||||
* {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
*/
|
||||
protected float intersectionX (IRay3 ray, float x) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (x - origin.x()) / dir.x();
|
||||
if (t < 0f) {
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
float iy = origin.y() + t*dir.y(), iz = origin.z() + t*dir.z();
|
||||
return (iy >= _minExtent.y && iy <= _maxExtent.y &&
|
||||
iz >= _minExtent.z && iz <= _maxExtent.z) ? t : Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
// * intersects the box at the plane where y equals the value specified, or returns
|
||||
// * {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
// */
|
||||
// protected float intersectionY (Ray3D ray, float y) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (y - origin.y) / dir.y;
|
||||
// if (t < 0f) {
|
||||
// return Float.MAX_VALUE;
|
||||
// }
|
||||
// float ix = origin.x + t*dir.x, iz = origin.z + t*dir.z;
|
||||
// return (ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
// iz >= _minExtent.z && iz <= _maxExtent.z) ? t : Float.MAX_VALUE;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
* intersects the box at the plane where y equals the value specified, or returns
|
||||
* {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
*/
|
||||
protected float intersectionY (IRay3 ray, float y) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (y - origin.y()) / dir.y();
|
||||
if (t < 0f) {
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
float ix = origin.x() + t*dir.x(), iz = origin.z() + t*dir.z();
|
||||
return (ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
iz >= _minExtent.z && iz <= _maxExtent.z) ? t : Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
// * intersects the box at the plane where z equals the value specified, or returns
|
||||
// * {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
// */
|
||||
// protected float intersectionZ (Ray3D ray, float z) {
|
||||
// Vector3 origin = ray.origin(), dir = ray.direction();
|
||||
// float t = (z - origin.z) / dir.z;
|
||||
// if (t < 0f) {
|
||||
// return Float.MAX_VALUE;
|
||||
// }
|
||||
// float ix = origin.x + t*dir.x, iy = origin.y + t*dir.y;
|
||||
// return (ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
// iy >= _minExtent.y && iy <= _maxExtent.y) ? t : Float.MAX_VALUE;
|
||||
// }
|
||||
/**
|
||||
* Helper method for {@link #intersection}. Finds the <code>t</code> value where the ray
|
||||
* intersects the box at the plane where z equals the value specified, or returns
|
||||
* {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
*/
|
||||
protected float intersectionZ (IRay3 ray, float z) {
|
||||
IVector3 origin = ray.origin(), dir = ray.direction();
|
||||
float t = (z - origin.z()) / dir.z();
|
||||
if (t < 0f) {
|
||||
return Float.MAX_VALUE;
|
||||
}
|
||||
float ix = origin.x() + t*dir.x(), iy = origin.y() + t*dir.y();
|
||||
return (ix >= _minExtent.x && ix <= _maxExtent.x &&
|
||||
iy >= _minExtent.y && iy <= _maxExtent.y) ? t : Float.MAX_VALUE;
|
||||
}
|
||||
|
||||
/** The box's minimum extent. */
|
||||
protected final Vector3 _minExtent = new Vector3();
|
||||
|
||||
@@ -156,8 +156,18 @@ public interface IBox
|
||||
*/
|
||||
Box expand (float x, float y, float z, Box result);
|
||||
|
||||
// /**
|
||||
// * Determines whether the specified ray intersects this box.
|
||||
// */
|
||||
// boolean intersects (Ray3D ray);
|
||||
/**
|
||||
* Determines whether the specified ray intersects this box.
|
||||
*/
|
||||
boolean intersects (IRay3 ray);
|
||||
|
||||
/**
|
||||
* Finds the location of the (first) intersection between the specified ray and this box. This
|
||||
* will be the ray origin if the ray starts inside the box.
|
||||
*
|
||||
* @param result a vector to hold the location of the intersection.
|
||||
* @return true if the ray intersects the box (in which case the result vector will be
|
||||
* populated with the location of the intersection), false if not.
|
||||
*/
|
||||
boolean intersection (IRay3 ray, Vector3 result);
|
||||
}
|
||||
|
||||
@@ -56,19 +56,19 @@ public interface IPlane
|
||||
*/
|
||||
Plane negate (Plane result);
|
||||
|
||||
// /**
|
||||
// * Computes the intersection of the supplied ray with this plane, placing the result
|
||||
// * in the given vector (if the ray intersects).
|
||||
// *
|
||||
// * @return true if the ray intersects the plane (in which case the result will contain
|
||||
// * the point of intersection), false if not.
|
||||
// */
|
||||
// boolean intersection (Ray3D ray, Vector3 result);
|
||||
/**
|
||||
* Computes the intersection of the supplied ray with this plane, placing the result
|
||||
* in the given vector (if the ray intersects).
|
||||
*
|
||||
* @return true if the ray intersects the plane (in which case the result will contain
|
||||
* the point of intersection), false if not.
|
||||
*/
|
||||
boolean intersection (IRay3 ray, Vector3 result);
|
||||
|
||||
// /**
|
||||
// * Computes the signed distance to this plane along the specified ray.
|
||||
// *
|
||||
// * @return the signed distance, or {@link Float#NaN} if the ray runs parallel to the plane.
|
||||
// */
|
||||
// float distance (Ray3D ray);
|
||||
/**
|
||||
* Computes the signed distance to this plane along the specified ray.
|
||||
*
|
||||
* @return the signed distance, or {@link Float#NaN} if the ray runs parallel to the plane.
|
||||
*/
|
||||
float distance (IRay3 ray);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* Provides read-only access to a {@link Ray2}.
|
||||
*/
|
||||
public interface IRay2
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the ray's point of origin.
|
||||
*/
|
||||
IVector origin ();
|
||||
|
||||
/**
|
||||
* Returns a reference to the ray's unit direction vector.
|
||||
*/
|
||||
IVector direction ();
|
||||
|
||||
// /**
|
||||
// * Transforms this ray.
|
||||
// *
|
||||
// * @return a new ray containing the result.
|
||||
// */
|
||||
// Ray2 transform (Transform2D transform);
|
||||
|
||||
// /**
|
||||
// * Transforms this ray, placing the result in the object provided.
|
||||
// *
|
||||
// * @return a reference to the result ray, for chaining.
|
||||
// */
|
||||
// Ray2 transform (Transform2D transform, Ray2 result);
|
||||
|
||||
/**
|
||||
* Determines whether the ray intersects the specified point.
|
||||
*/
|
||||
boolean intersects (IVector pt);
|
||||
|
||||
/**
|
||||
* Finds the intersection between the ray and a line segment with the given start and end
|
||||
* points.
|
||||
*
|
||||
* @return true if the ray intersected the segment (in which case the result will contain the
|
||||
* point of intersection), false otherwise.
|
||||
*/
|
||||
boolean getIntersection (IVector start, IVector end, Vector result);
|
||||
|
||||
/**
|
||||
* Finds the intersection between the ray and a capsule with the given start point, end point,
|
||||
* and radius.
|
||||
*
|
||||
* @return true if the ray intersected the circle (in which case the result will contain the
|
||||
* point of intersection), false otherwise.
|
||||
*/
|
||||
boolean getIntersection (IVector start, IVector end, float radius, Vector result);
|
||||
|
||||
/**
|
||||
* Finds the intersection between the ray and a circle with the given center and radius.
|
||||
*
|
||||
* @return true if the ray intersected the circle (in which case the result will contain the
|
||||
* point of intersection), false otherwise.
|
||||
*/
|
||||
boolean getIntersection (IVector center, float radius, Vector result);
|
||||
|
||||
/**
|
||||
* Computes the nearest point on the Ray to the supplied point.
|
||||
* @return {@code result} for chaining.
|
||||
*/
|
||||
Vector getNearestPoint (IVector point, Vector result);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* Provides read-only access to a {@link Ray3}.
|
||||
*/
|
||||
public interface IRay3
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the ray's point of origin.
|
||||
*/
|
||||
IVector3 origin ();
|
||||
|
||||
/**
|
||||
* Returns a reference to the ray's unit direction vector.
|
||||
*/
|
||||
IVector3 direction ();
|
||||
|
||||
// /**
|
||||
// * Transforms this ray.
|
||||
// *
|
||||
// * @return a new ray containing the result.
|
||||
// */
|
||||
// Ray3 transform (Transform3D transform);
|
||||
|
||||
// /**
|
||||
// * Transforms this ray, placing the result in the object provided.
|
||||
// *
|
||||
// * @return a reference to the result ray, for chaining.
|
||||
// */
|
||||
// Ray3 transform (Transform3D transform, Ray3 result);
|
||||
}
|
||||
@@ -186,29 +186,29 @@ public class Plane implements IPlane, Serializable
|
||||
return result;
|
||||
}
|
||||
|
||||
// @Override // from IPlane
|
||||
// public boolean intersection (Ray3D ray, Vector3 result) {
|
||||
// float distance = distance(ray);
|
||||
// if (Float.isNaN(distance) || distance < 0f) {
|
||||
// return false;
|
||||
// } else {
|
||||
// ray.origin().addScaled(ray.direction(), distance, result);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
@Override // from IPlane
|
||||
public boolean intersection (IRay3 ray, Vector3 result) {
|
||||
float distance = distance(ray);
|
||||
if (Float.isNaN(distance) || distance < 0f) {
|
||||
return false;
|
||||
} else {
|
||||
ray.origin().addScaled(ray.direction(), distance, result);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// @Override // from IPlane
|
||||
// public float distance (Ray3D ray) {
|
||||
// float dividend = -distance(ray.origin());
|
||||
// float divisor = _normal.dot(ray.direction());
|
||||
// if (Math.abs(dividend) < MathUtil.EPSILON) {
|
||||
// return 0f; // origin is on plane
|
||||
// } else if (Math.abs(divisor) < MathUtil.EPSILON) {
|
||||
// return Float.NaN; // ray is parallel to plane
|
||||
// } else {
|
||||
// return dividend / divisor;
|
||||
// }
|
||||
// }
|
||||
@Override // from IPlane
|
||||
public float distance (IRay3 ray) {
|
||||
float dividend = -distance(ray.origin());
|
||||
float divisor = _normal.dot(ray.direction());
|
||||
if (Math.abs(dividend) < MathUtil.EPSILON) {
|
||||
return 0f; // origin is on plane
|
||||
} else if (Math.abs(divisor) < MathUtil.EPSILON) {
|
||||
return Float.NaN; // ray is parallel to plane
|
||||
} else {
|
||||
return dividend / divisor;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode () {
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* A ray consisting of an origin point and a unit direction vector.
|
||||
*/
|
||||
public class Ray2 implements IRay2
|
||||
{
|
||||
/** The ray's point of origin. */
|
||||
public final Vector origin = new Vector();
|
||||
|
||||
/** The ray's unit direction vector. */
|
||||
public final Vector direction = new Vector();
|
||||
|
||||
/**
|
||||
* Creates a ray with the values contained in the supplied origin point and unit direction
|
||||
* vector.
|
||||
*/
|
||||
public Ray2 (Vector origin, Vector direction) {
|
||||
set(origin, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
public Ray2 (Ray2 other) {
|
||||
set(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty (invalid) ray.
|
||||
*/
|
||||
public Ray2 () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the parameters of another ray.
|
||||
*
|
||||
* @return a reference to this ray, for chaining.
|
||||
*/
|
||||
public Ray2 set (IRay2 other) {
|
||||
return set(other.origin(), other.direction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ray parameters to the values contained in the supplied vectors.
|
||||
*
|
||||
* @return a reference to this ray, for chaining.
|
||||
*/
|
||||
public Ray2 set (IVector origin, IVector direction) {
|
||||
this.origin.set(origin);
|
||||
this.direction.set(direction);
|
||||
return this;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Transforms this ray in-place.
|
||||
// *
|
||||
// * @return a reference to this ray, for chaining.
|
||||
// */
|
||||
// public Ray2 transformLocal (Transform2D transform) {
|
||||
// return transform(transform, this);
|
||||
// }
|
||||
|
||||
@Override // from IRay2
|
||||
public IVector origin () {
|
||||
return origin;
|
||||
}
|
||||
|
||||
@Override // from IRay2
|
||||
public IVector direction () {
|
||||
return direction;
|
||||
}
|
||||
|
||||
// @Override // from IRay2
|
||||
// public Ray2 transform (Transform2D transform) {
|
||||
// return transform(transform, new Ray2());
|
||||
// }
|
||||
|
||||
// @Override // from IRay2
|
||||
// public Ray2 transform (Transform2D transform, Ray2 result) {
|
||||
// transform.transformPoint(origin, result.origin);
|
||||
// transform.transformVector(direction, result.direction).normalizeLocal();
|
||||
// return result;
|
||||
// }
|
||||
|
||||
@Override // from IRay2
|
||||
public boolean intersects (IVector pt) {
|
||||
if (Math.abs(direction.x) > Math.abs(direction.y)) {
|
||||
float t = (pt.x() - origin.x) / direction.x;
|
||||
return t >= 0f && origin.y + t*direction.y == pt.y();
|
||||
} else {
|
||||
float t = (pt.y() - origin.y) / direction.y;
|
||||
return t >= 0f && origin.x + t*direction.x == pt.x();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from IRay2
|
||||
public boolean getIntersection (IVector start, IVector end, Vector result) {
|
||||
// ray is a + t*b, segment is c + s*d
|
||||
float ax = origin.x, ay = origin.y;
|
||||
float bx = direction.x, by = direction.y;
|
||||
float cx = start.x(), cy = start.y();
|
||||
float dx = end.x() - start.x(), dy = end.y() - start.y();
|
||||
|
||||
float divisor = bx*dy - by*dx;
|
||||
if (Math.abs(divisor) < FloatMath.EPSILON) {
|
||||
// the lines are parallel (or the segment is zero-length)
|
||||
float t = Math.min(getIntersection(start), getIntersection(end));
|
||||
boolean isect = (t != Float.MAX_VALUE);
|
||||
if (isect) {
|
||||
origin.addScaled(direction, t, result);
|
||||
}
|
||||
return isect;
|
||||
}
|
||||
float cxax = cx - ax, cyay = cy - ay;
|
||||
float s = (by*cxax - bx*cyay) / divisor;
|
||||
if (s < 0f || s > 1f) {
|
||||
return false;
|
||||
}
|
||||
float t = (dy*cxax - dx*cyay) / divisor;
|
||||
boolean isect = (t >= 0f);
|
||||
if (isect) {
|
||||
origin.addScaled(direction, t, result);
|
||||
}
|
||||
return isect;
|
||||
}
|
||||
|
||||
@Override // from IRay2
|
||||
public boolean getIntersection (IVector start, IVector end, float radius, Vector result) {
|
||||
float startx = start.x(), starty = start.y();
|
||||
// compute the segment's line parameters
|
||||
float a = starty - end.y(), b = end.x() - startx;
|
||||
float len = FloatMath.hypot(a, b);
|
||||
if (len < FloatMath.EPSILON) { // start equals end; check as circle
|
||||
return getIntersection(start, radius, result);
|
||||
}
|
||||
float rlen = 1f / len;
|
||||
a *= rlen;
|
||||
b *= rlen;
|
||||
float c = -a*startx - b*starty;
|
||||
|
||||
// find out where the origin lies with respect to the top and bottom
|
||||
float dist = a*origin.x + b*origin.y + c;
|
||||
boolean above = (dist > +radius), below = (dist < -radius);
|
||||
float x, y;
|
||||
if (above || below) { // check the intersection with the top/bottom boundary
|
||||
float divisor = a*direction.x + b*direction.y;
|
||||
if (Math.abs(divisor) < FloatMath.EPSILON) { // lines are parallel
|
||||
return false;
|
||||
}
|
||||
c += (above ? -radius : +radius);
|
||||
float t = (-a*origin.x - b*origin.y - c) / divisor;
|
||||
if (t < 0f) { // wrong direction
|
||||
return false;
|
||||
}
|
||||
x = origin.x + t*direction.x;
|
||||
y = origin.y + t*direction.y;
|
||||
|
||||
} else { // middle; check the origin
|
||||
x = origin.x;
|
||||
y = origin.y;
|
||||
}
|
||||
// see where the test point lies with respect to the start and end boundaries
|
||||
float tmp = a;
|
||||
a = b;
|
||||
b = -tmp;
|
||||
c = -a*startx - b*starty;
|
||||
dist = a*x + b*y + c;
|
||||
if (dist < 0f) { // before start
|
||||
return getIntersection(start, radius, result);
|
||||
} else if (dist > len) { // after end
|
||||
return getIntersection(end, radius, result);
|
||||
} else { // middle
|
||||
result.set(x, y);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from IRay2
|
||||
public boolean getIntersection (IVector center, float radius, Vector result) {
|
||||
// see if we start inside the circle
|
||||
if (origin.distanceSq(center) <= radius*radius) {
|
||||
result.set(origin);
|
||||
return true;
|
||||
}
|
||||
// then if we intersect the circle
|
||||
float ax = origin.x - center.x(), ay = origin.y - center.y();
|
||||
float b = 2f*(direction.x*ax + direction.y*ay);
|
||||
float c = ax*ax + ay*ay - radius*radius;
|
||||
float radicand = b*b - 4f*c;
|
||||
if (radicand < 0f) {
|
||||
return false;
|
||||
}
|
||||
float t = (-b - FloatMath.sqrt(radicand)) * 0.5f;
|
||||
boolean isect = (t >= 0f);
|
||||
if (isect) {
|
||||
origin.addScaled(direction, t, result);
|
||||
}
|
||||
return isect;
|
||||
}
|
||||
|
||||
@Override // from IRay2
|
||||
public Vector getNearestPoint (IVector point, Vector result) {
|
||||
if (result == null) {
|
||||
result = new Vector();
|
||||
}
|
||||
float r = point.subtract(origin).dot(direction);
|
||||
result.set(origin.add(direction.scale(r)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "[origin=" + origin + ", direction=" + direction + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameter of the ray when it intersects the supplied point, or
|
||||
* {@link Float#MAX_VALUE} if there is no such intersection.
|
||||
*/
|
||||
protected float getIntersection (IVector pt) {
|
||||
if (Math.abs(direction.x) > Math.abs(direction.y)) {
|
||||
float t = (pt.x() - origin.x) / direction.x;
|
||||
return (t >= 0f && origin.y + t*direction.y == pt.y()) ? t : Float.MAX_VALUE;
|
||||
} else {
|
||||
float t = (pt.y() - origin.y) / direction.y;
|
||||
return (t >= 0f && origin.x + t*direction.x == pt.x()) ? t : Float.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.f;
|
||||
|
||||
/**
|
||||
* A ray consisting of an origin point and a unit direction vector.
|
||||
*/
|
||||
public class Ray3 implements IRay3
|
||||
{
|
||||
/** The ray's point of origin. */
|
||||
public final Vector3 origin = new Vector3();
|
||||
|
||||
/** The ray's unit direction vector. */
|
||||
public final Vector3 direction = new Vector3();
|
||||
|
||||
/**
|
||||
* Creates a ray with the values contained in the supplied origin point and unit direction
|
||||
* vector.
|
||||
*/
|
||||
public Ray3 (Vector3 origin, Vector3 direction) {
|
||||
set(origin, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
public Ray3 (Ray3 other) {
|
||||
set(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty (invalid) ray.
|
||||
*/
|
||||
public Ray3 () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the parameters of another ray.
|
||||
*
|
||||
* @return a reference to this ray, for chaining.
|
||||
*/
|
||||
public Ray3 set (Ray3 other) {
|
||||
return set(other.origin(), other.direction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ray parameters to the values contained in the supplied vectors.
|
||||
*
|
||||
* @return a reference to this ray, for chaining.
|
||||
*/
|
||||
public Ray3 set (Vector3 origin, Vector3 direction) {
|
||||
this.origin.set(origin);
|
||||
this.direction.set(direction);
|
||||
return this;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Transforms this ray in-place.
|
||||
// *
|
||||
// * @return a reference to this ray, for chaining.
|
||||
// */
|
||||
// public Ray3 transformLocal (Transform3D transform) {
|
||||
// return transform(transform, this);
|
||||
// }
|
||||
|
||||
@Override // from IRay3
|
||||
public Vector3 origin () {
|
||||
return origin;
|
||||
}
|
||||
|
||||
@Override // from IRay3
|
||||
public Vector3 direction () {
|
||||
return direction;
|
||||
}
|
||||
|
||||
// @Override // from IRay3
|
||||
// public Ray3 transform (Transform3D transform) {
|
||||
// return transform(transform, new Ray3());
|
||||
// }
|
||||
|
||||
// @Override // from IRay3
|
||||
// public Ray3 transform (Transform3D transform, Ray3 result) {
|
||||
// transform.transformPoint(origin, result.origin);
|
||||
// transform.transformVector(direction, result.direction).normalizeLocal();
|
||||
// return result;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "[origin=" + origin + ", direction=" + direction + "]";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user