Home | History | Annotate | Download | only in gl
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 /**
     18  * @author Denis M. Kishenko
     19  * @version $Revision$
     20  */
     21 package org.apache.harmony.awt.gl;
     22 
     23 import java.awt.Shape;
     24 import java.awt.geom.PathIterator;
     25 
     26 public class Crossing {
     27 
     28     /**
     29      * Allowable tolerance for bounds comparison
     30      */
     31     static final double DELTA = 1E-5;
     32 
     33     /**
     34      * If roots have distance less then <code>ROOT_DELTA</code> they are double
     35      */
     36     static final double ROOT_DELTA = 1E-10;
     37 
     38     /**
     39      * Rectangle cross segment
     40      */
     41     public static final int CROSSING = 255;
     42 
     43     /**
     44      * Unknown crossing result
     45      */
     46     static final int UNKNOWN = 254;
     47 
     48     /**
     49      * Solves quadratic equation
     50      * @param eqn - the coefficients of the equation
     51      * @param res - the roots of the equation
     52      * @return a number of roots
     53      */
     54     public static int solveQuad(double eqn[], double res[]) {
     55         double a = eqn[2];
     56         double b = eqn[1];
     57         double c = eqn[0];
     58         int rc = 0;
     59         if (a == 0.0) {
     60             if (b == 0.0) {
     61                 return -1;
     62             }
     63             res[rc++] = -c / b;
     64         } else {
     65             double d = b * b - 4.0 * a * c;
     66             // d < 0.0
     67             if (d < 0.0) {
     68                 return 0;
     69             }
     70             d = Math.sqrt(d);
     71             res[rc++] = (- b + d) / (a * 2.0);
     72             // d != 0.0
     73             if (d != 0.0) {
     74                 res[rc++] = (- b - d) / (a * 2.0);
     75             }
     76         }
     77         return fixRoots(res, rc);
     78     }
     79 
     80     /**
     81      * Solves cubic equation
     82      * @param eqn - the coefficients of the equation
     83      * @param res - the roots of the equation
     84      * @return a number of roots
     85      */
     86     public static int solveCubic(double eqn[], double res[]) {
     87         double d = eqn[3];
     88         if (d == 0) {
     89             return solveQuad(eqn, res);
     90         }
     91         double a = eqn[2] / d;
     92         double b = eqn[1] / d;
     93         double c = eqn[0] / d;
     94         int rc = 0;
     95 
     96         double Q = (a * a - 3.0 * b) / 9.0;
     97         double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;
     98         double Q3 = Q * Q * Q;
     99         double R2 = R * R;
    100         double n = - a / 3.0;
    101 
    102         if (R2 < Q3) {
    103             double t = Math.acos(R / Math.sqrt(Q3)) / 3.0;
    104             double p = 2.0 * Math.PI / 3.0;
    105             double m = -2.0 * Math.sqrt(Q);
    106             res[rc++] = m * Math.cos(t) + n;
    107             res[rc++] = m * Math.cos(t + p) + n;
    108             res[rc++] = m * Math.cos(t - p) + n;
    109         } else {
    110 //          Debug.println("R2 >= Q3 (" + R2 + "/" + Q3 + ")");
    111             double A = Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0);
    112             if (R > 0.0) {
    113                 A = -A;
    114             }
    115 //          if (A == 0.0) {
    116             if (-ROOT_DELTA < A && A < ROOT_DELTA) {
    117                 res[rc++] = n;
    118             } else {
    119                 double B = Q / A;
    120                 res[rc++] = A + B + n;
    121 //              if (R2 == Q3) {
    122                 double delta = R2 - Q3;
    123                 if (-ROOT_DELTA < delta && delta < ROOT_DELTA) {
    124                     res[rc++] = - (A + B) / 2.0 + n;
    125                 }
    126             }
    127 
    128         }
    129         return fixRoots(res, rc);
    130     }
    131 
    132     /**
    133      * Excludes double roots. Roots are double if they lies enough close with each other.
    134      * @param res - the roots
    135      * @param rc - the roots count
    136      * @return new roots count
    137      */
    138     static int fixRoots(double res[], int rc) {
    139         int tc = 0;
    140         for(int i = 0; i < rc; i++) {
    141             out: {
    142                 for(int j = i + 1; j < rc; j++) {
    143                     if (isZero(res[i] - res[j])) {
    144                         break out;
    145                     }
    146                 }
    147                 res[tc++] = res[i];
    148             }
    149         }
    150         return tc;
    151     }
    152 
    153     /**
    154      * QuadCurve class provides basic functionality to find curve crossing and calculating bounds
    155      */
    156     public static class QuadCurve {
    157 
    158         double ax, ay, bx, by;
    159         double Ax, Ay, Bx, By;
    160 
    161         public QuadCurve(double x1, double y1, double cx, double cy, double x2, double y2) {
    162             ax = x2 - x1;
    163             ay = y2 - y1;
    164             bx = cx - x1;
    165             by = cy - y1;
    166 
    167             Bx = bx + bx;   // Bx = 2.0 * bx
    168             Ax = ax - Bx;   // Ax = ax - 2.0 * bx
    169 
    170             By = by + by;   // By = 2.0 * by
    171             Ay = ay - By;   // Ay = ay - 2.0 * by
    172         }
    173 
    174         int cross(double res[], int rc, double py1, double py2) {
    175             int cross = 0;
    176 
    177             for (int i = 0; i < rc; i++) {
    178                 double t = res[i];
    179 
    180                 // CURVE-OUTSIDE
    181                 if (t < -DELTA || t > 1 + DELTA) {
    182                     continue;
    183                 }
    184                 // CURVE-START
    185                 if (t < DELTA) {
    186                     if (py1 < 0.0 && (bx != 0.0 ? bx : ax - bx) < 0.0) {
    187                         cross--;
    188                     }
    189                     continue;
    190                 }
    191                 // CURVE-END
    192                 if (t > 1 - DELTA) {
    193                     if (py1 < ay && (ax != bx ? ax - bx : bx) > 0.0) {
    194                         cross++;
    195                     }
    196                     continue;
    197                 }
    198                 // CURVE-INSIDE
    199                 double ry = t * (t * Ay + By);
    200                 // ry = t * t * Ay + t * By
    201                 if (ry > py2) {
    202                     double rxt = t * Ax + bx;
    203                     // rxt = 2.0 * t * Ax + Bx = 2.0 * t * Ax + 2.0 * bx
    204                     if (rxt > -DELTA && rxt < DELTA) {
    205                         continue;
    206                     }
    207                     cross += rxt > 0.0 ? 1 : -1;
    208                 }
    209             } // for
    210 
    211             return cross;
    212         }
    213 
    214         int solvePoint(double res[], double px) {
    215             double eqn[] = {-px, Bx, Ax};
    216             return solveQuad(eqn, res);
    217         }
    218 
    219         int solveExtrem(double res[]) {
    220             int rc = 0;
    221             if (Ax != 0.0) {
    222                 res[rc++] = - Bx / (Ax + Ax);
    223             }
    224             if (Ay != 0.0) {
    225                 res[rc++] = - By / (Ay + Ay);
    226             }
    227             return rc;
    228         }
    229 
    230         int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) {
    231             for(int i = 0; i < rc; i++) {
    232                 double t = res[i];
    233                 if (t > -DELTA && t < 1 + DELTA) {
    234                     double rx = t * (t * Ax + Bx);
    235                     if (minX <= rx && rx <= maxX) {
    236                         bound[bc++] = t;
    237                         bound[bc++] = rx;
    238                         bound[bc++] = t * (t * Ay + By);
    239                         bound[bc++] = id;
    240                         if (changeId) {
    241                             id++;
    242                         }
    243                     }
    244                 }
    245             }
    246             return bc;
    247         }
    248 
    249     }
    250 
    251     /**
    252      * CubicCurve class provides basic functionality to find curve crossing and calculating bounds
    253      */
    254     public static class CubicCurve {
    255 
    256         double ax, ay, bx, by, cx, cy;
    257         double Ax, Ay, Bx, By, Cx, Cy;
    258         double Ax3, Bx2;
    259 
    260         public CubicCurve(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2) {
    261             ax = x2 - x1;
    262             ay = y2 - y1;
    263             bx = cx1 - x1;
    264             by = cy1 - y1;
    265             cx = cx2 - x1;
    266             cy = cy2 - y1;
    267 
    268             Cx = bx + bx + bx;           // Cx = 3.0 * bx
    269             Bx = cx + cx + cx - Cx - Cx; // Bx = 3.0 * cx - 6.0 * bx
    270             Ax = ax - Bx - Cx;           // Ax = ax - 3.0 * cx + 3.0 * bx
    271 
    272             Cy = by + by + by;           // Cy = 3.0 * by
    273             By = cy + cy + cy - Cy - Cy; // By = 3.0 * cy - 6.0 * by
    274             Ay = ay - By - Cy;           // Ay = ay - 3.0 * cy + 3.0 * by
    275 
    276             Ax3 = Ax + Ax + Ax;
    277             Bx2 = Bx + Bx;
    278         }
    279 
    280         int cross(double res[], int rc, double py1, double py2) {
    281             int cross = 0;
    282             for (int i = 0; i < rc; i++) {
    283                 double t = res[i];
    284 
    285                 // CURVE-OUTSIDE
    286                 if (t < -DELTA || t > 1 + DELTA) {
    287                     continue;
    288                 }
    289                 // CURVE-START
    290                 if (t < DELTA) {
    291                     if (py1 < 0.0 && (bx != 0.0 ? bx : (cx != bx ? cx - bx : ax - cx)) < 0.0) {
    292                         cross--;
    293                     }
    294                     continue;
    295                 }
    296                 // CURVE-END
    297                 if (t > 1 - DELTA) {
    298                     if (py1 < ay && (ax != cx ? ax - cx : (cx != bx ? cx - bx : bx)) > 0.0) {
    299                         cross++;
    300                     }
    301                     continue;
    302                 }
    303                 // CURVE-INSIDE
    304                 double ry = t * (t * (t * Ay + By) + Cy);
    305                 // ry = t * t * t * Ay + t * t * By + t * Cy
    306                 if (ry > py2) {
    307                     double rxt = t * (t * Ax3 + Bx2) + Cx;
    308                     // rxt = 3.0 * t * t * Ax + 2.0 * t * Bx + Cx
    309                     if (rxt > -DELTA && rxt < DELTA) {
    310                         rxt = t * (Ax3 + Ax3) + Bx2;
    311                         // rxt = 6.0 * t * Ax + 2.0 * Bx
    312                         if (rxt < -DELTA || rxt > DELTA) {
    313                             // Inflection point
    314                             continue;
    315                         }
    316                         rxt = ax;
    317                     }
    318                     cross += rxt > 0.0 ? 1 : -1;
    319                 }
    320             } //for
    321 
    322             return cross;
    323         }
    324 
    325         int solvePoint(double res[], double px) {
    326             double eqn[] = {-px, Cx, Bx, Ax};
    327             return solveCubic(eqn, res);
    328         }
    329 
    330         int solveExtremX(double res[]) {
    331             double eqn[] = {Cx, Bx2, Ax3};
    332             return solveQuad(eqn, res);
    333         }
    334 
    335         int solveExtremY(double res[]) {
    336             double eqn[] = {Cy, By + By, Ay + Ay + Ay};
    337             return solveQuad(eqn, res);
    338         }
    339 
    340         int addBound(double bound[], int bc, double res[], int rc, double minX, double maxX, boolean changeId, int id) {
    341             for(int i = 0; i < rc; i++) {
    342                 double t = res[i];
    343                 if (t > -DELTA && t < 1 + DELTA) {
    344                     double rx = t * (t * (t * Ax + Bx) + Cx);
    345                     if (minX <= rx && rx <= maxX) {
    346                         bound[bc++] = t;
    347                         bound[bc++] = rx;
    348                         bound[bc++] = t * (t * (t * Ay + By) + Cy);
    349                         bound[bc++] = id;
    350                         if (changeId) {
    351                             id++;
    352                         }
    353                     }
    354                 }
    355             }
    356             return bc;
    357         }
    358 
    359     }
    360 
    361     /**
    362      * Returns how many times ray from point (x,y) cross line.
    363      */
    364     public static int crossLine(double x1, double y1, double x2, double y2, double x, double y) {
    365 
    366         // LEFT/RIGHT/UP/EMPTY
    367         if ((x < x1 && x < x2) ||
    368             (x > x1 && x > x2) ||
    369             (y > y1 && y > y2) ||
    370             (x1 == x2))
    371         {
    372             return 0;
    373         }
    374 
    375         // DOWN
    376         if (y < y1 && y < y2) {
    377         } else {
    378             // INSIDE
    379             if ((y2 - y1) * (x - x1) / (x2 - x1) <= y - y1) {
    380                 // INSIDE-UP
    381                 return 0;
    382             }
    383         }
    384 
    385         // START
    386         if (x == x1) {
    387             return x1 < x2 ? 0 : -1;
    388         }
    389 
    390         // END
    391         if (x == x2) {
    392             return x1 < x2 ? 1 : 0;
    393         }
    394 
    395         // INSIDE-DOWN
    396         return x1 < x2 ? 1 : -1;
    397     }
    398 
    399     /**
    400      * Returns how many times ray from point (x,y) cross quard curve
    401      */
    402     public static int crossQuad(double x1, double y1, double cx, double cy, double x2, double y2, double x, double y) {
    403 
    404         // LEFT/RIGHT/UP/EMPTY
    405         if ((x < x1 && x < cx && x < x2) ||
    406             (x > x1 && x > cx && x > x2) ||
    407             (y > y1 && y > cy && y > y2) ||
    408             (x1 == cx && cx == x2))
    409         {
    410             return 0;
    411         }
    412 
    413         // DOWN
    414         if (y < y1 && y < cy && y < y2 && x != x1 && x != x2) {
    415             if (x1 < x2) {
    416                 return x1 < x && x < x2 ? 1 : 0;
    417             }
    418             return x2 < x && x < x1 ? -1 : 0;
    419         }
    420 
    421         // INSIDE
    422         QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
    423         double px = x - x1;
    424         double py = y - y1;
    425         double res[] = new double[3];
    426         int rc = c.solvePoint(res, px);
    427 
    428         return c.cross(res, rc, py, py);
    429     }
    430 
    431     /**
    432      * Returns how many times ray from point (x,y) cross cubic curve
    433      */
    434     public static int crossCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double x, double y) {
    435 
    436         // LEFT/RIGHT/UP/EMPTY
    437         if ((x < x1 && x < cx1 && x < cx2 && x < x2) ||
    438             (x > x1 && x > cx1 && x > cx2 && x > x2) ||
    439             (y > y1 && y > cy1 && y > cy2 && y > y2) ||
    440             (x1 == cx1 && cx1 == cx2 && cx2 == x2))
    441         {
    442             return 0;
    443         }
    444 
    445         // DOWN
    446         if (y < y1 && y < cy1 && y < cy2 && y < y2 && x != x1 && x != x2) {
    447             if (x1 < x2) {
    448                 return x1 < x && x < x2 ? 1 : 0;
    449             }
    450             return x2 < x && x < x1 ? -1 : 0;
    451         }
    452 
    453         // INSIDE
    454         CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
    455         double px = x - x1;
    456         double py = y - y1;
    457         double res[] = new double[3];
    458         int rc = c.solvePoint(res, px);
    459         return c.cross(res, rc, py, py);
    460     }
    461 
    462     /**
    463      * Returns how many times ray from point (x,y) cross path
    464      */
    465     public static int crossPath(PathIterator p, double x, double y) {
    466         int cross = 0;
    467         double mx, my, cx, cy;
    468         mx = my = cx = cy = 0.0;
    469         double coords[] = new double[6];
    470 
    471         while (!p.isDone()) {
    472             switch (p.currentSegment(coords)) {
    473             case PathIterator.SEG_MOVETO:
    474                 if (cx != mx || cy != my) {
    475                     cross += crossLine(cx, cy, mx, my, x, y);
    476                 }
    477                 mx = cx = coords[0];
    478                 my = cy = coords[1];
    479                 break;
    480             case PathIterator.SEG_LINETO:
    481                 cross += crossLine(cx, cy, cx = coords[0], cy = coords[1], x, y);
    482                 break;
    483             case PathIterator.SEG_QUADTO:
    484                 cross += crossQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3], x, y);
    485                 break;
    486             case PathIterator.SEG_CUBICTO:
    487                 cross += crossCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5], x, y);
    488                 break;
    489             case PathIterator.SEG_CLOSE:
    490                 if (cy != my || cx != mx) {
    491                     cross += crossLine(cx, cy, cx = mx, cy = my, x, y);
    492                 }
    493                 break;
    494             }
    495             p.next();
    496         }
    497         if (cy != my) {
    498             cross += crossLine(cx, cy, mx, my, x, y);
    499         }
    500         return cross;
    501     }
    502 
    503     /**
    504      * Returns how many times ray from point (x,y) cross shape
    505      */
    506     public static int crossShape(Shape s, double x, double y) {
    507         if (!s.getBounds2D().contains(x, y)) {
    508             return 0;
    509         }
    510         return crossPath(s.getPathIterator(null), x, y);
    511     }
    512 
    513     /**
    514      * Returns true if value enough small
    515      */
    516     public static boolean isZero(double val) {
    517         return -DELTA < val && val < DELTA;
    518     }
    519 
    520     /**
    521      * Sort bound array
    522      */
    523     static void sortBound(double bound[], int bc) {
    524         for(int i = 0; i < bc - 4; i += 4) {
    525             int k = i;
    526             for(int j = i + 4; j < bc; j += 4) {
    527                 if (bound[k] > bound[j]) {
    528                     k = j;
    529                 }
    530             }
    531             if (k != i) {
    532                 double tmp = bound[i];
    533                 bound[i] = bound[k];
    534                 bound[k] = tmp;
    535                 tmp = bound[i + 1];
    536                 bound[i + 1] = bound[k + 1];
    537                 bound[k + 1] = tmp;
    538                 tmp = bound[i + 2];
    539                 bound[i + 2] = bound[k + 2];
    540                 bound[k + 2] = tmp;
    541                 tmp = bound[i + 3];
    542                 bound[i + 3] = bound[k + 3];
    543                 bound[k + 3] = tmp;
    544             }
    545         }
    546     }
    547 
    548     /**
    549      * Returns are bounds intersect or not intersect rectangle
    550      */
    551     static int crossBound(double bound[], int bc, double py1, double py2) {
    552 
    553         // LEFT/RIGHT
    554         if (bc == 0) {
    555             return 0;
    556         }
    557 
    558         // Check Y coordinate
    559         int up = 0;
    560         int down = 0;
    561         for(int i = 2; i < bc; i += 4) {
    562             if (bound[i] < py1) {
    563                 up++;
    564                 continue;
    565             }
    566             if (bound[i] > py2) {
    567                 down++;
    568                 continue;
    569             }
    570             return CROSSING;
    571         }
    572 
    573         // UP
    574         if (down == 0) {
    575             return 0;
    576         }
    577 
    578         if (up != 0) {
    579             // bc >= 2
    580             sortBound(bound, bc);
    581             boolean sign = bound[2] > py2;
    582             for(int i = 6; i < bc; i += 4) {
    583                 boolean sign2 = bound[i] > py2;
    584                 if (sign != sign2 && bound[i + 1] != bound[i - 3]) {
    585                     return CROSSING;
    586                 }
    587                 sign = sign2;
    588             }
    589         }
    590         return UNKNOWN;
    591     }
    592 
    593     /**
    594      * Returns how many times rectangle stripe cross line or the are intersect
    595      */
    596     public static int intersectLine(double x1, double y1, double x2, double y2, double rx1, double ry1, double rx2, double ry2) {
    597 
    598         // LEFT/RIGHT/UP
    599         if ((rx2 < x1 && rx2 < x2) ||
    600             (rx1 > x1 && rx1 > x2) ||
    601             (ry1 > y1 && ry1 > y2))
    602         {
    603             return 0;
    604         }
    605 
    606         // DOWN
    607         if (ry2 < y1 && ry2 < y2) {
    608         } else {
    609 
    610             // INSIDE
    611             if (x1 == x2) {
    612                 return CROSSING;
    613             }
    614 
    615             // Build bound
    616             double bx1, bx2;
    617             if (x1 < x2) {
    618                 bx1 = x1 < rx1 ? rx1 : x1;
    619                 bx2 = x2 < rx2 ? x2 : rx2;
    620             } else {
    621                 bx1 = x2 < rx1 ? rx1 : x2;
    622                 bx2 = x1 < rx2 ? x1 : rx2;
    623             }
    624             double k = (y2 - y1) / (x2 - x1);
    625             double by1 = k * (bx1 - x1) + y1;
    626             double by2 = k * (bx2 - x1) + y1;
    627 
    628             // BOUND-UP
    629             if (by1 < ry1 && by2 < ry1) {
    630                 return 0;
    631             }
    632 
    633             // BOUND-DOWN
    634             if (by1 > ry2 && by2 > ry2) {
    635             } else {
    636                 return CROSSING;
    637             }
    638         }
    639 
    640         // EMPTY
    641         if (x1 == x2) {
    642             return 0;
    643         }
    644 
    645         // CURVE-START
    646         if (rx1 == x1) {
    647             return x1 < x2 ? 0 : -1;
    648         }
    649 
    650         // CURVE-END
    651         if (rx1 == x2) {
    652             return x1 < x2 ? 1 : 0;
    653         }
    654 
    655         if (x1 < x2) {
    656             return x1 < rx1 && rx1 < x2 ? 1 : 0;
    657         }
    658         return x2 < rx1 && rx1 < x1 ? -1 : 0;
    659 
    660     }
    661 
    662     /**
    663      * Returns how many times rectangle stripe cross quad curve or the are intersect
    664      */
    665     public static int intersectQuad(double x1, double y1, double cx, double cy, double x2, double y2, double rx1, double ry1, double rx2, double ry2) {
    666 
    667         // LEFT/RIGHT/UP ------------------------------------------------------
    668         if ((rx2 < x1 && rx2 < cx && rx2 < x2) ||
    669             (rx1 > x1 && rx1 > cx && rx1 > x2) ||
    670             (ry1 > y1 && ry1 > cy && ry1 > y2))
    671         {
    672             return 0;
    673         }
    674 
    675         // DOWN ---------------------------------------------------------------
    676         if (ry2 < y1 && ry2 < cy && ry2 < y2 && rx1 != x1 && rx1 != x2) {
    677             if (x1 < x2) {
    678                 return x1 < rx1 && rx1 < x2 ? 1 : 0;
    679             }
    680             return x2 < rx1 && rx1 < x1 ? -1 : 0;
    681         }
    682 
    683         // INSIDE -------------------------------------------------------------
    684         QuadCurve c = new QuadCurve(x1, y1, cx, cy, x2, y2);
    685         double px1 = rx1 - x1;
    686         double py1 = ry1 - y1;
    687         double px2 = rx2 - x1;
    688         double py2 = ry2 - y1;
    689 
    690         double res1[] = new double[3];
    691         double res2[] = new double[3];
    692         int rc1 = c.solvePoint(res1, px1);
    693         int rc2 = c.solvePoint(res2, px2);
    694 
    695         // INSIDE-LEFT/RIGHT
    696         if (rc1 == 0 && rc2 == 0) {
    697             return 0;
    698         }
    699 
    700         // Build bound --------------------------------------------------------
    701         double minX = px1 - DELTA;
    702         double maxX = px2 + DELTA;
    703         double bound[] = new double[28];
    704         int bc = 0;
    705         // Add roots
    706         bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
    707         bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1);
    708         // Add extremal points`
    709         rc2 = c.solveExtrem(res2);
    710         bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2);
    711         // Add start and end
    712         if (rx1 < x1 && x1 < rx2) {
    713             bound[bc++] = 0.0;
    714             bound[bc++] = 0.0;
    715             bound[bc++] = 0.0;
    716             bound[bc++] = 4;
    717         }
    718         if (rx1 < x2 && x2 < rx2) {
    719             bound[bc++] = 1.0;
    720             bound[bc++] = c.ax;
    721             bound[bc++] = c.ay;
    722             bound[bc++] = 5;
    723         }
    724         // End build bound ----------------------------------------------------
    725 
    726         int cross = crossBound(bound, bc, py1, py2);
    727         if (cross != UNKNOWN) {
    728             return cross;
    729         }
    730         return c.cross(res1, rc1, py1, py2);
    731     }
    732 
    733     /**
    734      * Returns how many times rectangle stripe cross cubic curve or the are intersect
    735      */
    736     public static int intersectCubic(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2, double rx1, double ry1, double rx2, double ry2) {
    737 
    738         // LEFT/RIGHT/UP
    739         if ((rx2 < x1 && rx2 < cx1 && rx2 < cx2 && rx2 < x2) ||
    740             (rx1 > x1 && rx1 > cx1 && rx1 > cx2 && rx1 > x2) ||
    741             (ry1 > y1 && ry1 > cy1 && ry1 > cy2 && ry1 > y2))
    742         {
    743             return 0;
    744         }
    745 
    746         // DOWN
    747         if (ry2 < y1 && ry2 < cy1 && ry2 < cy2 && ry2 < y2 && rx1 != x1 && rx1 != x2) {
    748             if (x1 < x2) {
    749                 return x1 < rx1 && rx1 < x2 ? 1 : 0;
    750             }
    751             return x2 < rx1 && rx1 < x1 ? -1 : 0;
    752         }
    753 
    754         // INSIDE
    755         CubicCurve c = new CubicCurve(x1, y1, cx1, cy1, cx2, cy2, x2, y2);
    756         double px1 = rx1 - x1;
    757         double py1 = ry1 - y1;
    758         double px2 = rx2 - x1;
    759         double py2 = ry2 - y1;
    760 
    761         double res1[] = new double[3];
    762         double res2[] = new double[3];
    763         int rc1 = c.solvePoint(res1, px1);
    764         int rc2 = c.solvePoint(res2, px2);
    765 
    766         // LEFT/RIGHT
    767         if (rc1 == 0 && rc2 == 0) {
    768             return 0;
    769         }
    770 
    771         double minX = px1 - DELTA;
    772         double maxX = px2 + DELTA;
    773 
    774         // Build bound --------------------------------------------------------
    775         double bound[] = new double[40];
    776         int bc = 0;
    777         // Add roots
    778         bc = c.addBound(bound, bc, res1, rc1, minX, maxX, false, 0);
    779         bc = c.addBound(bound, bc, res2, rc2, minX, maxX, false, 1);
    780         // Add extrimal points
    781         rc2 = c.solveExtremX(res2);
    782         bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 2);
    783         rc2 = c.solveExtremY(res2);
    784         bc = c.addBound(bound, bc, res2, rc2, minX, maxX, true, 4);
    785         // Add start and end
    786         if (rx1 < x1 && x1 < rx2) {
    787             bound[bc++] = 0.0;
    788             bound[bc++] = 0.0;
    789             bound[bc++] = 0.0;
    790             bound[bc++] = 6;
    791         }
    792         if (rx1 < x2 && x2 < rx2) {
    793             bound[bc++] = 1.0;
    794             bound[bc++] = c.ax;
    795             bound[bc++] = c.ay;
    796             bound[bc++] = 7;
    797         }
    798         // End build bound ----------------------------------------------------
    799 
    800         int cross = crossBound(bound, bc, py1, py2);
    801         if (cross != UNKNOWN) {
    802             return cross;
    803         }
    804         return c.cross(res1, rc1, py1, py2);
    805     }
    806 
    807     /**
    808      * Returns how many times rectangle stripe cross path or the are intersect
    809      */
    810     public static int intersectPath(PathIterator p, double x, double y, double w, double h) {
    811 
    812         int cross = 0;
    813         int count;
    814         double mx, my, cx, cy;
    815         mx = my = cx = cy = 0.0;
    816         double coords[] = new double[6];
    817 
    818         double rx1 = x;
    819         double ry1 = y;
    820         double rx2 = x + w;
    821         double ry2 = y + h;
    822 
    823         while (!p.isDone()) {
    824             count = 0;
    825             switch (p.currentSegment(coords)) {
    826             case PathIterator.SEG_MOVETO:
    827                 if (cx != mx || cy != my) {
    828                     count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2);
    829                 }
    830                 mx = cx = coords[0];
    831                 my = cy = coords[1];
    832                 break;
    833             case PathIterator.SEG_LINETO:
    834                 count = intersectLine(cx, cy, cx = coords[0], cy = coords[1], rx1, ry1, rx2, ry2);
    835                 break;
    836             case PathIterator.SEG_QUADTO:
    837                 count = intersectQuad(cx, cy, coords[0], coords[1], cx = coords[2], cy = coords[3], rx1, ry1, rx2, ry2);
    838                 break;
    839             case PathIterator.SEG_CUBICTO:
    840                 count = intersectCubic(cx, cy, coords[0], coords[1], coords[2], coords[3], cx = coords[4], cy = coords[5], rx1, ry1, rx2, ry2);
    841                 break;
    842             case PathIterator.SEG_CLOSE:
    843                 if (cy != my || cx != mx) {
    844                     count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2);
    845                 }
    846                 cx = mx;
    847                 cy = my;
    848                 break;
    849             }
    850             if (count == CROSSING) {
    851                 return CROSSING;
    852             }
    853             cross += count;
    854             p.next();
    855         }
    856         if (cy != my) {
    857             count = intersectLine(cx, cy, mx, my, rx1, ry1, rx2, ry2);
    858             if (count == CROSSING) {
    859                 return CROSSING;
    860             }
    861             cross += count;
    862         }
    863         return cross;
    864     }
    865 
    866     /**
    867      * Returns how many times rectangle stripe cross shape or the are intersect
    868      */
    869     public static int intersectShape(Shape s, double x, double y, double w, double h) {
    870         if (!s.getBounds2D().intersects(x, y, w, h)) {
    871             return 0;
    872         }
    873         return intersectPath(s.getPathIterator(null), x, y, w, h);
    874     }
    875 
    876     /**
    877      * Returns true if cross count correspond inside location for non zero path rule
    878      */
    879     public static boolean isInsideNonZero(int cross) {
    880         return cross != 0;
    881     }
    882 
    883     /**
    884      * Returns true if cross count correspond inside location for even-odd path rule
    885      */
    886     public static boolean isInsideEvenOdd(int cross) {
    887         return (cross & 1) != 0;
    888     }
    889 }