/**
*
*/
package wblut.geom;
import wblut.WB_Epsilon;
import wblut.math.WB_Fast;
import wblut.math.WB_MTRandom;
// TODO: Auto-generated Javadoc
/**
* The Class WB_Point2d.
*
* @author Frederik Vanhoutte, W:Blut
*/
public class WB_Point2d {
/** The Constant ZERO. */
public static final WB_Point2d ZERO = new WB_Point2d();
/** Coordinates. */
public double x, y;
/**
* Instantiates a new WB_XY.
*/
public WB_Point2d() {
x = y = 0;
}
/**
* Instantiates a new WB_XY.
*
* @param x the x
* @param y the y
*/
public WB_Point2d(final double x, final double y) {
this.x = x;
this.y = y;
}
/**
* Instantiates a new WB_XY.
*
* @param v the v
*/
public WB_Point2d(final WB_Point2d v) {
x = v.x;
y = v.y;
}
/**
* Instantiates a new WB_XY.
*
* @param v the v
*/
public WB_Point2d(final WB_Point3d v) {
x = v.x;
y = v.y;
}
/**
* Set coordinates.
*
* @param x the x
* @param y the y
*/
public void set(final double x, final double y) {
this.x = x;
this.y = y;
}
/**
* Set coordinates.
*
* @param v the v
*/
public void set(final WB_Point2d v) {
x = v.x;
y = v.y;
}
/**
* Dot product.
*
* @param p the p
* @param q the q
* @return dot product
*/
public static double dot(final WB_Point2d p, final WB_Point2d q) {
return (p.x * q.x + p.y * q.y);
}
/**
* Dot product.
*
* @param p the p
* @return dot product
*/
public double dot(final WB_Point2d p) {
return (p.x * x + p.y * y);
}
/**
* Perp dot product.
*
* @param p the p
* @param q the q
* @return dot product
*/
public static double perpDot(final WB_Point2d p, final WB_Point2d q) {
return (-p.y * q.x + p.x * q.y);
}
/**
* Perp dot product.
*
* @param p the p
* @return dot product
*/
public double perpDot(final WB_Point2d p) {
return (-p.x * y + p.y * x);
}
/**
* Angle to vector. Normalized vectors are assumed.
*
* @param p normalized point, vector or normal
* @return angle
*/
public double angleNorm(final WB_Point2d p) {
return Math.acos(p.x * x + p.y * y);
}
/**
* Absolute value of dot product.
*
* @param p the p
* @param q the q
* @return absolute value of dot product
*/
public static double absDot(final WB_Point2d p, final WB_Point2d q) {
return WB_Fast.abs(p.x * q.x + p.y * q.y);
}
/**
* Absolute value of dot product.
*
* @param p the p
* @return absolute value of dot product
*/
public double absDot(final WB_Point2d p) {
return WB_Fast.abs(p.x * x + p.y * y);
}
/**
* Get squared magnitude.
*
* @return squared magnitude
*/
public double mag2() {
return x * x + y * y;
}
/**
* Get magnitude.
*
* @return magnitude
*/
public double mag() {
return Math.sqrt(x * x + y * y);
}
/**
* Checks if vector is zero-vector.
*
* @return true, if zero
*/
public boolean isZero() {
return (mag2() < WB_Epsilon.SQEPSILON);
}
/*
* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
/**
* Compare to.
*
* @param otherXY the other xy
* @return the int
*/
public int compareTo(final WB_Point2d otherXY) {
int _tmp = WB_Epsilon.compareAbs(x, otherXY.x);
if (_tmp != 0) {
return _tmp;
}
_tmp = WB_Epsilon.compareAbs(y, otherXY.y);
return _tmp;
}
/**
* Compare to y1st.
*
* @param otherXY the other xy
* @return the int
*/
public int compareToY1st(final WB_Point2d otherXY) {
int _tmp = WB_Epsilon.compareAbs(y, otherXY.y);
if (_tmp != 0) {
return _tmp;
}
_tmp = WB_Epsilon.compareAbs(x, otherXY.x);
return _tmp;
}
/**
* Smaller than.
*
* @param otherXYZ point, vector or normal
* @return true, if successful
*/
public boolean smallerThan(final WB_Point2d otherXYZ) {
int _tmp = WB_Epsilon.compareAbs(x, otherXYZ.x);
if (_tmp != 0) {
return (_tmp < 0);
}
_tmp = WB_Epsilon.compareAbs(y, otherXYZ.y);
return (_tmp < 0);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "XY [x=" + x + ", y=" + y + "]";
}
/**
* Get coordinate from index value.
*
* @param i 0,1
* @return x- or y-coordinate
*/
public double get(final int i) {
if (i == 0) {
return x;
}
if (i == 1) {
return y;
}
return Double.NaN;
}
/**
* Set coordinate with index value.
*
* @param i 0,1
* @param v x- or y-coordinate
*/
public void set(final int i, final double v) {
if (i == 0) {
x = v;
} else if (i == 1) {
y = v;
}
}
/**
* Get x-coordinate as float.
*
* @return x
*/
public float xf() {
return (float) x;
}
/**
* Get y-coordinate as float.
*
* @return y
*/
public float yf() {
return (float) y;
}
/**
* Cross product. Internal use only.
*
* @param p the p
* @return the w b_ point3d
*/
public WB_Point3d cross(final WB_Point2d p) {
return new WB_Point3d(0, 0, x * p.y - y * p.x);
}
/**
* Cross product. Internal use only.
*
* @param p the p
* @param q the q
* @return the w b_ point3d
*/
public static WB_Point3d cross(final WB_Point2d p, final WB_Point2d q) {
return new WB_Point3d(0, 0, p.x * q.y - p.y * q.x);
}
/**
* Cross product. Internal use only.
*
* @param p the p
* @param result the result
*/
public void crossInto(final WB_Point2d p, final WB_Point3d result) {
result.x = 0;
result.y = 0;
result.z = x * p.y - y * p.x;
}
/**
* return copy.
*
* @return copy
*/
public WB_Point2d get() {
return new WB_Point2d(x, y);
}
/*
*/
/**
* Perp.
*
* @return the w b_ point2d
*/
public WB_Point2d perp() {
return new WB_Point2d(-y, x);
}
/**
* Perp into.
*
* @param result the result
*/
public void perpInto(final WB_Point2d result) {
result.set(-y, x);
}
/**
* Move to position.
*
* @param x the x
* @param y the y
* @return self
*/
public WB_Point2d moveTo(final double x, final double y) {
this.x = x;
this.y = y;
return this;
}
/**
* Move to position.
*
* @param p point, vector or normal
* @return self
*/
public WB_Point2d moveTo(final WB_Point2d p) {
x = p.x;
y = p.y;
return this;
}
/**
* Move by vector.
*
* @param x the x
* @param y the y
* @return self
*/
public WB_Point2d moveBy(final double x, final double y) {
this.x += x;
this.y += y;
return this;
}
/**
* Move by vector.
*
* @param v point, vector or normal
* @return self
*/
public WB_Point2d moveBy(final WB_Point2d v) {
x += v.x;
y += v.y;
return this;
}
/**
* Move by vector.
*
* @param x the x
* @param y the y
* @param result WB_XY to store result
*/
public void moveByInto(final double x, final double y,
final WB_Point2d result) {
result.x = this.x + x;
result.y = this.y + y;
}
/**
* Move by vector.
*
* @param v point, vector or normal
* @param result WB_XY to store result
*/
public void moveByInto(final WB_Point2d v, final WB_Point2d result) {
result.x = x + v.x;
result.y = y + v.y;
}
/**
* Move by vector.
*
* @param x the x
* @param y the y
* @return new WB_XY
*/
public WB_Point2d moveByAndCopy(final double x, final double y) {
return new WB_Point2d(this.x + x, this.y + y);
}
/**
* Move by vector.
*
* @param v point, vector or normal
* @return new WB_XY
*/
public WB_Point2d moveByAndCopy(final WB_Point2d v) {
return new WB_Point2d(x + v.x, y + v.y);
}
/**
* Scale.
*
* @param f scale factor
* @return self
*/
public WB_Point2d scale(final double f) {
x *= f;
y *= f;
return this;
}
/**
* Scale .
*
* @param f scale factor
* @param result WB_XY to store result
*/
public void scaleInto(final double f, final WB_Point2d result) {
result.x = x * f;
result.y = y * f;
}
/**
* Scale.
*
* @param fx scale factor
* @param fy scale factor
* @return self
*/
public WB_Point2d scale(final double fx, final double fy) {
x *= fx;
y *= fy;
return this;
}
/**
* Scale .
*
* @param fx scale factor
* @param fy scale factor
* @param result WB_XY to store result
*/
public void scaleInto(final double fx, final double fy,
final WB_Point2d result) {
result.x = x * fx;
result.y = y * fy;
}
/**
* Adds the.
*
* @param x the x
* @param y the y
* @return self
*/
public WB_Point2d add(final double x, final double y) {
this.x += x;
this.y += y;
return this;
}
/**
* Adds the.
*
* @param x the x
* @param y the y
* @param f the f
* @return self
*/
public WB_Point2d add(final double x, final double y, final double f) {
this.x += f * x;
this.y += f * y;
return this;
}
/**
* Adds the.
*
* @param p the p
* @return self
*/
public WB_Point2d add(final WB_Point2d p) {
x += p.x;
y += p.y;
return this;
}
/**
* Adds the.
*
* @param p the p
* @param f the f
* @return self
*/
public WB_Point2d add(final WB_Point2d p, final double f) {
x += f * p.x;
y += f * p.y;
return this;
}
/**
* Adds the into.
*
* @param x the x
* @param y the y
* @param result the result
*/
public void addInto(final double x, final double y, final WB_Point2d result) {
result.x = (this.x + x);
result.y = (this.y + y);
}
/**
* Adds the into.
*
* @param p the p
* @param result the result
*/
public void addInto(final WB_Point3d p, final WB_Point2d result) {
result.x = x + p.x;
result.y = y + p.y;
}
/**
* Adds the and copy.
*
* @param x the x
* @param y the y
* @param f the f
* @return new WB_XY
*/
public WB_Point2d addAndCopy(final double x, final double y, final double f) {
return new WB_Point2d(this.x + f * x, this.y + f * y);
}
/**
* Adds the and copy.
*
* @param x the x
* @param y the y
* @return new WB_XY
*/
public WB_Point2d addAndCopy(final double x, final double y) {
return new WB_Point2d(this.x + x, this.y + y);
}
/**
* Adds the and copy.
*
* @param p the p
* @return new WB_XY
*/
public WB_Point2d addAndCopy(final WB_Point2d p) {
return new WB_Point2d(x + p.x, y + p.y);
}
/**
* Adds the and copy.
*
* @param p the p
* @param f the f
* @return new WB_XY
*/
public WB_Point2d addAndCopy(final WB_Point2d p, final double f) {
return new WB_Point2d(x + f * p.x, y + f * p.y);
}
/**
* Sub.
*
* @param x the x
* @param y the y
* @return self
*/
public WB_Point2d sub(final double x, final double y) {
this.x -= x;
this.y -= y;
return this;
}
/**
* Sub.
*
* @param v the v
* @return self
*/
public WB_Point2d sub(final WB_Point2d v) {
x -= v.x;
y -= v.y;
return this;
}
/**
* Sub into.
*
* @param x the x
* @param y the y
* @param result the result
*/
public void subInto(final double x, final double y, final WB_Point2d result) {
result.x = (this.x - x);
result.y = (this.y - y);
}
/**
* Sub into.
*
* @param p the p
* @param result the result
*/
public void subInto(final WB_Point2d p, final WB_Point2d result) {
result.x = x - p.x;
result.y = y - p.y;
}
/**
* Sub and copy.
*
* @param x the x
* @param y the y
* @return new WB_XY
*/
public WB_Point2d subAndCopy(final double x, final double y) {
return new WB_Point2d(this.x - x, this.y - y);
}
/**
* Sub and copy.
*
* @param p the p
* @return new WB_XY
*/
public WB_Point2d subAndCopy(final WB_Point2d p) {
return new WB_Point2d(x - p.x, y - p.y);
}
/**
* Mult.
*
* @param f the f
* @return self
*/
public WB_Point2d mult(final double f) {
x *= f;
y *= f;
return this;
}
/**
* Invert.
*
* @return self
*/
public WB_Point2d invert() {
x *= -1;
y *= -1;
return this;
}
/**
* Normalize.
*
* @return the double
*/
public double normalize() {
final double d = mag();
if (WB_Epsilon.isZero(d)) {
set(0, 0);
} else {
set(x / d, y / d);
}
return d;
}
/**
* Trim.
*
* @param d the d
*/
public void trim(final double d) {
if (mag2() > d * d) {
normalize();
mult(d);
}
}
/**
* Mult into.
*
* @param f the f
* @param result the result
*/
public void multInto(final double f, final WB_Point2d result) {
result.x = (x * f);
result.y = (y * f);
}
/**
* Mult and copy.
*
* @param f the f
* @return new WB_XY
*/
public WB_Point2d multAndCopy(final double f) {
return new WB_Point2d(x * f, y * f);
}
/**
* Div.
*
* @param f the f
* @return self
*/
public WB_Point2d div(final double f) {
return mult(1.0 / f);
}
/**
* Div into.
*
* @param f the f
* @param result the result
*/
public void divInto(final double f, final WB_Point2d result) {
multInto(1.0 / f, result);
}
/**
* Div and copy.
*
* @param f the f
* @return new WB_XY
*/
public WB_Point2d divAndCopy(final double f) {
return multAndCopy(1.0 / f);
}
/**
* Normalize.
*
* @param result WB_XY to store result
*/
public void normalizeInto(final WB_Point2d result) {
final double d = mag();
if (WB_Epsilon.isZero(d)) {
result.set(0, 0);
} else {
result.set(x, y);
result.div(d);
}
}
/**
* Random points.
*
* @param n the n
* @param x the x
* @param y the y
* @return the w b_ point2d[]
*/
public static WB_Point2d[] randomPoints(final int n, final double x,
final double y) {
final WB_MTRandom mtr = new WB_MTRandom();
final WB_Point2d[] points = new WB_Point2d[n];
for (int i = 0; i < n; i++) {
points[i] = new WB_Point2d(-x + 2 * mtr.nextDouble() * x, -y + 2
* mtr.nextDouble() * y);
}
return points;
}
/**
* Random points.
*
* @param n the n
* @param lx the lx
* @param ly the ly
* @param ux the ux
* @param uy the uy
* @return the w b_ point2d[]
*/
public static WB_Point2d[] randomPoints(final int n, final double lx,
final double ly, final double ux, final double uy) {
final WB_MTRandom mtr = new WB_MTRandom();
final WB_Point2d[] points = new WB_Point2d[n];
final double dx = ux - lx;
final double dy = uy - ly;
for (int i = 0; i < n; i++) {
points[i] = new WB_Point2d(lx + mtr.nextDouble() * dx, ly
+ mtr.nextDouble() * dy);
}
return points;
}
/**
* Is vector parallel to other vector.
*
* @param p the p
* @return true, if parallel
*/
public boolean isParallel(final WB_Point2d p) {
return (cross(p).mag2() / (p.mag2() * mag2()) < WB_Epsilon.SQEPSILON);
}
/**
* Is vector parallel to other vector.
*
* @param p the p
* @param t threshold value = (sin(threshold angle))^2
* @return true, if parallel
*/
public boolean isParallel(final WB_Point2d p, final double t) {
return (cross(p).mag2() / (p.mag2() * mag2()) < t
+ WB_Epsilon.SQEPSILON);
}
/**
* Is normalized vector parallel to other normalized vector.
*
* @param p the p
* @return true, if parallel
*/
public boolean isParallelNorm(final WB_Point2d p) {
return (cross(p).mag2() < WB_Epsilon.SQEPSILON);
}
/**
* Is normalized vector parallel to other normalized vector.
*
* @param p the p
* @param t threshold value = (sin(threshold angle))^2
* @return true, if parallel
*/
public boolean isParallelNorm(final WB_Point2d p, final double t) {
return (cross(p).mag2() < t + WB_Epsilon.SQEPSILON);
}
/**
* Calculate hash code.
*
* @param x the x
* @param y the y
* @return the int
*/
protected static int calculateHashCode(final double x, final double y) {
int result = 17;
final long a = Double.doubleToLongBits(x);
result += 31 * result + (int) (a ^ (a >>> 32));
final long b = Double.doubleToLongBits(y);
result += 31 * result + (int) (b ^ (b >>> 32));
return result;
}
/**
* Calculate hash code.
*
* @return the int
*/
protected int calculateHashCode() {
int result = 17;
final long a = Double.doubleToLongBits(x);
result += 31 * result + (int) (a ^ (a >>> 32));
final long b = Double.doubleToLongBits(y);
result += 31 * result + (int) (b ^ (b >>> 32));
return result;
}
/**
* Interpolate.
*
* @param p0 the p0
* @param p1 the p1
* @param t the t
* @return the w b_ point
*/
public static WB_Point2d interpolate(final WB_Point2d p0,
final WB_Point2d p1, final double t) {
return new WB_Point2d(p0.x + t * (p1.x - p0.x), p0.y + t
* (p1.y - p0.y));
}
/**
* Rotate.
*
* @param angle the angle
*/
public void rotate(final double angle) {
final double tmpx = x;
final double tmpy = y;
final double ca = Math.cos(angle);
final double sa = Math.sin(angle);
x = ca * tmpx - sa * tmpy;
y = sa * tmpx + ca * tmpy;
}
/**
* Rotate.
*
* @param angle the angle
* @param origin the origin
*/
public void rotate(final double angle, final WB_Point2d origin) {
final double tmpx = x - origin.x;
final double tmpy = y - origin.y;
final double ca = Math.cos(angle);
final double sa = Math.sin(angle);
x = origin.x + ca * tmpx - sa * tmpy;
y = origin.y + sa * tmpx + ca * tmpy;
}
/**
* Rotate.
*
* @param cosangle the cosangle
* @param sinangle the sinangle
*/
public void rotate(final double cosangle, final double sinangle) {
final double tmpx = x;
final double tmpy = y;
x = cosangle * tmpx - sinangle * tmpy;
y = sinangle * tmpx + cosangle * tmpy;
}
/**
* Rotate.
*
* @param cosangle the cosangle
* @param sinangle the sinangle
* @param origin the origin
*/
public void rotate(final double cosangle, final double sinangle,
final WB_Point2d origin) {
final double tmpx = x - origin.x;
final double tmpy = y - origin.y;
x = origin.x + cosangle * tmpx - sinangle * tmpy;
y = origin.y + sinangle * tmpx + cosangle * tmpy;
}
}