blob: ddb54b25cee02f8c9acf2ca9cd4a05199f08cb6a [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.awt.geom;
27
28import java.awt.geom.Rectangle2D;
29import java.awt.geom.PathIterator;
30import java.util.Vector;
31
32final 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}