001: /*
002: * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.geom;
027:
028: import java.awt.geom.Rectangle2D;
029: import java.awt.geom.PathIterator;
030: import java.util.Vector;
031:
032: final class Order1 extends Curve {
033: private double x0;
034: private double y0;
035: private double x1;
036: private double y1;
037: private double xmin;
038: private double xmax;
039:
040: public Order1(double x0, double y0, double x1, double y1,
041: int direction) {
042: super (direction);
043: this .x0 = x0;
044: this .y0 = y0;
045: this .x1 = x1;
046: this .y1 = y1;
047: if (x0 < x1) {
048: this .xmin = x0;
049: this .xmax = x1;
050: } else {
051: this .xmin = x1;
052: this .xmax = x0;
053: }
054: }
055:
056: public int getOrder() {
057: return 1;
058: }
059:
060: public double getXTop() {
061: return x0;
062: }
063:
064: public double getYTop() {
065: return y0;
066: }
067:
068: public double getXBot() {
069: return x1;
070: }
071:
072: public double getYBot() {
073: return y1;
074: }
075:
076: public double getXMin() {
077: return xmin;
078: }
079:
080: public double getXMax() {
081: return xmax;
082: }
083:
084: public double getX0() {
085: return (direction == INCREASING) ? x0 : x1;
086: }
087:
088: public double getY0() {
089: return (direction == INCREASING) ? y0 : y1;
090: }
091:
092: public double getX1() {
093: return (direction == DECREASING) ? x0 : x1;
094: }
095:
096: public double getY1() {
097: return (direction == DECREASING) ? y0 : y1;
098: }
099:
100: public double XforY(double y) {
101: if (x0 == x1 || y <= y0) {
102: return x0;
103: }
104: if (y >= y1) {
105: return x1;
106: }
107: // assert(y0 != y1); /* No horizontal lines... */
108: return (x0 + (y - y0) * (x1 - x0) / (y1 - y0));
109: }
110:
111: public double TforY(double y) {
112: if (y <= y0) {
113: return 0;
114: }
115: if (y >= y1) {
116: return 1;
117: }
118: return (y - y0) / (y1 - y0);
119: }
120:
121: public double XforT(double t) {
122: return x0 + t * (x1 - x0);
123: }
124:
125: public double YforT(double t) {
126: return y0 + t * (y1 - y0);
127: }
128:
129: public double dXforT(double t, int deriv) {
130: switch (deriv) {
131: case 0:
132: return x0 + t * (x1 - x0);
133: case 1:
134: return (x1 - x0);
135: default:
136: return 0;
137: }
138: }
139:
140: public double dYforT(double t, int deriv) {
141: switch (deriv) {
142: case 0:
143: return y0 + t * (y1 - y0);
144: case 1:
145: return (y1 - y0);
146: default:
147: return 0;
148: }
149: }
150:
151: public double nextVertical(double t0, double t1) {
152: return t1;
153: }
154:
155: public boolean accumulateCrossings(Crossings c) {
156: double xlo = c.getXLo();
157: double ylo = c.getYLo();
158: double xhi = c.getXHi();
159: double yhi = c.getYHi();
160: if (xmin >= xhi) {
161: return false;
162: }
163: double xstart, ystart, xend, yend;
164: if (y0 < ylo) {
165: if (y1 <= ylo) {
166: return false;
167: }
168: ystart = ylo;
169: xstart = XforY(ylo);
170: } else {
171: if (y0 >= yhi) {
172: return false;
173: }
174: ystart = y0;
175: xstart = x0;
176: }
177: if (y1 > yhi) {
178: yend = yhi;
179: xend = XforY(yhi);
180: } else {
181: yend = y1;
182: xend = x1;
183: }
184: if (xstart >= xhi && xend >= xhi) {
185: return false;
186: }
187: if (xstart > xlo || xend > xlo) {
188: return true;
189: }
190: c.record(ystart, yend, direction);
191: return false;
192: }
193:
194: public void enlarge(Rectangle2D r) {
195: r.add(x0, y0);
196: r.add(x1, y1);
197: }
198:
199: public Curve getSubCurve(double ystart, double yend, int dir) {
200: if (ystart == y0 && yend == y1) {
201: return getWithDirection(dir);
202: }
203: if (x0 == x1) {
204: return new Order1(x0, ystart, x1, yend, dir);
205: }
206: double num = x0 - x1;
207: double denom = y0 - y1;
208: double xstart = (x0 + (ystart - y0) * num / denom);
209: double xend = (x0 + (yend - y0) * num / denom);
210: return new Order1(xstart, ystart, xend, yend, dir);
211: }
212:
213: public Curve getReversedCurve() {
214: return new Order1(x0, y0, x1, y1, -direction);
215: }
216:
217: public int compareTo(Curve other, double yrange[]) {
218: if (!(other instanceof Order1)) {
219: return super .compareTo(other, yrange);
220: }
221: Order1 c1 = (Order1) other;
222: if (yrange[1] <= yrange[0]) {
223: throw new InternalError("yrange already screwed up...");
224: }
225: yrange[1] = Math.min(Math.min(yrange[1], y1), c1.y1);
226: if (yrange[1] <= yrange[0]) {
227: throw new InternalError("backstepping from " + yrange[0]
228: + " to " + yrange[1]);
229: }
230: if (xmax <= c1.xmin) {
231: return (xmin == c1.xmax) ? 0 : -1;
232: }
233: if (xmin >= c1.xmax) {
234: return 1;
235: }
236: /*
237: * If "this" is curve A and "other" is curve B, then...
238: * xA(y) = x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
239: * xB(y) = x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
240: * xA(y) == xB(y)
241: * x0A + (y - y0A) (x1A - x0A) / (y1A - y0A)
242: * == x0B + (y - y0B) (x1B - x0B) / (y1B - y0B)
243: * 0 == x0A (y1A - y0A) (y1B - y0B) + (y - y0A) (x1A - x0A) (y1B - y0B)
244: * - x0B (y1A - y0A) (y1B - y0B) - (y - y0B) (x1B - x0B) (y1A - y0A)
245: * 0 == (x0A - x0B) (y1A - y0A) (y1B - y0B)
246: * + (y - y0A) (x1A - x0A) (y1B - y0B)
247: * - (y - y0B) (x1B - x0B) (y1A - y0A)
248: * If (dxA == x1A - x0A), etc...
249: * 0 == (x0A - x0B) * dyA * dyB
250: * + (y - y0A) * dxA * dyB
251: * - (y - y0B) * dxB * dyA
252: * 0 == (x0A - x0B) * dyA * dyB
253: * + y * dxA * dyB - y0A * dxA * dyB
254: * - y * dxB * dyA + y0B * dxB * dyA
255: * 0 == (x0A - x0B) * dyA * dyB
256: * + y * dxA * dyB - y * dxB * dyA
257: * - y0A * dxA * dyB + y0B * dxB * dyA
258: * 0 == (x0A - x0B) * dyA * dyB
259: * + y * (dxA * dyB - dxB * dyA)
260: * - y0A * dxA * dyB + y0B * dxB * dyA
261: * y == ((x0A - x0B) * dyA * dyB
262: * - y0A * dxA * dyB + y0B * dxB * dyA)
263: * / (-(dxA * dyB - dxB * dyA))
264: * y == ((x0A - x0B) * dyA * dyB
265: * - y0A * dxA * dyB + y0B * dxB * dyA)
266: * / (dxB * dyA - dxA * dyB)
267: */
268: double dxa = x1 - x0;
269: double dya = y1 - y0;
270: double dxb = c1.x1 - c1.x0;
271: double dyb = c1.y1 - c1.y0;
272: double denom = dxb * dya - dxa * dyb;
273: double y;
274: if (denom != 0) {
275: double num = ((x0 - c1.x0) * dya * dyb - y0 * dxa * dyb + c1.y0
276: * dxb * dya);
277: y = num / denom;
278: if (y <= yrange[0]) {
279: // intersection is above us
280: // Use bottom-most common y for comparison
281: y = Math.min(y1, c1.y1);
282: } else {
283: // intersection is below the top of our range
284: if (y < yrange[1]) {
285: // If intersection is in our range, adjust valid range
286: yrange[1] = y;
287: }
288: // Use top-most common y for comparison
289: y = Math.max(y0, c1.y0);
290: }
291: } else {
292: // lines are parallel, choose any common y for comparison
293: // Note - prefer an endpoint for speed of calculating the X
294: // (see shortcuts in Order1.XforY())
295: y = Math.max(y0, c1.y0);
296: }
297: return orderof(XforY(y), c1.XforY(y));
298: }
299:
300: public int getSegment(double coords[]) {
301: if (direction == INCREASING) {
302: coords[0] = x1;
303: coords[1] = y1;
304: } else {
305: coords[0] = x0;
306: coords[1] = y0;
307: }
308: return PathIterator.SEG_LINETO;
309: }
310: }
|