View Javadoc

1   /* File Ray2D.java 
2    *
3    * Project : Java Geometry Library
4    *
5    * ===========================================
6    * 
7    * This library is free software; you can redistribute it and/or modify it 
8    * under the terms of the GNU Lesser General Public License as published by
9    * the Free Software Foundation, either version 2.1 of the License, or (at
10   * your option) any later version.
11   *
12   * This library is distributed in the hope that it will be useful, but 
13   * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
14   * or FITNESS FOR A PARTICULAR PURPOSE.
15   *
16   * See the GNU Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public License
19   * along with this library. if not, write to :
20   * The Free Software Foundation, Inc., 59 Temple Place, Suite 330,
21   * Boston, MA 02111-1307, USA.
22   */
23  
24  // package
25  
26  package math.geom2d.line;
27  
28  import java.awt.geom.GeneralPath;
29  
30  import math.geom2d.AffineTransform2D;
31  import math.geom2d.Box2D;
32  import math.geom2d.Point2D;
33  import math.geom2d.Shape2D;
34  import math.geom2d.UnboundedShapeException;
35  import math.geom2d.Vector2D;
36  
37  // Imports
38  
39  /**
40   * Ray, or half-line, defined from an origin and a direction vector. It is
41   * composed of all points satisfying the parametric equation:
42   * <p>
43   * <code>x(t) = x0+t*dx<code><br>
44   * <code>y(t) = y0+t*dy<code></p> 
45   * With <code>t<code> comprised between 0 and +INFINITY.
46   */
47  public class Ray2D extends AbstractLine2D implements Cloneable {
48  
49      // ===================================================================
50      // constants
51  
52      // ===================================================================
53      // class variables
54  
55      // ===================================================================
56      // constructors
57  
58      /**
59       * Empty constructor for Ray2D. Default is ray starting at origin, and
60       * having a slope of 1*dx and 0*dy.
61       */
62      public Ray2D() {
63          this(0, 0, 1, 0);
64      }
65  
66      /**
67       * Creates a new Ray2D, originating from
68       * <code>point1<\code>, and going in the
69       * direction of <code>point2<\code>.
70       */
71      public Ray2D(Point2D point1, Point2D point2) {
72          this(point1.getX(), point1.getY(), 
73          		point2.getX()-point1.getX(),
74          		point2.getY()-point1.getY());
75      }
76  
77      /**
78       * Creates a new Ray2D, originating from point
79       * <code>(x1,y1)<\code>, and going 
80       * in the direction defined by vector <code>(dx, dy)<\code>.
81       */
82      public Ray2D(double x1, double y1, double dx, double dy) {
83          super(x1, y1, dx, dy);
84      }
85  
86      /**
87       * Creates a new Ray2D, originating from point <code>point<\code>, and going 
88       * in the direction defined by vector <code>(dx,dy)<\code>.
89       */
90      public Ray2D(Point2D point, double dx, double dy) {
91          this(point.getX(), point.getY(), dx, dy);
92      }
93  
94      /**
95       * Creates a new Ray2D, originating from point <code>point<\code>, and going 
96       * in the direction specified by <code>vector<\code>.
97       */
98      public Ray2D(Point2D point, Vector2D vector) {
99          this(point.getX(), point.getY(), vector.getX(), vector.getY());
100     }
101 
102     /**
103      * Creates a new Ray2D, originating from point <code>point<\code>, and going 
104      * in the direction specified by <code>angle<\code> (in radians).
105      */
106     public Ray2D(Point2D point, double angle) {
107         this(point.getX(), point.getY(), Math.cos(angle), Math.sin(angle));
108     }
109 
110     /**
111      * Creates a new Ray2D, originating from point
112      * <code>(x, y)<\code>, and going 
113      * in the direction specified by <code>angle<\code> (in radians).
114      */
115     public Ray2D(double x, double y, double angle) {
116         this(x, y, Math.cos(angle), Math.sin(angle));
117     }
118 
119     /**
120      * Define a new Ray, with same characteristics as given object.
121      */
122     public Ray2D(LinearShape2D line) {
123         super(line);
124     }
125 
126     // ===================================================================
127     // methods specific to Ray2D
128 
129     /**
130      * Static factory for creating a new ray.
131      * @since 0.8.1
132      */
133     public final static Ray2D create(Point2D origin, Vector2D direction) {
134     	return new Ray2D(origin, direction);
135     }
136     
137     /**
138      * Static factory for creating a new ray, originating from
139      * <code>origin<\code>, and going in the
140      * direction of <code>target<\code>.
141      * @since 0.8.1
142      */
143     public final static Ray2D create(Point2D origin, Point2D target) {
144     	return new Ray2D(origin, target);
145     }
146     
147     /**
148      * @deprecated lines will become immutable in a future release
149      */
150     @Deprecated
151     public void setRay(double x0, double y0, double dx, double dy) {
152         this.x0 = x0;
153         this.y0 = y0;
154         this.dx = dx;
155         this.dy = dy;
156     }
157 
158     /**
159      * @deprecated lines will become immutable in a future release
160      */
161     @Deprecated
162     public void setRay(Point2D p1, Point2D p2) {
163         this.x0 = p1.getX();
164         this.y0 = p1.getY();
165         this.dx = p2.getX()-this.x0;
166         this.dy = p2.getY()-this.y0;
167     }
168 
169     /**
170      * @deprecated lines will become immutable in a future release
171      */
172     @Deprecated
173     public void setRay(Point2D point, Vector2D vect) {
174         this.x0 = point.getX();
175         this.y0 = point.getY();
176         this.dx = vect.getX();
177         this.dy = vect.getY();
178     }
179 
180 
181     // ===================================================================
182     // methods implementing the CirculinearCurve2D interface
183 
184 	/* (non-Javadoc)
185 	 * @see math.geom2d.circulinear.CirculinearCurve2D#getParallel(double)
186 	 */
187 	public Ray2D getParallel(double d) {
188         double dd = Math.sqrt(dx*dx+dy*dy);
189         return new Ray2D(x0+dy*d/dd, y0-dx*d/dd, dx, dy);
190 	}
191 
192     // ===================================================================
193     // methods implementing the ContinuousCurve2D interface
194 
195     /** Throws an infiniteShapeException */
196     public GeneralPath appendPath(GeneralPath path) {
197         throw new UnboundedShapeException(this);
198     }
199 
200     /** Throws an infiniteShapeException */
201     public java.awt.geom.GeneralPath getGeneralPath() {
202         throw new UnboundedShapeException(this);
203     }
204 
205     // ===================================================================
206     // methods implementing the Curve2D interface
207 
208 	@Override
209     public Point2D getFirstPoint() {
210         return new Point2D(x0, y0);
211     }
212 
213     public Point2D getPoint(double t) {
214         t = Math.max(t, 0);
215         return new Point2D(x0+t*dx, y0+t*dy);
216     }
217 
218     public double getT0() {
219         return 0;
220     }
221 
222     public double getT1() {
223         return Double.POSITIVE_INFINITY;
224     }
225 
226     public InvertedRay2D getReverseCurve() {
227         return new InvertedRay2D(x0, y0, -dx, -dy);
228     }
229 
230     // ===================================================================
231     // methods implementing the Shape2D interface
232 
233     /** Always returns false, because a ray is not bounded. */
234     public boolean isBounded() {
235         return false;
236     }
237 
238     public boolean contains(double x, double y) {
239         if (!this.supportContains(x, y))
240             return false;
241         double t = this.getPositionOnLine(x, y);
242         return t>-Shape2D.ACCURACY;
243     }
244 
245     public Box2D getBoundingBox() {
246         double t = Double.POSITIVE_INFINITY;
247         return new Box2D(x0, x0+t*dx, y0, y0+t*dy);
248     }
249 
250     @Override
251     public Ray2D transform(AffineTransform2D trans) {
252         double[] tab = trans.getCoefficients();
253         double x1 = x0*tab[0]+y0*tab[1]+tab[2];
254         double y1 = x0*tab[3]+y0*tab[4]+tab[5];
255         return new Ray2D(x1, y1, dx*tab[0]+dy*tab[1], dx*tab[3]+dy*tab[4]);
256     }
257 
258 
259     // ===================================================================
260     // methods implementing the Object interface
261 
262     @Override
263     public String toString() {
264         return new String("Ray2D(" + x0 + "," + y0 + "," + 
265         		dx + "," + dy + ")");
266     }
267     
268     @Override
269     public boolean equals(Object obj) {
270         if (!(obj instanceof Ray2D))
271             return false;
272         Ray2D ray = (Ray2D) obj;
273         if (Math.abs(x0-ray.x0)>Shape2D.ACCURACY)
274             return false;
275         if (Math.abs(y0-ray.y0)>Shape2D.ACCURACY)
276             return false;
277         if (Math.abs(dx-ray.dx)>Shape2D.ACCURACY)
278             return false;
279         if (Math.abs(dy-ray.dy)>Shape2D.ACCURACY)
280             return false;
281         return true;
282     }
283 
284     @Override
285     public Ray2D clone() {
286         return new Ray2D(x0, y0, dx, dy);
287         
288     }
289 }