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 }