/* * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt.geom; import java.awt.geom.Rectangle2D; import java.awt.geom.PathIterator; import java.util.Vector; final class Order1 extends Curve { private double x0; private double y0; private double x1; private double y1; private double xmin; private double xmax; public Order1(double x0, double y0, double x1, double y1, int direction) { super(direction); this.x0 = x0; this.y0 = y0; this.x1 = x1; this.y1 = y1; if (x0 < x1) { this.xmin = x0; this.xmax = x1; } else { this.xmin = x1; this.xmax = x0; } } public int getOrder() { return 1; } public double getXTop() { return x0; } public double getYTop() { return y0; } public double getXBot() { return x1; } public double getYBot() { return y1; } public double getXMin() { return xmin; } public double getXMax() { return xmax; } public double getX0() { return (direction == INCREASING) ? x0 : x1; } public double getY0() { return (direction == INCREASING) ? y0 : y1; } public double getX1() { return (direction == DECREASING) ? x0 : x1; } public double getY1() { return (direction == DECREASING) ? y0 : y1; } public double XforY(double y) { if (x0 == x1 || y <= y0) { return x0; } if (y >= y1) { return x1; } // assert(y0 != y1); /* No horizontal lines... */ return (x0 + (y - y0) * (x1 - x0) / (y1 - y0)); } public double TforY(double y) { if (y <= y0) { return 0; } if (y >= y1) { return 1; } return (y - y0) / (y1 - y0); } public double XforT(double t) { return x0 + t * (x1 - x0); } public double YforT(double t) { return y0 + t * (y1 - y0); } public double dXforT(double t, int deriv) { switch (deriv) { case 0: return x0 + t * (x1 - x0); case 1: return (x1 - x0); default: return 0; } } public double dYforT(double t, int deriv) { switch (deriv) { case 0: return y0 + t * (y1 - y0); case 1: return (y1 - y0); default: return 0; } } public double nextVertical(double t0, double t1) { return t1; } public boolean accumulateCrossings(Crossings c) { double xlo = c.getXLo(); double ylo = c.getYLo(); double xhi = c.getXHi(); double yhi = c.getYHi(); if (xmin >= xhi) { return false; } double xstart, ystart, xend, yend; if (y0 < ylo) { if (y1 <= ylo) { return false; } ystart = ylo; xstart = XforY(ylo); } else { if (y0 >= yhi) { return false; } ystart = y0; xstart = x0; } if (y1 > yhi) { yend = yhi; xend = XforY(yhi); } else { yend = y1; xend = x1; } if (xstart >= xhi && xend >= xhi) { return false; } if (xstart > xlo || xend > xlo) { return true; } c.record(ystart, yend, direction); return false; } public void enlarge(Rectangle2D r) { r.add(x0, y0); r.add(x1, y1); } public Curve getSubCurve(double ystart, double yend, int dir) { if (ystart == y0 && yend == y1) { return getWithDirection(dir); } if (x0 == x1) { return new Order1(x0, ystart, x1, yend, dir); } double num = x0 - x1; double denom = y0 - y1; double xstart = (x0 + (ystart - y0) * num / denom); double xend = (x0 + (yend - y0) * num / denom); return new Order1(xstart, ystart, xend, yend, dir); } public Curve getReversedCurve() { return new Order1(x0, y0, x1, y1, -direction); } public int compareTo(Curve other, double[] yrange) { if (!(other instanceof Order1)) { return super.compareTo(other, yrange); } Order1 c1 = (Order1) other; if (yrange[1] <= yrange[0]) { throw new InternalError("yrange already screwed up..."); } yrange[1] = Math.min(Math.min(yrange[1], y1), c1.y1); if (yrange[1] <= yrange[0]) { throw new InternalError("backstepping from "+yrange[0]+" to "+yrange[1]); } if (xmax <= c1.xmin) { return (xmin == c1.xmax) ? 0 : -1; } if (xmin >= c1.xmax) { return 1; } /* * If "this" is curve A and "other" is curve B, then... * xA(y) = x0A + (y - y0A) (x1A - x0A) / (y1A - y0A) * xB(y) = x0B + (y - y0B) (x1B - x0B) / (y1B - y0B) * xA(y) == xB(y) * x0A + (y - y0A) (x1A - x0A) / (y1A - y0A) * == x0B + (y - y0B) (x1B - x0B) / (y1B - y0B) * 0 == x0A (y1A - y0A) (y1B - y0B) + (y - y0A) (x1A - x0A) (y1B - y0B) * - x0B (y1A - y0A) (y1B - y0B) - (y - y0B) (x1B - x0B) (y1A - y0A) * 0 == (x0A - x0B) (y1A - y0A) (y1B - y0B) * + (y - y0A) (x1A - x0A) (y1B - y0B) * - (y - y0B) (x1B - x0B) (y1A - y0A) * If (dxA == x1A - x0A), etc... * 0 == (x0A - x0B) * dyA * dyB * + (y - y0A) * dxA * dyB * - (y - y0B) * dxB * dyA * 0 == (x0A - x0B) * dyA * dyB * + y * dxA * dyB - y0A * dxA * dyB * - y * dxB * dyA + y0B * dxB * dyA * 0 == (x0A - x0B) * dyA * dyB * + y * dxA * dyB - y * dxB * dyA * - y0A * dxA * dyB + y0B * dxB * dyA * 0 == (x0A - x0B) * dyA * dyB * + y * (dxA * dyB - dxB * dyA) * - y0A * dxA * dyB + y0B * dxB * dyA * y == ((x0A - x0B) * dyA * dyB * - y0A * dxA * dyB + y0B * dxB * dyA) * / (-(dxA * dyB - dxB * dyA)) * y == ((x0A - x0B) * dyA * dyB * - y0A * dxA * dyB + y0B * dxB * dyA) * / (dxB * dyA - dxA * dyB) */ double dxa = x1 - x0; double dya = y1 - y0; double dxb = c1.x1 - c1.x0; double dyb = c1.y1 - c1.y0; double denom = dxb * dya - dxa * dyb; double y; if (denom != 0) { double num = ((x0 - c1.x0) * dya * dyb - y0 * dxa * dyb + c1.y0 * dxb * dya); y = num / denom; if (y <= yrange[0]) { // intersection is above us // Use bottom-most common y for comparison y = Math.min(y1, c1.y1); } else { // intersection is below the top of our range if (y < yrange[1]) { // If intersection is in our range, adjust valid range yrange[1] = y; } // Use top-most common y for comparison y = Math.max(y0, c1.y0); } } else { // lines are parallel, choose any common y for comparison // Note - prefer an endpoint for speed of calculating the X // (see shortcuts in Order1.XforY()) y = Math.max(y0, c1.y0); } return orderof(XforY(y), c1.XforY(y)); } public int getSegment(double[] coords) { if (direction == INCREASING) { coords[0] = x1; coords[1] = y1; } else { coords[0] = x0; coords[1] = y0; } return PathIterator.SEG_LINETO; } }