package com.kreative.paint.document.draw; import java.awt.geom.Point2D; public class PathPoint extends Point2D implements Cloneable { private double pcdx; private double pcdy; private boolean pcQuadratic; private double x; private double y; private boolean lockAngle; private boolean lockRadius; private double ncdx; private double ncdy; private boolean ncQuadratic; public PathPoint(double x, double y) { this.pcdx = 0; this.pcdy = 0; this.pcQuadratic = false; this.x = x; this.y = y; this.lockAngle = false; this.lockRadius = false; this.ncdx = 0; this.ncdy = 0; this.ncQuadratic = false; } private PathPoint(PathPoint o) { this.pcdx = o.pcdx; this.pcdy = o.pcdy; this.pcQuadratic = o.pcQuadratic; this.x = o.x; this.y = o.y; this.lockAngle = o.lockAngle; this.lockRadius = o.lockRadius; this.ncdx = o.ncdx; this.ncdy = o.ncdy; this.ncQuadratic = o.ncQuadratic; } @Override public PathPoint clone() { return new PathPoint(this); } public Point2D getPreviousCtrl() { return new Point2D.Double(x + pcdx, y + pcdy); } public boolean isPreviousLinear() { return ((pcdx == 0) && (pcdy == 0)); } public boolean isPreviousQuadratic() { return pcQuadratic; } @Override public double getX() { return x; } @Override public double getY() { return y; } public Point2D getLocation() { return new Point2D.Double(x, y); } public boolean isAngleLocked() { return lockAngle; } public boolean isRadiusLocked() { return lockRadius; } public Point2D getNextCtrl() { return new Point2D.Double(x + ncdx, y + ncdy); } public boolean isNextLinear() { return ((ncdx == 0) && (ncdy == 0)); } public boolean isNextQuadratic() { return ncQuadratic; } public void setPreviousCtrl(Point2D p) { setPreviousCtrl(p.getX(), p.getY()); } public void setPreviousCtrl(double pcx, double pcy) { this.pcdx = pcx - x; this.pcdy = pcy - y; if (lockAngle && lockRadius) { this.ncdx = -pcdx; this.ncdy = -pcdy; } else if (lockAngle || lockRadius) { double or = oppRadius(pcdy, pcdx, ncdy, ncdx); double oa = oppAngle(pcdy, pcdx, ncdy, ncdx); this.ncdx = or * Math.cos(oa); this.ncdy = or * Math.sin(oa); } } public void setPreviousLinear() { this.pcdx = 0; this.pcdy = 0; if (lockRadius) { this.ncdx = 0; this.ncdy = 0; } } public void setPreviousQuadratic(boolean quadratic) { this.pcQuadratic = quadratic; } @Override public void setLocation(Point2D p) { setLocation(p.getX(), p.getY()); } @Override public void setLocation(double x, double y) { this.x = x; this.y = y; } public void setAngleLocked(boolean locked) { this.lockAngle = locked; } public void setRadiusLocked(boolean locked) { this.lockRadius = locked; } public void setNextCtrl(Point2D p) { setNextCtrl(p.getX(), p.getY()); } public void setNextCtrl(double ncx, double ncy) { this.ncdx = ncx - x; this.ncdy = ncy - y; if (lockAngle && lockRadius) { this.pcdx = -ncdx; this.pcdy = -ncdy; } else if (lockAngle || lockRadius) { double or = oppRadius(ncdy, ncdx, pcdy, pcdx); double oa = oppAngle(ncdy, ncdx, pcdy, pcdx); this.pcdx = or * Math.cos(oa); this.pcdy = or * Math.sin(oa); } } public void setNextLinear() { this.ncdx = 0; this.ncdy = 0; if (lockRadius) { this.pcdx = 0; this.pcdy = 0; } } public void setNextQuadratic(boolean quadratic) { this.ncQuadratic = quadratic; } @Override public boolean equals(Object that) { if (that instanceof PathPoint) { return (this.pcdx == ((PathPoint)that).pcdx) && (this.pcdy == ((PathPoint)that).pcdy) && (this.pcQuadratic == ((PathPoint)that).pcQuadratic) && (this.x == ((PathPoint)that).x) && (this.y == ((PathPoint)that).y) && (this.lockAngle == ((PathPoint)that).lockAngle) && (this.lockRadius == ((PathPoint)that).lockRadius) && (this.ncdx == ((PathPoint)that).ncdx) && (this.ncdy == ((PathPoint)that).ncdy) && (this.ncQuadratic == ((PathPoint)that).ncQuadratic); } else { return false; } } @Override public int hashCode() { return java.lang.Float.floatToRawIntBits((float)pcdx) ^ java.lang.Float.floatToRawIntBits((float)pcdy) ^ (pcQuadratic ? 0x11111111 : 0) ^ java.lang.Float.floatToRawIntBits((float)x) ^ java.lang.Float.floatToRawIntBits((float)y) ^ (lockAngle ? 0x22222222 : 0) ^ (lockRadius ? 0x44444444 : 0) ^ java.lang.Float.floatToRawIntBits((float)ncdx) ^ java.lang.Float.floatToRawIntBits((float)ncdy) ^ (ncQuadratic ? 0x88888888 : 0); } private double oppRadius(double dy, double dx, double ody, double odx) { if (lockRadius) { double r = Math.hypot(dy, dx); if (!(java.lang.Double.isNaN(r) || java.lang.Double.isInfinite(r))) return r; } double r = Math.hypot(ody, odx); if (!(java.lang.Double.isNaN(r) || java.lang.Double.isInfinite(r))) return r; return 0; } private double oppAngle(double dy, double dx, double ody, double odx) { if (lockAngle) { double a = Math.atan2(-dy, -dx); if (!(java.lang.Double.isNaN(a) || java.lang.Double.isInfinite(a))) return a; } double a = Math.atan2(ody, odx); if (!(java.lang.Double.isNaN(a) || java.lang.Double.isInfinite(a))) return a; return 0; } }