Back to index

moin  1.9.0~rc2
Geom.java
Go to the documentation of this file.
00001 /*
00002  * @(#)Geom.java 5.1
00003  *
00004  */
00005 
00006 package CH.ifa.draw.util;
00007 
00008 import java.awt.Rectangle;
00009 import java.awt.Point;
00010 
00014 public class Geom {
00015 
00016     private Geom() {}; // never instantiated
00017 
00021     static public boolean lineContainsPoint(int x1, int y1,
00022                             int x2, int y2,
00023                             int px, int py) {
00024 
00025         Rectangle r = new Rectangle(new Point(x1, y1));
00026         r.add(x2, y2);
00027 
00028         r.grow(2,2);
00029         if (! r.contains(px,py))
00030             return false;
00031 
00032         double a, b, x, y;
00033 
00034         if (x1 == x2)
00035             return (Math.abs(px - x1) < 3);
00036 
00037         if (y1 == y2)
00038             return (Math.abs(py - y1) < 3);
00039 
00040         a = (double)(y1 - y2) / (double)(x1 - x2);
00041         b = (double)y1 - a * (double)x1;
00042         x = (py - b) / a;
00043         y = a * px + b;
00044 
00045         return (Math.min(Math.abs(x - px), Math.abs(y - py)) < 4);
00046     }
00047 
00048     static public final int NORTH = 1;
00049     static public final int SOUTH = 2;
00050     static public final int WEST = 3;
00051     static public final int EAST = 4;
00052 
00057     static public int direction(int x1, int y1, int x2, int y2) {
00058         int direction = 0;
00059         int vx = x2 - x1;
00060         int vy = y2 - y1;
00061 
00062         if (vy < vx && vx > -vy)
00063             direction = EAST;
00064         else if (vy > vx && vy > -vx)
00065             direction = NORTH;
00066         else if (vx < vy && vx < -vy)
00067             direction = WEST;
00068         else
00069             direction = SOUTH;
00070         return direction;
00071     }
00072 
00073     static public Point south(Rectangle r) {
00074         return new Point(r.x + r.width /2, r.y + r.height);
00075     }
00076 
00077     static public Point center(Rectangle r) {
00078         return new Point(r.x + r.width /2, r.y + r.height/2);
00079     }
00080 
00081     static public Point west(Rectangle r) {
00082         return new Point(r.x, r.y + r.height/ 2);
00083     }
00084 
00085     static public Point east(Rectangle r) {
00086         return new Point(r.x+r.width, r.y + r.height/ 2);
00087     }
00088 
00089     static public Point north(Rectangle r) {
00090         return new Point(r.x+r.width/2, r.y);
00091     }
00092 
00097     static public int range(int min, int max, int value) {
00098         if (value < min)
00099             value = min;
00100         if (value > max)
00101             value = max;
00102         return value;
00103     }
00104 
00108     static public long length2(int x1, int y1, int x2, int y2) {
00109         return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
00110     }
00111 
00115     static public long length(int x1, int y1, int x2, int y2) {
00116         return (long)Math.sqrt(length2(x1, y1, x2, y2));
00117     }
00118 
00122     static public double pointToAngle(Rectangle r, Point p) {
00123         int px = p.x - (r.x+r.width/2);
00124         int py = p.y - (r.y+r.height/2);
00125         return Math.atan2(py*r.width, px*r.height);
00126     }
00127 
00131     static public Point angleToPoint(Rectangle r, double angle) {
00132         double si = Math.sin(angle);
00133         double co = Math.cos(angle);
00134         double e = 0.0001;
00135 
00136        int x= 0, y= 0;
00137            if (Math.abs(si) > e) {
00138                   x= (int) ((1.0 + co/Math.abs(si))/2.0 * r.width);
00139                   x= range(0, r.width, x);
00140            } else if (co >= 0.0)
00141                   x= r.width;
00142            if (Math.abs(co) > e) {
00143                   y= (int) ((1.0 + si/Math.abs(co))/2.0 * r.height);
00144                   y= range(0, r.height, y);
00145            } else if (si >= 0.0)
00146                   y= r.height;
00147            return new Point(r.x + x, r.y + y);
00148     }
00149 
00153     static public Point polarToPoint(double angle, double fx, double fy) {
00154         double si = Math.sin(angle);
00155         double co = Math.cos(angle);
00156            return new Point((int)(fx*co+0.5), (int)(fy*si+0.5));
00157     }
00158 
00162     static public Point ovalAngleToPoint(Rectangle r, double angle) {
00163         Point center = Geom.center(r);
00164         Point p = Geom.polarToPoint(angle, r.width/2, r.height/2);
00165         return new Point(center.x + p.x, center.y + p.y);
00166     }
00167 
00172    // from Doug Lea's PolygonFigure
00173   static public Point intersect(int xa, // line 1 point 1 x
00174                                 int ya, // line 1 point 1 y
00175                                 int xb, // line 1 point 2 x
00176                                 int yb, // line 1 point 2 y
00177                                 int xc, // line 2 point 1 x
00178                                 int yc, // line 2 point 1 y
00179                                 int xd, // line 2 point 2 x
00180                                 int yd) { // line 2 point 2 y
00181 
00182     // source: http://vision.dai.ed.ac.uk/andrewfg/c-g-a-faq.html
00183     // eq: for lines AB and CD
00184     //     (YA-YC)(XD-XC)-(XA-XC)(YD-YC)
00185     // r = -----------------------------  (eqn 1)
00186     //     (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
00187     //
00188     //     (YA-YC)(XB-XA)-(XA-XC)(YB-YA)
00189     // s = -----------------------------  (eqn 2)
00190     //     (XB-XA)(YD-YC)-(YB-YA)(XD-XC)
00191     //  XI = XA + r(XB-XA)
00192     //  YI = YA + r(YB-YA)
00193 
00194     double denom = ((xb - xa) * (yd - yc) - (yb - ya) * (xd - xc));
00195 
00196     double rnum = ((ya - yc) * (xd - xc) - (xa - xc) * (yd - yc));
00197 
00198     if (denom == 0.0) { // parallel
00199       if (rnum == 0.0) { // coincident; pick one end of first line
00200         if ((xa < xb && (xb < xc || xb < xd)) ||
00201             (xa > xb && (xb > xc || xb > xd)))
00202           return new Point(xb, yb);
00203         else
00204           return new Point(xa, ya);
00205       }
00206       else
00207         return null;
00208     }
00209 
00210     double r = rnum / denom;
00211 
00212     double snum = ((ya - yc) * (xb - xa) - (xa - xc) * (yb - ya));
00213     double s = snum / denom;
00214 
00215     if (0.0 <= r && r <= 1.0 && 0.0 <= s && s <= 1.0) {
00216       int px = (int)(xa + (xb - xa) * r);
00217       int py = (int)(ya + (yb - ya) * r);
00218       return new Point(px, py);
00219     }
00220     else
00221       return null;
00222   }
00223 
00224 }