1 /* 2 * Copyright (c) 1998, 2018, 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 }