cafa081ff6e6e236996c4e6dad5f8c8fde0c71dc
[anneal.git] / src / edu / berkeley / qfat / geom / Line.java
1 package edu.berkeley.qfat.geom;
2 import javax.media.opengl.*;
3
4 /** an infinitely long line in 3-space */
5 public class Line implements AffineConstraint {
6
7     // y=mx+c
8     // z=nx+d
9     public final float m, n, c, d;
10
11     /** the line passing through two points */
12     public Line(Point p1, Point p2) {
13         // FIXME: division by zero?
14         this.m = (p2.y-p1.y)/(p2.x-p1.x);
15         this.n = (p2.z-p1.z)/(p2.x-p1.x);
16         this.c = p1.y - m * p1.x;
17         this.d = p1.z - n * p1.x;
18     }
19
20     /** the line passing through p1 with direction v */
21     public Line(Point p1, Vec v) {
22         this(p1, v.plus(p1));
23     }
24
25     public int hashCode() {
26         return
27             Float.floatToIntBits(m) ^
28             Float.floatToIntBits(n) ^
29             Float.floatToIntBits(c) ^
30             Float.floatToIntBits(d);
31     }
32     public boolean equals(Object o) {
33         if (o==null || !(o instanceof Line)) return false;
34         Line line = (Line)o;
35         return line.m==m && line.n==n && line.c==c && line.d==d;
36     }
37
38     public String toString() {
39         return "[line: y="+m+"x+"+c+" z="+n+"x+"+d+"]";
40     }
41
42     public double distance(Point p) { return getProjection(p).distance(p); }
43
44     public Vec getUnit() {
45         Point p1 = new Point(0, c,   d);
46         Point p2 = new Point(1, m+c, n+d);
47         return p2.minus(p1).norm();
48     }
49
50     /** returns the point on this line which is closest to p */
51     public Point getProjection(Point p) {
52         Point p1 = new Point(0, c,   d);
53         Point p2 = new Point(1, m+c, n+d);
54         Vec w = p.minus(p1);
55         return p1.plus(getUnit().times(w.dot(getUnit())));
56         /*
57         throw new RuntimeException("test this before using; may not be correct");
58         */
59     }
60
61     public AffineConstraint intersect(AffineConstraint con, float epsilon) {
62         if (!(con instanceof Line)) return con.intersect(this, epsilon);
63         Line line = (Line)con;
64         if (Math.abs(this.m-line.m) <= epsilon &&
65             Math.abs(this.n-line.n) <= epsilon &&
66             Math.abs(this.c-line.c) <= epsilon &&
67             Math.abs(this.d-line.d) <= epsilon)
68             return this;
69         float x = (line.c-this.c)/(this.m-line.m);
70         if (Math.abs( (m*x+c)-(line.m*x+line.c) ) > epsilon ) return null;
71         if (Math.abs( (n*x+d)-(line.n*x+line.d) ) > epsilon ) return null;
72         return new Point(x, m*x+c, n*x+d);
73     }
74
75     public AffineConstraint multiply(Matrix m) {
76         // FIXME: ugly
77         Point p1 = new Point(0, c, d);
78         Point p2 = new Point(1, this.m+c, n+d);
79         return new Line(m.times(p1), m.times(p2));
80     }
81
82 }