View Javadoc

1   /**
2    * 
3    */
4   
5   package math.geom3d.plane;
6   
7   import math.geom2d.Point2D;
8   import math.geom3d.Box3D;
9   import math.geom3d.Point3D;
10  import math.geom3d.Shape3D;
11  import math.geom3d.Vector3D;
12  import math.geom3d.line.StraightLine3D;
13  import math.geom3d.transform.AffineTransform3D;
14  
15  /**
16   * @author dlegland
17   */
18  public class Plane3D implements Shape3D {
19  
20      // ===================================================================
21      // class variables
22  
23      protected double x0  = 0;
24      protected double y0  = 0;
25      protected double z0  = 0;
26      protected double dx1 = 1;
27      protected double dy1 = 0;
28      protected double dz1 = 0;
29      protected double dx2 = 0;
30      protected double dy2 = 1;
31      protected double dz2 = 0;
32  
33      // ===================================================================
34      // static methods
35  
36      public final static Plane3D createXYPlane() {
37          return new Plane3D(new Point3D(0, 0, 0), new Vector3D(1, 0, 0),
38                  new Vector3D(0, 1, 0));
39      }
40  
41      public final static Plane3D createXZPlane() {
42          return new Plane3D(new Point3D(0, 0, 0), new Vector3D(1, 0, 0),
43                  new Vector3D(0, 0, 1));
44      }
45  
46      public final static Plane3D createYZPlane() {
47          return new Plane3D(new Point3D(0, 0, 0), new Vector3D(0, 1, 0),
48                  new Vector3D(0, 0, 1));
49      }
50  
51      // ===================================================================
52      // constructors
53  
54      public Plane3D() {
55      }
56  
57      public Plane3D(Point3D point, Vector3D vector1, Vector3D vector2) {
58          this.x0 = point.getX();
59          this.y0 = point.getY();
60          this.z0 = point.getZ();
61          this.dx1 = vector1.getX();
62          this.dy1 = vector1.getY();
63          this.dz1 = vector1.getZ();
64          this.dx2 = vector2.getX();
65          this.dy2 = vector2.getY();
66          this.dz2 = vector2.getZ();
67      }
68  
69      // ===================================================================
70      // methods specific to Plane3D
71  
72      public Point3D getOrigin() {
73          return new Point3D(x0, y0, z0);
74      }
75  
76      public Vector3D getVector1() {
77          return new Vector3D(dx1, dy1, dz1);
78      }
79  
80      public Vector3D getVector2() {
81          return new Vector3D(dx2, dy2, dz2);
82      }
83  
84      /**
85       * Points towars the outside part of the plane.
86       * 
87       * @return the outer normal vector.
88       */
89      public Vector3D getNormalVector() {
90          return Vector3D.crossProduct(this.getVector1(), this.getVector2())
91                  .getOpposite();
92      }
93  
94      /**
95       * Compute intersection of a line with this plane. Uses algorithm 1 given
96       * in: <a href="http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/">
97       * http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/</a>.
98       * 
99       * @param line the line which intersects the plane
100      * @return the intersection point
101      */
102     public Point3D getLineIntersection(StraightLine3D line) {
103         // the plane normal
104         Vector3D n = this.getNormalVector();
105 
106         // the difference between origin of plane and origin of line
107         Vector3D dp = new Vector3D(line.getOrigin(), this.getOrigin());
108 
109         // compute ratio of dot products,
110         // see http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/
111         double t = Vector3D.dotProduct(n, dp)
112                 /Vector3D.dotProduct(n, line.getDirection());
113 
114         return line.getPoint(t);
115     }
116 
117     public Point3D projectPoint(Point3D point) {
118         StraightLine3D line = new StraightLine3D(point, this.getNormalVector());
119         return this.getLineIntersection(line);
120     }
121 
122     public Vector3D projectVector(Vector3D vect) {
123         Point3D point = new Point3D(x0+vect.getX(), y0+vect.getY(), z0
124                 +vect.getZ());
125         point = this.projectPoint(point);
126         return new Vector3D(point.getX()-x0, point.getY()-y0, point.getZ()-z0);
127     }
128 
129     public Point3D getPoint(double u, double v) {
130         return new Point3D(x0+u*dx1+v*dx2, y0+u*dy1+v*dy2, z0+u*dz1+v*dz2);
131     }
132 
133     public Point2D getPointPosition(Point3D point) {
134         point = this.projectPoint(point);
135         throw new UnsupportedOperationException();
136     }
137 
138     // ===================================================================
139     // methods implementing Shape3D interface
140 
141     /*
142      * (non-Javadoc)
143      * 
144      * @see math.geom3d.Shape3D#clip(math.geom3d.Box3D)
145      */
146     public Shape3D clip(Box3D box) {
147         // TODO Auto-generated method stub
148     	throw new UnsupportedOperationException();
149     }
150 
151     /*
152      * (non-Javadoc)
153      * 
154      * @see math.geom3d.Shape3D#contains(math.geom3d.Point3D)
155      */
156     public boolean contains(Point3D point) {
157         Point3D proj = this.projectPoint(point);
158         return (point.getDistance(proj)<Shape3D.ACCURACY);
159     }
160 
161     /*
162      * (non-Javadoc)
163      * 
164      * @see math.geom3d.Shape3D#getBoundingBox()
165      */
166     public Box3D getBoundingBox() {
167         // plane parallel to XY plane
168         if (Math.abs(dz1)<Shape3D.ACCURACY&&Math.abs(dz2)<Shape3D.ACCURACY)
169             return new Box3D(Double.NEGATIVE_INFINITY,
170                     Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,
171                     Double.POSITIVE_INFINITY, z0, z0);
172 
173         // plane parallel to YZ plane
174         if (Math.abs(dx1)<Shape3D.ACCURACY&&Math.abs(dx2)<Shape3D.ACCURACY)
175             return new Box3D(x0, x0, Double.NEGATIVE_INFINITY,
176                     Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,
177                     Double.POSITIVE_INFINITY);
178 
179         // plane parallel to XZ plane
180         if (Math.abs(dy1)<Shape3D.ACCURACY&&Math.abs(dy2)<Shape3D.ACCURACY)
181             return new Box3D(Double.NEGATIVE_INFINITY,
182                     Double.POSITIVE_INFINITY, y0, y0, Double.NEGATIVE_INFINITY,
183                     Double.POSITIVE_INFINITY);
184 
185         return new Box3D(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
186                 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
187                 Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
188     }
189 
190     /*
191      * (non-Javadoc)
192      * 
193      * @see math.geom3d.Shape3D#getDistance(math.geom3d.Point3D)
194      */
195     public double getDistance(Point3D point) {
196         return point.getDistance(this.projectPoint(point));
197     }
198 
199     /*
200      * (non-Javadoc)
201      * 
202      * @see math.geom3d.Shape3D#isBounded()
203      */
204     public boolean isBounded() {
205         return false;
206     }
207 
208     /*
209      * (non-Javadoc)
210      * 
211      * @see math.geom3d.Shape3D#isEmpty()
212      */
213     public boolean isEmpty() {
214         return false;
215     }
216 
217     /*
218      * (non-Javadoc)
219      * 
220      * @see math.geom3d.Shape3D#transform(math.geom3d.transform.AffineTransform3D)
221      */
222     public Shape3D transform(AffineTransform3D trans) {
223         return new Plane3D(this.getOrigin().transform(trans), this.getVector1()
224                 .transform(trans), this.getVector2().transform(trans));
225     }
226 
227     // ===================================================================
228     // methods overriding Object superclass
229 
230     @Override
231     public boolean equals(Object obj) {
232         if (!(obj instanceof Plane3D))
233             return false;
234         Plane3D plane = (Plane3D) obj;
235 
236         if (Math.abs(this.x0-plane.x0)>Shape3D.ACCURACY)
237             return false;
238         if (Math.abs(this.y0-plane.y0)>Shape3D.ACCURACY)
239             return false;
240         if (Math.abs(this.z0-plane.z0)>Shape3D.ACCURACY)
241             return false;
242         if (Math.abs(this.dx1-plane.dx1)>Shape3D.ACCURACY)
243             return false;
244         if (Math.abs(this.dy1-plane.dy1)>Shape3D.ACCURACY)
245             return false;
246         if (Math.abs(this.dz1-plane.dz1)>Shape3D.ACCURACY)
247             return false;
248         if (Math.abs(this.dx2-plane.dx2)>Shape3D.ACCURACY)
249             return false;
250         if (Math.abs(this.dy2-plane.dy2)>Shape3D.ACCURACY)
251             return false;
252         if (Math.abs(this.dz2-plane.dz2)>Shape3D.ACCURACY)
253             return false;
254         return true;
255     }
256 
257 }