package ProGAL.geom3d; import java.awt.Color; //import ProGAL.geom3d.viewer.J3DScene; import ProGAL.geom3d.volumes.Cylinder; import ProGAL.math.Constants; /** * A line represented by a point and a direction. Several methods work with a * parameter that can be used to specify a point on the line. For instance *
* Line3d l = new Line3d( new Point3d(0,0,0), new Vector3d(2,0,0) ); * System.out.println( l.getPoint( 0.0 ) ); * System.out.println( l.getPoint( 1.0 ) ); ** will print the points (0,0,0) and (2,0,0). Similarly, the lines *
* l.orthogonalProjection(new Point3d(1,1,0)); * l.orthogonalProjectionParameter(new Point3d(1,1,0)); ** will return the point (1,0,0) and the parameter 0.5 respectively. */ public class Line { protected Point p; protected Vector dir; /** Constructs a line through origo with direction d. */ public Line(Vector d) { p = new Point(0, 0, 0); dir = d.normalize(); } /** Constructs a line through p with direction d.*/ public Line(Point p, Vector d) { this.p = p; dir = d.normalize(); } /** * Constructs a line through the segment s. The point will be s.getA() and the direction * will be s.getAToB(). Subsequent changes to the line segment should not change this line. */ public Line(LineSegment s) { p = s.getA().clone(); dir = s.getAToB().normalize(); } /** Constructs a line through the two specified points. */ public Line(Point p1, Point p2){ this(p1, p1.vectorTo(p2)); } /** Constructs a line trisecting three points */ public Line(Point a, Point b, Point c) { Circle circle = new Circle(a,b,c); p = circle.getCenter(); dir = new Vector(a,b).cross(new Vector(a,c)).normalizeThis(); } /** Construct a line that is a clone of L. */ public Line clone() { return new Line(new Point(p), new Vector(dir)); } /** Returns the point defining this line. */ public Point getP() { return p; } /** Returns the direction vector defining this line. */ public Vector getDir() { return dir; } /** Gets the point on the line defined by the specified parameter. If the parameter is * zero this method will not return a reference to the defining point (but the returned * point will equal it). */ public Point getPoint(double t) { return new Point(p.x() + t*dir.x(), p.y() + t*dir.y(), p.z() + t*dir.z()); } /** Returns the othogonal projection of the point q onto this line. */ public Point orthogonalProjection(Point q) { return getPoint(orthogonalProjectionParameter(q)); } /** Returns the line-parameter of the othogonal projection of the point q onto this line. */ public double orthogonalProjectionParameter(Point q) { Vector pq = p.vectorTo(q); return pq.dot(dir)/dir.getLengthSquared(); } /** Returns the smallest segment that contains all orthogonol * projections of a point set onto this line. */ public LineSegment orthogonalProjection(PointList points) { double minT = Double.POSITIVE_INFINITY, maxT = Double.NEGATIVE_INFINITY; for(Point q: points){ double t = orthogonalProjectionParameter(q); minT = Math.min(minT, t); maxT = Math.max(maxT, t); } return new LineSegment(getPoint(minT), getPoint(maxT)); } /** Returns the line-parameters of the end-points of the smallest segment that * contains all orthogonol projections of a point set onto this line. * @return a double-array with two entries containing the smallest and largest * orthogonal projection line-parameter of the point-set.*/ public double[] orthogonalProjectionParameters(PointList points) { double minT = Double.POSITIVE_INFINITY, maxT = Double.NEGATIVE_INFINITY; for(Point q: points){ double t = orthogonalProjectionParameter(q); minT = Math.min(minT, t); maxT = Math.max(maxT, t); } return new double[]{minT, maxT}; } /** Gets the squared orthogonal distance to a point. */ public double getDistanceSquared(Point q) { return dir.cross(q.vectorTo(p)).getLengthSquared()/dir.getLengthSquared(); } /** Gets the orthogonal distance to a point. */ public double getDistance(Point q) { return Math.sqrt(getDistanceSquared(q)); } /** * Gets the minimum squared distance to another line. * @see [Ericsson 05, p. 147] * @hop 14-32 */ public double getSquaredDistance(Line l) { double a = dir.getLengthSquared(); double b = dir.dot(l.dir); double e = l.dir.getLengthSquared(); double d = a*e-b*b; if(Math.abs(d)
double S = m[0].distanceSquared(f[0]) + ... + m[m.length-1].distanceSquared(f[m.length-1]);
* This method follows the description by Canutescu and Dunbrack 2003.
* @param moving Array of effector points
* @param target Array of target points
* @return an angle which the effector points should be rotated so they come close to the target points.
*/
public double optimalRotation(Point[] moving, Point[] target){
Point[] m = moving;
Point[] f = target;
if(f.length!=m.length) throw new RuntimeException("Lengths must match");
double tanNum = 0, tanDenom = 0;
for(int i=0;i