View Javadoc
1   /*
2    * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.awt.geom;
27  
28  import java.awt.geom.Rectangle2D;
29  import java.awt.geom.PathIterator;
30  import java.util.Vector;
31  
32  final class Order1 extends Curve {
33      private double x0;
34      private double y0;
35      private double x1;
36      private double y1;
37      private double xmin;
38      private double xmax;
39  
40      public Order1(double x0, double y0,
41                    double x1, double y1,
42                    int direction)
43      {
44          super(direction);
45          this.x0 = x0;
46          this.y0 = y0;
47          this.x1 = x1;
48          this.y1 = y1;
49          if (x0 < x1) {
50              this.xmin = x0;
51              this.xmax = x1;
52          } else {
53              this.xmin = x1;
54              this.xmax = x0;
55          }
56      }
57  
58      public int getOrder() {
59          return 1;
60      }
61  
62      public double getXTop() {
63          return x0;
64      }
65  
66      public double getYTop() {
67          return y0;
68      }
69  
70      public double getXBot() {
71          return x1;
72      }
73  
74      public double getYBot() {
75          return y1;
76      }
77  
78      public double getXMin() {
79          return xmin;
80      }
81  
82      public double getXMax() {
83          return xmax;
84      }
85  
86      public double getX0() {
87          return (direction == INCREASING) ? x0 : x1;
88      }
89  
90      public double getY0() {
91          return (direction == INCREASING) ? y0 : y1;
92      }
93  
94      public double getX1() {
95          return (direction == DECREASING) ? x0 : x1;
96      }
97  
98      public double getY1() {
99          return (direction == DECREASING) ? y0 : y1;
100     }
101 
102     public double XforY(double y) {
103         if (x0 == x1 || y <= y0) {
104             return x0;
105         }
106         if (y >= y1) {
107             return x1;
108         }
109         // assert(y0 != y1); /* No horizontal lines... */
110         return (x0 + (y - y0) * (x1 - x0) / (y1 - y0));
111     }
112 
113     public double TforY(double y) {
114         if (y <= y0) {
115             return 0;
116         }
117         if (y >= y1) {
118             return 1;
119         }
120         return (y - y0) / (y1 - y0);
121     }
122 
123     public double XforT(double t) {
124         return x0 + t * (x1 - x0);
125     }
126 
127     public double YforT(double t) {
128         return y0 + t * (y1 - y0);
129     }
130 
131     public double dXforT(double t, int deriv) {
132         switch (deriv) {
133         case 0:
134             return x0 + t * (x1 - x0);
135         case 1:
136             return (x1 - x0);
137         default:
138             return 0;
139         }
140     }
141 
142     public double dYforT(double t, int deriv) {
143         switch (deriv) {
144         case 0:
145             return y0 + t * (y1 - y0);
146         case 1:
147             return (y1 - y0);
148         default:
149             return 0;
150         }
151     }
152 
153     public double nextVertical(double t0, double t1) {
154         return t1;
155     }
156 
157     public boolean accumulateCrossings(Crossings c) {
158         double xlo = c.getXLo();
159         double ylo = c.getYLo();
160         double xhi = c.getXHi();
161         double yhi = c.getYHi();
162         if (xmin >= xhi) {
163             return false;
164         }
165         double xstart, ystart, xend, yend;
166         if (y0 < ylo) {
167             if (y1 <= ylo) {
168                 return false;
169             }
170             ystart = ylo;
171             xstart = XforY(ylo);
172         } else {
173             if (y0 >= yhi) {
174                 return false;
175             }
176             ystart = y0;
177             xstart = x0;
178         }
179         if (y1 > yhi) {
180             yend = yhi;
181             xend = XforY(yhi);
182         } else {
183             yend = y1;
184             xend = x1;
185         }
186         if (xstart >= xhi && xend >= xhi) {
187             return false;
188         }
189         if (xstart > xlo || xend > xlo) {
190             return true;
191         }
192         c.record(ystart, yend, direction);
193         return false;
194     }
195 
196     public void enlarge(Rectangle2D r) {
197         r.add(x0, y0);
198         r.add(x1, y1);
199     }
200 
201     public Curve getSubCurve(double ystart, double yend, int dir) {
202         if (ystart == y0 && yend == y1) {
203             return getWithDirection(dir);
204         }
205         if (x0 == x1) {
206             return new Order1(x0, ystart, x1, yend, dir);
207         }
208         double num = x0 - x1;
209         double denom = y0 - y1;
210         double xstart = (x0 + (ystart - y0) * num / denom);
211         double xend = (x0 + (yend - y0) * num / denom);
212         return new Order1(xstart, ystart, xend, yend, dir);
213     }
214 
215     public Curve getReversedCurve() {
216         return new Order1(x0, y0, x1, y1, -direction);
217     }
218 
219     public int compareTo(Curve other, double yrange[]) {
220         if (!(other instanceof Order1)) {
221             return super.compareTo(other, yrange);
222         }
223         Order1 c1 = (Order1) other;
224         if (yrange[1] <= yrange[0]) {
225             throw new InternalError("yrange already screwed up...");
226         }
227         yrange[1] = Math.min(Math.min(yrange[1], y1), c1.y1);
228         if (yrange[1] <= yrange[0]) {
229             throw new InternalError("backstepping from "+yrange[0]+" to "+yrange[1]);
230         }
231         if (xmax <= c1.xmin) {
232             return (xmin == c1.xmax) ? 0 : -1;
233         }
234         if (xmin >= c1.xmax) {
235             return 1;
236         }
237         /*
238          * If "this" is curve A and "other" is curve B, then...
239          * xA(y) = x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
240          * xB(y) = x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
241          * xA(y) == xB(y)
242          * x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
243          *    == x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
244          * 0 == x0A (y1A - y0A) (y1B - y0B) + (y - y0A) (x1A - x0A) (y1B - y0B)
245          *    - x0B (y1A - y0A) (y1B - y0B) - (y - y0B) (x1B - x0B) (y1A - y0A)
246          * 0 == (x0A - x0B) (y1A - y0A) (y1B - y0B)
247          *    + (y - y0A) (x1A - x0A) (y1B - y0B)
248          *    - (y - y0B) (x1B - x0B) (y1A - y0A)
249          * If (dxA == x1A - x0A), etc...
250          * 0 == (x0A - x0B) * dyA * dyB
251          *    + (y - y0A) * dxA * dyB
252          *    - (y - y0B) * dxB * dyA
253          * 0 == (x0A - x0B) * dyA * dyB
254          *    + y * dxA * dyB - y0A * dxA * dyB
255          *    - y * dxB * dyA + y0B * dxB * dyA
256          * 0 == (x0A - x0B) * dyA * dyB
257          *    + y * dxA * dyB - y * dxB * dyA
258          *    - y0A * dxA * dyB + y0B * dxB * dyA
259          * 0 == (x0A - x0B) * dyA * dyB
260          *    + y * (dxA * dyB - dxB * dyA)
261          *    - y0A * dxA * dyB + y0B * dxB * dyA
262          * y == ((x0A - x0B) * dyA * dyB
263          *       - y0A * dxA * dyB + y0B * dxB * dyA)
264          *    / (-(dxA * dyB - dxB * dyA))
265          * y == ((x0A - x0B) * dyA * dyB
266          *       - y0A * dxA * dyB + y0B * dxB * dyA)
267          *    / (dxB * dyA - dxA * dyB)
268          */
269         double dxa = x1 - x0;
270         double dya = y1 - y0;
271         double dxb = c1.x1 - c1.x0;
272         double dyb = c1.y1 - c1.y0;
273         double denom = dxb * dya - dxa * dyb;
274         double y;
275         if (denom != 0) {
276             double num = ((x0 - c1.x0) * dya * dyb
277                           - y0 * dxa * dyb
278                           + c1.y0 * dxb * dya);
279             y = num / denom;
280             if (y <= yrange[0]) {
281                 // intersection is above us
282                 // Use bottom-most common y for comparison
283                 y = Math.min(y1, c1.y1);
284             } else {
285                 // intersection is below the top of our range
286                 if (y < yrange[1]) {
287                     // If intersection is in our range, adjust valid range
288                     yrange[1] = y;
289                 }
290                 // Use top-most common y for comparison
291                 y = Math.max(y0, c1.y0);
292             }
293         } else {
294             // lines are parallel, choose any common y for comparison
295             // Note - prefer an endpoint for speed of calculating the X
296             // (see shortcuts in Order1.XforY())
297             y = Math.max(y0, c1.y0);
298         }
299         return orderof(XforY(y), c1.XforY(y));
300     }
301 
302     public int getSegment(double coords[]) {
303         if (direction == INCREASING) {
304             coords[0] = x1;
305             coords[1] = y1;
306         } else {
307             coords[0] = x0;
308             coords[1] = y0;
309         }
310         return PathIterator.SEG_LINETO;
311     }
312 }