package ProGAL.geom2d;
import java.awt.Color;
import ProGAL.geom2d.Line;
import ProGAL.math.Constants;
import ProGAL.math.Functions;
/**
* A point in (x,y)-space represented using double precision.
* @author R.Fonseca
*/
public class Point extends ProGAL.geomNd.Point {
private static final long serialVersionUID = 8095991200265432551L;
public static Point origo = new Point(0.0, 0.0);
/** Construct a point at (0,0) */
public Point() { this(0,0); }
/** Construct a point with the specified coordinates. */
public Point(double x, double y) { super(new double[]{x,y}); }
/** Construct a point with the specified coordinates. */
public Point(double[] coords) { super(coords); }
/** Construct a point with the same two first coordinates as p. */
public Point(ProGAL.geomNd.Point p){
this(p.getCoords());
}
/** Return the x-coordinate */
public double x(){ return coords[0]; }
/** Return the y-coordinate */
public double y(){ return coords[1]; }
public Point clone(){
return new Point(coords[0], coords[1]);
}
/** Return a vector pointing from this point to p
*/
public Vector vectorTo(Point p){
return new Vector(p.coords[0]-coords[0], p.coords[1]-coords[1]);
}
/** Add the vector v
to this point and return the result */
public Point add(Vector v){ return new Point(x()+v.x(), y()+v.y()); };
public Point add(double a, double b) { return new Point(x() + a, y() + b); }
/** Add the vector v
to this point and return the result (changes this object) */
public Point addThis(Vector v){ coords[0] += v.x(); coords[1] += v.y(); return this; }
public Point addThis(Point p){ coords[0] += p.x(); coords[1] += p.y(); return this; }
public Point addThis(double a, double b) { coords[0] += a; coords[1] += b; return this; }
/** Subtract the vector v
from this point and return the result */
public Point subtract(Vector v){ return new Point(x()-v.x(), y()-v.y()); }
/** Subtract the vector v
from this point and return the result (changes this object) */
public Point subtractThis(Vector v){ coords[0] -= v.x(); coords[1] -= v.y(); return this; }
public Point subtractThis(Point p) { coords[0] -= p.x(); coords[1] -= p.y(); return this; }
/** Returns the signed area of the triangle defined by the three points a, b and c (positive if counterclockwise) */
public static double area(Point a, Point b, Point c) {
return a.x()*(b.y()-c.y()) + a.y()*(c.x()-b.x()) + b.x()*c.y() - c.x()*b.y();
}
/* Returns true if the three points a, b, and c are collinear */
public static boolean collinear(Point a, Point b, Point c) { return area(a, b, c) < Constants.EPSILON; }
/** returns squared distance of this point to the origo. */
public double getSquaredDistance() { return x()*x() + y()*y(); }
/** returns squared distance of this point to point q. */
public double getSquaredDistance(Point q) { return Math.pow(x()-q.x(), 2) + Math.pow(y()-q.y(), 2); }
/** returns squared distance of this point to segment s */
public double getSquaredDistance(LineSegment s) {
double squaredSegmentLength = s.getSquaredLength();
if (squaredSegmentLength == 0.0) return getSquaredDistance(s.a);
double sx = s.b.x() - s.a.x();
double sy = s.b.y() - s.a.y();
double t = ((x() - s.a.x()) * sx + (y() - s.a.y()) * sy)/squaredSegmentLength;
if (t < 0) return getSquaredDistance(s.a);
if (t > 1) return getSquaredDistance(s.b);
return getSquaredDistance(new Point(s.a.x() + t*sx, s.a.y() + t*sy));
}
/** returns distance of this point to segment s */
public double getDistance(LineSegment s) { return Math.sqrt(getSquaredDistance(s)); }
/** Returns the angle between the points, but if they make a left turn the angle will be negative. */
public static double getSignedAngle(Point p1, Point p2, Point p3){
Vector v1 = p2.vectorTo(p1);
Vector v2 = p2.vectorTo(p3);
return Math.atan2(v1.x()*v2.y()-v1.y()*v2.x(), v1.dot(v2));
}
/** Returns a positive double if the point is inside the circle through the 3 specified points (must be in clockwise order). */
public static double inCircle(Point p, Point q, Point r, Point s) {
double pp = p.x()*p.x() + p.y()*p.y();
double qq = q.x()*q.x() + q.y()*q.y();
double rr = r.x()*r.x() + r.y()*r.y();
double ss = s.x()*s.x() + s.y()*s.y();
return pp*(q.x()*(r.y()-s.y()) + q.y()*(s.x()-r.x()) + r.x()*s.y() - r.y()*s.x()) -
qq*(p.x()*(r.y()-s.y()) + p.y()*(s.x()-r.x()) + r.x()*s.y() - r.y()*s.x()) +
rr*(p.x()*(q.y()-s.y()) + p.y()*(s.x()-q.x()) + q.x()*s.y() - q.y()*s.x()) -
ss*(p.x()*(q.y()-r.y()) + p.y()*(r.x()-q.x()) + q.x()*r.y() - q.y()*r.x());
}
/** Returns polar angle of this point */
public double polarAngle() {
double angle = Math.acos(polarAngleCos());
if ((coords[1] < 0) || ((coords[1] == 0.0) && (coords[0] < 0.0))) angle = Constants.TAU - angle;
return angle;
}
/** Returns the sinus of the polar angle of this point */
public double polarAngleSin() { return coords[1]/distance(); }
/** Returns the cosinus of the polar angle of this point */
public double polarAngleCos() { return coords[0]/distance(); }
/** Returns true if points a, b and c make a left turn at b */
public static boolean leftTurn(Point a, Point b, Point c ) { return area(a,b,c) > 0.0; }
/** Returns true if points a, b and c make a right turn at b or are colinear */
public static boolean rightTurn(Point a, Point b, Point c ) { return area(a,b,c) <= 0.0; }
/** Returns the midpoint of two points. */
public static Point midPoint(Point p, Point q) { return new Point((p.coords[0] + q.coords[0])/2, (p.coords[1] + q.coords[1])/2); }
/** Creates a bisector line between points p and q */
public static Line getBisector(Point p, Point q) {
if (!p.equals(q)) return new Line(midPoint(p,q), p.vectorTo(q));
return null;
}
/** Returns the line y = ax + b() where the coordinates of this point are (a,b) */
public Line getDualLine() { return new Line(x(), y()); }
/** Return true iff o
is a Point that has the same same coordinates as this. */
public boolean equals(Object o){
if(o instanceof Point) return equals((Point)o);
return false;
}
/** Return true iff p
has the same same coordinates as this. */
public boolean equals(Point p){
return Math.abs(coords[0]-p.coords[0])