< prev index next >

src/java.desktop/share/classes/sun/awt/geom/Order3.java

Print this page


   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


  36     private double cx0;
  37     private double cy0;
  38     private double cx1;
  39     private double cy1;
  40     private double x1;
  41     private double y1;
  42 
  43     private double xmin;
  44     private double xmax;
  45 
  46     private double xcoeff0;
  47     private double xcoeff1;
  48     private double xcoeff2;
  49     private double xcoeff3;
  50 
  51     private double ycoeff0;
  52     private double ycoeff1;
  53     private double ycoeff2;
  54     private double ycoeff3;
  55 
  56     public static void insert(Vector<Curve> curves, double tmp[],
  57                               double x0, double y0,
  58                               double cx0, double cy0,
  59                               double cx1, double cy1,
  60                               double x1, double y1,
  61                               int direction)
  62     {
  63         int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
  64         if (numparams == 0) {
  65             // We are using addInstance here to avoid inserting horisontal
  66             // segments
  67             addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
  68             return;
  69         }
  70         // Store coordinates for splitting at tmp[3..10]
  71         tmp[3] = x0;  tmp[4]  = y0;
  72         tmp[5] = cx0; tmp[6]  = cy0;
  73         tmp[7] = cx1; tmp[8]  = cy1;
  74         tmp[9] = x1;  tmp[10] = y1;
  75         double t = tmp[0];
  76         if (numparams > 1 && t > tmp[1]) {


 143      *          + (3*CP0 - 3*C0)
 144      *        0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
 145      *          + 3*2*(CP1 - 2*CP0 + C0)t
 146      *          + 3*(CP0 - C0)
 147      *        0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
 148      *          + 2*(CP1 - CP0 - CP0 + C0)t
 149      *          + (CP0 - C0)
 150      *        0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
 151      *          + 2*(CP1 - CP0 - CP0 + C0)t
 152      *          + (CP0 - C0)
 153      *        0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
 154      *          + 2*((CP1 - CP0) - (CP0 - C0))t
 155      *          + (CP0 - C0)
 156      * Note that this method will return 0 if the equation is a line,
 157      * which is either always horizontal or never horizontal.
 158      * Completely horizontal curves need to be eliminated by other
 159      * means outside of this method.
 160      */
 161     public static int getHorizontalParams(double c0, double cp0,
 162                                           double cp1, double c1,
 163                                           double ret[]) {
 164         if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
 165             return 0;
 166         }
 167         c1 -= cp1;
 168         cp1 -= cp0;
 169         cp0 -= c0;
 170         ret[0] = cp0;
 171         ret[1] = (cp1 - cp0) * 2;
 172         ret[2] = (c1 - cp1 - cp1 + cp0);
 173         int numroots = QuadCurve2D.solveQuadratic(ret, ret);
 174         int j = 0;
 175         for (int i = 0; i < numroots; i++) {
 176             double t = ret[i];
 177             // No splits at t==0 and t==1
 178             if (t > 0 && t < 1) {
 179                 if (j < i) {
 180                     ret[j] = t;
 181                 }
 182                 j++;
 183             }
 184         }
 185         return j;
 186     }
 187 
 188     /*
 189      * Split the cubic Bezier stored at coords[pos...pos+7] representing
 190      * the parametric range [0..1] into two subcurves representing the
 191      * parametric subranges [0..t] and [t..1].  Store the results back
 192      * into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
 193      */
 194     public static void split(double coords[], int pos, double t) {
 195         double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
 196         coords[pos+12] = x1 = coords[pos+6];
 197         coords[pos+13] = y1 = coords[pos+7];
 198         cx1 = coords[pos+4];
 199         cy1 = coords[pos+5];
 200         x1 = cx1 + (x1 - cx1) * t;
 201         y1 = cy1 + (y1 - cy1) * t;
 202         x0 = coords[pos+0];
 203         y0 = coords[pos+1];
 204         cx0 = coords[pos+2];
 205         cy0 = coords[pos+3];
 206         x0 = x0 + (cx0 - x0) * t;
 207         y0 = y0 + (cy0 - y0) * t;
 208         cx0 = cx0 + (cx1 - cx0) * t;
 209         cy0 = cy0 + (cy1 - cy0) * t;
 210         cx1 = cx0 + (x1 - cx0) * t;
 211         cy1 = cy0 + (y1 - cy0) * t;
 212         cx0 = x0 + (cx0 - x0) * t;
 213         cy0 = y0 + (cy0 - y0) * t;
 214         coords[pos+2] = x0;


 512             return 0;
 513         }
 514     }
 515 
 516     public double dYforT(double t, int deriv) {
 517         switch (deriv) {
 518         case 0:
 519             return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
 520         case 1:
 521             return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;
 522         case 2:
 523             return (6 * ycoeff3 * t) + 2 * ycoeff2;
 524         case 3:
 525             return 6 * ycoeff3;
 526         default:
 527             return 0;
 528         }
 529     }
 530 
 531     public double nextVertical(double t0, double t1) {
 532         double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
 533         int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
 534         for (int i = 0; i < numroots; i++) {
 535             if (eqn[i] > t0 && eqn[i] < t1) {
 536                 t1 = eqn[i];
 537             }
 538         }
 539         return t1;
 540     }
 541 
 542     public void enlarge(Rectangle2D r) {
 543         r.add(x0, y0);
 544         double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
 545         int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
 546         for (int i = 0; i < numroots; i++) {
 547             double t = eqn[i];
 548             if (t > 0 && t < 1) {
 549                 r.add(XforT(t), YforT(t));
 550             }
 551         }
 552         r.add(x1, y1);
 553     }
 554 
 555     public Curve getSubCurve(double ystart, double yend, int dir) {
 556         if (ystart <= y0 && yend >= y1) {
 557             return getWithDirection(dir);
 558         }
 559         double eqn[] = new double[14];
 560         double t0, t1;
 561         t0 = TforY(ystart);
 562         t1 = TforY(yend);
 563         eqn[0] = x0;
 564         eqn[1] = y0;
 565         eqn[2] = cx0;
 566         eqn[3] = cy0;
 567         eqn[4] = cx1;
 568         eqn[5] = cy1;
 569         eqn[6] = x1;
 570         eqn[7] = y1;
 571         if (t0 > t1) {
 572             /* This happens in only rare cases where ystart is
 573              * very near yend and solving for the yend root ends
 574              * up stepping slightly lower in t than solving for
 575              * the ystart root.
 576              * Ideally we might want to skip this tiny little
 577              * segment and just fudge the surrounding coordinates
 578              * to bridge the gap left behind, but there is no way
 579              * to do that from here.  Higher levels could


 591             split(eqn, 0, t1);
 592         }
 593         int i;
 594         if (t0 <= 0) {
 595             i = 0;
 596         } else {
 597             split(eqn, 0, t0 / t1);
 598             i = 6;
 599         }
 600         return new Order3(eqn[i+0], ystart,
 601                           eqn[i+2], eqn[i+3],
 602                           eqn[i+4], eqn[i+5],
 603                           eqn[i+6], yend,
 604                           dir);
 605     }
 606 
 607     public Curve getReversedCurve() {
 608         return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);
 609     }
 610 
 611     public int getSegment(double coords[]) {
 612         if (direction == INCREASING) {
 613             coords[0] = cx0;
 614             coords[1] = cy0;
 615             coords[2] = cx1;
 616             coords[3] = cy1;
 617             coords[4] = x1;
 618             coords[5] = y1;
 619         } else {
 620             coords[0] = cx1;
 621             coords[1] = cy1;
 622             coords[2] = cx0;
 623             coords[3] = cy0;
 624             coords[4] = x0;
 625             coords[5] = y0;
 626         }
 627         return PathIterator.SEG_CUBICTO;
 628     }
 629 
 630     public String controlPointString() {
 631         return (("("+round(getCX0())+", "+round(getCY0())+"), ")+
   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


  36     private double cx0;
  37     private double cy0;
  38     private double cx1;
  39     private double cy1;
  40     private double x1;
  41     private double y1;
  42 
  43     private double xmin;
  44     private double xmax;
  45 
  46     private double xcoeff0;
  47     private double xcoeff1;
  48     private double xcoeff2;
  49     private double xcoeff3;
  50 
  51     private double ycoeff0;
  52     private double ycoeff1;
  53     private double ycoeff2;
  54     private double ycoeff3;
  55 
  56     public static void insert(Vector<Curve> curves, double[] tmp,
  57                               double x0, double y0,
  58                               double cx0, double cy0,
  59                               double cx1, double cy1,
  60                               double x1, double y1,
  61                               int direction)
  62     {
  63         int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);
  64         if (numparams == 0) {
  65             // We are using addInstance here to avoid inserting horisontal
  66             // segments
  67             addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);
  68             return;
  69         }
  70         // Store coordinates for splitting at tmp[3..10]
  71         tmp[3] = x0;  tmp[4]  = y0;
  72         tmp[5] = cx0; tmp[6]  = cy0;
  73         tmp[7] = cx1; tmp[8]  = cy1;
  74         tmp[9] = x1;  tmp[10] = y1;
  75         double t = tmp[0];
  76         if (numparams > 1 && t > tmp[1]) {


 143      *          + (3*CP0 - 3*C0)
 144      *        0 = 3*(C1 - 3*CP1 + 3*CP0 - C0)t^2
 145      *          + 3*2*(CP1 - 2*CP0 + C0)t
 146      *          + 3*(CP0 - C0)
 147      *        0 = (C1 - CP1 - CP1 - CP1 + CP0 + CP0 + CP0 - C0)t^2
 148      *          + 2*(CP1 - CP0 - CP0 + C0)t
 149      *          + (CP0 - C0)
 150      *        0 = (C1 - CP1 + CP0 - CP1 + CP0 - CP1 + CP0 - C0)t^2
 151      *          + 2*(CP1 - CP0 - CP0 + C0)t
 152      *          + (CP0 - C0)
 153      *        0 = ((C1 - CP1) - (CP1 - CP0) - (CP1 - CP0) + (CP0 - C0))t^2
 154      *          + 2*((CP1 - CP0) - (CP0 - C0))t
 155      *          + (CP0 - C0)
 156      * Note that this method will return 0 if the equation is a line,
 157      * which is either always horizontal or never horizontal.
 158      * Completely horizontal curves need to be eliminated by other
 159      * means outside of this method.
 160      */
 161     public static int getHorizontalParams(double c0, double cp0,
 162                                           double cp1, double c1,
 163                                           double[] ret) {
 164         if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) {
 165             return 0;
 166         }
 167         c1 -= cp1;
 168         cp1 -= cp0;
 169         cp0 -= c0;
 170         ret[0] = cp0;
 171         ret[1] = (cp1 - cp0) * 2;
 172         ret[2] = (c1 - cp1 - cp1 + cp0);
 173         int numroots = QuadCurve2D.solveQuadratic(ret, ret);
 174         int j = 0;
 175         for (int i = 0; i < numroots; i++) {
 176             double t = ret[i];
 177             // No splits at t==0 and t==1
 178             if (t > 0 && t < 1) {
 179                 if (j < i) {
 180                     ret[j] = t;
 181                 }
 182                 j++;
 183             }
 184         }
 185         return j;
 186     }
 187 
 188     /*
 189      * Split the cubic Bezier stored at coords[pos...pos+7] representing
 190      * the parametric range [0..1] into two subcurves representing the
 191      * parametric subranges [0..t] and [t..1].  Store the results back
 192      * into the array at coords[pos...pos+7] and coords[pos+6...pos+13].
 193      */
 194     public static void split(double[] coords, int pos, double t) {
 195         double x0, y0, cx0, cy0, cx1, cy1, x1, y1;
 196         coords[pos+12] = x1 = coords[pos+6];
 197         coords[pos+13] = y1 = coords[pos+7];
 198         cx1 = coords[pos+4];
 199         cy1 = coords[pos+5];
 200         x1 = cx1 + (x1 - cx1) * t;
 201         y1 = cy1 + (y1 - cy1) * t;
 202         x0 = coords[pos+0];
 203         y0 = coords[pos+1];
 204         cx0 = coords[pos+2];
 205         cy0 = coords[pos+3];
 206         x0 = x0 + (cx0 - x0) * t;
 207         y0 = y0 + (cy0 - y0) * t;
 208         cx0 = cx0 + (cx1 - cx0) * t;
 209         cy0 = cy0 + (cy1 - cy0) * t;
 210         cx1 = cx0 + (x1 - cx0) * t;
 211         cy1 = cy0 + (y1 - cy0) * t;
 212         cx0 = x0 + (cx0 - x0) * t;
 213         cy0 = y0 + (cy0 - y0) * t;
 214         coords[pos+2] = x0;


 512             return 0;
 513         }
 514     }
 515 
 516     public double dYforT(double t, int deriv) {
 517         switch (deriv) {
 518         case 0:
 519             return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;
 520         case 1:
 521             return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;
 522         case 2:
 523             return (6 * ycoeff3 * t) + 2 * ycoeff2;
 524         case 3:
 525             return 6 * ycoeff3;
 526         default:
 527             return 0;
 528         }
 529     }
 530 
 531     public double nextVertical(double t0, double t1) {
 532         double[] eqn = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
 533         int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
 534         for (int i = 0; i < numroots; i++) {
 535             if (eqn[i] > t0 && eqn[i] < t1) {
 536                 t1 = eqn[i];
 537             }
 538         }
 539         return t1;
 540     }
 541 
 542     public void enlarge(Rectangle2D r) {
 543         r.add(x0, y0);
 544         double[] eqn = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3};
 545         int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);
 546         for (int i = 0; i < numroots; i++) {
 547             double t = eqn[i];
 548             if (t > 0 && t < 1) {
 549                 r.add(XforT(t), YforT(t));
 550             }
 551         }
 552         r.add(x1, y1);
 553     }
 554 
 555     public Curve getSubCurve(double ystart, double yend, int dir) {
 556         if (ystart <= y0 && yend >= y1) {
 557             return getWithDirection(dir);
 558         }
 559         double[] eqn = new double[14];
 560         double t0, t1;
 561         t0 = TforY(ystart);
 562         t1 = TforY(yend);
 563         eqn[0] = x0;
 564         eqn[1] = y0;
 565         eqn[2] = cx0;
 566         eqn[3] = cy0;
 567         eqn[4] = cx1;
 568         eqn[5] = cy1;
 569         eqn[6] = x1;
 570         eqn[7] = y1;
 571         if (t0 > t1) {
 572             /* This happens in only rare cases where ystart is
 573              * very near yend and solving for the yend root ends
 574              * up stepping slightly lower in t than solving for
 575              * the ystart root.
 576              * Ideally we might want to skip this tiny little
 577              * segment and just fudge the surrounding coordinates
 578              * to bridge the gap left behind, but there is no way
 579              * to do that from here.  Higher levels could


 591             split(eqn, 0, t1);
 592         }
 593         int i;
 594         if (t0 <= 0) {
 595             i = 0;
 596         } else {
 597             split(eqn, 0, t0 / t1);
 598             i = 6;
 599         }
 600         return new Order3(eqn[i+0], ystart,
 601                           eqn[i+2], eqn[i+3],
 602                           eqn[i+4], eqn[i+5],
 603                           eqn[i+6], yend,
 604                           dir);
 605     }
 606 
 607     public Curve getReversedCurve() {
 608         return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);
 609     }
 610 
 611     public int getSegment(double[] coords) {
 612         if (direction == INCREASING) {
 613             coords[0] = cx0;
 614             coords[1] = cy0;
 615             coords[2] = cx1;
 616             coords[3] = cy1;
 617             coords[4] = x1;
 618             coords[5] = y1;
 619         } else {
 620             coords[0] = cx1;
 621             coords[1] = cy1;
 622             coords[2] = cx0;
 623             coords[3] = cy0;
 624             coords[4] = x0;
 625             coords[5] = y0;
 626         }
 627         return PathIterator.SEG_CUBICTO;
 628     }
 629 
 630     public String controlPointString() {
 631         return (("("+round(getCX0())+", "+round(getCY0())+"), ")+
< prev index next >