| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.awt.geom;  | 
 | 
 | 
 | 
import java.awt.geom.Rectangle2D;  | 
 | 
import java.awt.geom.PathIterator;  | 
 | 
import java.awt.geom.QuadCurve2D;  | 
 | 
import java.util.Vector;  | 
 | 
 | 
 | 
final class Order3 extends Curve { | 
 | 
    private double x0;  | 
 | 
    private double y0;  | 
 | 
    private double cx0;  | 
 | 
    private double cy0;  | 
 | 
    private double cx1;  | 
 | 
    private double cy1;  | 
 | 
    private double x1;  | 
 | 
    private double y1;  | 
 | 
 | 
 | 
    private double xmin;  | 
 | 
    private double xmax;  | 
 | 
 | 
 | 
    private double xcoeff0;  | 
 | 
    private double xcoeff1;  | 
 | 
    private double xcoeff2;  | 
 | 
    private double xcoeff3;  | 
 | 
 | 
 | 
    private double ycoeff0;  | 
 | 
    private double ycoeff1;  | 
 | 
    private double ycoeff2;  | 
 | 
    private double ycoeff3;  | 
 | 
 | 
 | 
    public static void insert(Vector curves, double tmp[],  | 
 | 
                              double x0, double y0,  | 
 | 
                              double cx0, double cy0,  | 
 | 
                              double cx1, double cy1,  | 
 | 
                              double x1, double y1,  | 
 | 
                              int direction)  | 
 | 
    { | 
 | 
        int numparams = getHorizontalParams(y0, cy0, cy1, y1, tmp);  | 
 | 
        if (numparams == 0) { | 
 | 
            // We are using addInstance here to avoid inserting horisontal  | 
 | 
              | 
 | 
            addInstance(curves, x0, y0, cx0, cy0, cx1, cy1, x1, y1, direction);  | 
 | 
            return;  | 
 | 
        }  | 
 | 
          | 
 | 
        tmp[3] = x0;  tmp[4]  = y0;  | 
 | 
        tmp[5] = cx0; tmp[6]  = cy0;  | 
 | 
        tmp[7] = cx1; tmp[8]  = cy1;  | 
 | 
        tmp[9] = x1;  tmp[10] = y1;  | 
 | 
        double t = tmp[0];  | 
 | 
        if (numparams > 1 && t > tmp[1]) { | 
 | 
              | 
 | 
            tmp[0] = tmp[1];  | 
 | 
            tmp[1] = t;  | 
 | 
            t = tmp[0];  | 
 | 
        }  | 
 | 
        split(tmp, 3, t);  | 
 | 
        if (numparams > 1) { | 
 | 
              | 
 | 
            t = (tmp[1] - t) / (1 - t);  | 
 | 
            split(tmp, 9, t);  | 
 | 
        }  | 
 | 
        int index = 3;  | 
 | 
        if (direction == DECREASING) { | 
 | 
            index += numparams * 6;  | 
 | 
        }  | 
 | 
        while (numparams >= 0) { | 
 | 
            addInstance(curves,  | 
 | 
                        tmp[index + 0], tmp[index + 1],  | 
 | 
                        tmp[index + 2], tmp[index + 3],  | 
 | 
                        tmp[index + 4], tmp[index + 5],  | 
 | 
                        tmp[index + 6], tmp[index + 7],  | 
 | 
                        direction);  | 
 | 
            numparams--;  | 
 | 
            if (direction == INCREASING) { | 
 | 
                index += 6;  | 
 | 
            } else { | 
 | 
                index -= 6;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public static void addInstance(Vector curves,  | 
 | 
                                   double x0, double y0,  | 
 | 
                                   double cx0, double cy0,  | 
 | 
                                   double cx1, double cy1,  | 
 | 
                                   double x1, double y1,  | 
 | 
                                   int direction) { | 
 | 
        if (y0 > y1) { | 
 | 
            curves.add(new Order3(x1, y1, cx1, cy1, cx0, cy0, x0, y0,  | 
 | 
                                  -direction));  | 
 | 
        } else if (y1 > y0) { | 
 | 
            curves.add(new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1,  | 
 | 
                                  direction));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static int getHorizontalParams(double c0, double cp0,  | 
 | 
                                          double cp1, double c1,  | 
 | 
                                          double ret[]) { | 
 | 
        if (c0 <= cp0 && cp0 <= cp1 && cp1 <= c1) { | 
 | 
            return 0;  | 
 | 
        }  | 
 | 
        c1 -= cp1;  | 
 | 
        cp1 -= cp0;  | 
 | 
        cp0 -= c0;  | 
 | 
        ret[0] = cp0;  | 
 | 
        ret[1] = (cp1 - cp0) * 2;  | 
 | 
        ret[2] = (c1 - cp1 - cp1 + cp0);  | 
 | 
        int numroots = QuadCurve2D.solveQuadratic(ret, ret);  | 
 | 
        int j = 0;  | 
 | 
        for (int i = 0; i < numroots; i++) { | 
 | 
            double t = ret[i];  | 
 | 
              | 
 | 
            if (t > 0 && t < 1) { | 
 | 
                if (j < i) { | 
 | 
                    ret[j] = t;  | 
 | 
                }  | 
 | 
                j++;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return j;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static void split(double coords[], int pos, double t) { | 
 | 
        double x0, y0, cx0, cy0, cx1, cy1, x1, y1;  | 
 | 
        coords[pos+12] = x1 = coords[pos+6];  | 
 | 
        coords[pos+13] = y1 = coords[pos+7];  | 
 | 
        cx1 = coords[pos+4];  | 
 | 
        cy1 = coords[pos+5];  | 
 | 
        x1 = cx1 + (x1 - cx1) * t;  | 
 | 
        y1 = cy1 + (y1 - cy1) * t;  | 
 | 
        x0 = coords[pos+0];  | 
 | 
        y0 = coords[pos+1];  | 
 | 
        cx0 = coords[pos+2];  | 
 | 
        cy0 = coords[pos+3];  | 
 | 
        x0 = x0 + (cx0 - x0) * t;  | 
 | 
        y0 = y0 + (cy0 - y0) * t;  | 
 | 
        cx0 = cx0 + (cx1 - cx0) * t;  | 
 | 
        cy0 = cy0 + (cy1 - cy0) * t;  | 
 | 
        cx1 = cx0 + (x1 - cx0) * t;  | 
 | 
        cy1 = cy0 + (y1 - cy0) * t;  | 
 | 
        cx0 = x0 + (cx0 - x0) * t;  | 
 | 
        cy0 = y0 + (cy0 - y0) * t;  | 
 | 
        coords[pos+2] = x0;  | 
 | 
        coords[pos+3] = y0;  | 
 | 
        coords[pos+4] = cx0;  | 
 | 
        coords[pos+5] = cy0;  | 
 | 
        coords[pos+6] = cx0 + (cx1 - cx0) * t;  | 
 | 
        coords[pos+7] = cy0 + (cy1 - cy0) * t;  | 
 | 
        coords[pos+8] = cx1;  | 
 | 
        coords[pos+9] = cy1;  | 
 | 
        coords[pos+10] = x1;  | 
 | 
        coords[pos+11] = y1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public Order3(double x0, double y0,  | 
 | 
                  double cx0, double cy0,  | 
 | 
                  double cx1, double cy1,  | 
 | 
                  double x1, double y1,  | 
 | 
                  int direction)  | 
 | 
    { | 
 | 
        super(direction);  | 
 | 
        // REMIND: Better accuracy in the root finding methods would  | 
 | 
        //  ensure that cys are in range.  As it stands, they are never  | 
 | 
          | 
 | 
        if (cy0 < y0) cy0 = y0;  | 
 | 
        if (cy1 > y1) cy1 = y1;  | 
 | 
        this.x0 = x0;  | 
 | 
        this.y0 = y0;  | 
 | 
        this.cx0 = cx0;  | 
 | 
        this.cy0 = cy0;  | 
 | 
        this.cx1 = cx1;  | 
 | 
        this.cy1 = cy1;  | 
 | 
        this.x1 = x1;  | 
 | 
        this.y1 = y1;  | 
 | 
        xmin = Math.min(Math.min(x0, x1), Math.min(cx0, cx1));  | 
 | 
        xmax = Math.max(Math.max(x0, x1), Math.max(cx0, cx1));  | 
 | 
        xcoeff0 = x0;  | 
 | 
        xcoeff1 = (cx0 - x0) * 3.0;  | 
 | 
        xcoeff2 = (cx1 - cx0 - cx0 + x0) * 3.0;  | 
 | 
        xcoeff3 = x1 - (cx1 - cx0) * 3.0 - x0;  | 
 | 
        ycoeff0 = y0;  | 
 | 
        ycoeff1 = (cy0 - y0) * 3.0;  | 
 | 
        ycoeff2 = (cy1 - cy0 - cy0 + y0) * 3.0;  | 
 | 
        ycoeff3 = y1 - (cy1 - cy0) * 3.0 - y0;  | 
 | 
        YforT1 = YforT2 = YforT3 = y0;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getOrder() { | 
 | 
        return 3;  | 
 | 
    }  | 
 | 
 | 
 | 
    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 getCX0() { | 
 | 
        return (direction == INCREASING) ? cx0 : cx1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double getCY0() { | 
 | 
        return (direction == INCREASING) ? cy0 : cy1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double getCX1() { | 
 | 
        return (direction == DECREASING) ? cx0 : cx1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double getCY1() { | 
 | 
        return (direction == DECREASING) ? cy0 : cy1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double getX1() { | 
 | 
        return (direction == DECREASING) ? x0 : x1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double getY1() { | 
 | 
        return (direction == DECREASING) ? y0 : y1;  | 
 | 
    }  | 
 | 
 | 
 | 
    private double TforY1;  | 
 | 
    private double YforT1;  | 
 | 
    private double TforY2;  | 
 | 
    private double YforT2;  | 
 | 
    private double TforY3;  | 
 | 
    private double YforT3;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public double TforY(double y) { | 
 | 
        if (y <= y0) return 0;  | 
 | 
        if (y >= y1) return 1;  | 
 | 
        if (y == YforT1) return TforY1;  | 
 | 
        if (y == YforT2) return TforY2;  | 
 | 
        if (y == YforT3) return TforY3;  | 
 | 
          | 
 | 
        if (ycoeff3 == 0.0) { | 
 | 
              | 
 | 
            return Order2.TforY(y, ycoeff0, ycoeff1, ycoeff2);  | 
 | 
        }  | 
 | 
        double a = ycoeff2 / ycoeff3;  | 
 | 
        double b = ycoeff1 / ycoeff3;  | 
 | 
        double c = (ycoeff0 - y) / ycoeff3;  | 
 | 
        int roots = 0;  | 
 | 
        double Q = (a * a - 3.0 * b) / 9.0;  | 
 | 
        double R = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0;  | 
 | 
        double R2 = R * R;  | 
 | 
        double Q3 = Q * Q * Q;  | 
 | 
        double a_3 = a / 3.0;  | 
 | 
        double t;  | 
 | 
        if (R2 < Q3) { | 
 | 
            double theta = Math.acos(R / Math.sqrt(Q3));  | 
 | 
            Q = -2.0 * Math.sqrt(Q);  | 
 | 
            t = refine(a, b, c, y, Q * Math.cos(theta / 3.0) - a_3);  | 
 | 
            if (t < 0) { | 
 | 
                t = refine(a, b, c, y,  | 
 | 
                           Q * Math.cos((theta + Math.PI * 2.0)/ 3.0) - a_3);  | 
 | 
            }  | 
 | 
            if (t < 0) { | 
 | 
                t = refine(a, b, c, y,  | 
 | 
                           Q * Math.cos((theta - Math.PI * 2.0)/ 3.0) - a_3);  | 
 | 
            }  | 
 | 
        } else { | 
 | 
            boolean neg = (R < 0.0);  | 
 | 
            double S = Math.sqrt(R2 - Q3);  | 
 | 
            if (neg) { | 
 | 
                R = -R;  | 
 | 
            }  | 
 | 
            double A = Math.pow(R + S, 1.0 / 3.0);  | 
 | 
            if (!neg) { | 
 | 
                A = -A;  | 
 | 
            }  | 
 | 
            double B = (A == 0.0) ? 0.0 : (Q / A);  | 
 | 
            t = refine(a, b, c, y, (A + B) - a_3);  | 
 | 
        }  | 
 | 
        if (t < 0) { | 
 | 
              | 
 | 
            double t0 = 0;  | 
 | 
            double t1 = 1;  | 
 | 
            while (true) { | 
 | 
                t = (t0 + t1) / 2;  | 
 | 
                if (t == t0 || t == t1) { | 
 | 
                    break;  | 
 | 
                }  | 
 | 
                double yt = YforT(t);  | 
 | 
                if (yt < y) { | 
 | 
                    t0 = t;  | 
 | 
                } else if (yt > y) { | 
 | 
                    t1 = t;  | 
 | 
                } else { | 
 | 
                    break;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (t >= 0) { | 
 | 
            TforY3 = TforY2;  | 
 | 
            YforT3 = YforT2;  | 
 | 
            TforY2 = TforY1;  | 
 | 
            YforT2 = YforT1;  | 
 | 
            TforY1 = t;  | 
 | 
            YforT1 = y;  | 
 | 
        }  | 
 | 
        return t;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double refine(double a, double b, double c,  | 
 | 
                         double target, double t)  | 
 | 
    { | 
 | 
        if (t < -0.1 || t > 1.1) { | 
 | 
            return -1;  | 
 | 
        }  | 
 | 
        double y = YforT(t);  | 
 | 
        double t0, t1;  | 
 | 
        if (y < target) { | 
 | 
            t0 = t;  | 
 | 
            t1 = 1;  | 
 | 
        } else { | 
 | 
            t0 = 0;  | 
 | 
            t1 = t;  | 
 | 
        }  | 
 | 
        double origt = t;  | 
 | 
        double origy = y;  | 
 | 
        boolean useslope = true;  | 
 | 
        while (y != target) { | 
 | 
            if (!useslope) { | 
 | 
                double t2 = (t0 + t1) / 2;  | 
 | 
                if (t2 == t0 || t2 == t1) { | 
 | 
                    break;  | 
 | 
                }  | 
 | 
                t = t2;  | 
 | 
            } else { | 
 | 
                double slope = dYforT(t, 1);  | 
 | 
                if (slope == 0) { | 
 | 
                    useslope = false;  | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                double t2 = t + ((target - y) / slope);  | 
 | 
                if (t2 == t || t2 <= t0 || t2 >= t1) { | 
 | 
                    useslope = false;  | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                t = t2;  | 
 | 
            }  | 
 | 
            y = YforT(t);  | 
 | 
            if (y < target) { | 
 | 
                t0 = t;  | 
 | 
            } else if (y > target) { | 
 | 
                t1 = t;  | 
 | 
            } else { | 
 | 
                break;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        boolean verbose = false;  | 
 | 
        if (false && t >= 0 && t <= 1) { | 
 | 
            y = YforT(t);  | 
 | 
            long tdiff = diffbits(t, origt);  | 
 | 
            long ydiff = diffbits(y, origy);  | 
 | 
            long yerr = diffbits(y, target);  | 
 | 
            if (yerr > 0 || (verbose && tdiff > 0)) { | 
 | 
                System.out.println("target was y = "+target); | 
 | 
                System.out.println("original was y = "+origy+", t = "+origt); | 
 | 
                System.out.println("final was y = "+y+", t = "+t); | 
 | 
                System.out.println("t diff is "+tdiff); | 
 | 
                System.out.println("y diff is "+ydiff); | 
 | 
                System.out.println("y error is "+yerr); | 
 | 
                double tlow = prev(t);  | 
 | 
                double ylow = YforT(tlow);  | 
 | 
                double thi = next(t);  | 
 | 
                double yhi = YforT(thi);  | 
 | 
                if (Math.abs(target - ylow) < Math.abs(target - y) ||  | 
 | 
                    Math.abs(target - yhi) < Math.abs(target - y))  | 
 | 
                { | 
 | 
                    System.out.println("adjacent y's = ["+ylow+", "+yhi+"]"); | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return (t > 1) ? -1 : t;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double XforY(double y) { | 
 | 
        if (y <= y0) { | 
 | 
            return x0;  | 
 | 
        }  | 
 | 
        if (y >= y1) { | 
 | 
            return x1;  | 
 | 
        }  | 
 | 
        return XforT(TforY(y));  | 
 | 
    }  | 
 | 
 | 
 | 
    public double XforT(double t) { | 
 | 
        return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double YforT(double t) { | 
 | 
        return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;  | 
 | 
    }  | 
 | 
 | 
 | 
    public double dXforT(double t, int deriv) { | 
 | 
        switch (deriv) { | 
 | 
        case 0:  | 
 | 
            return (((xcoeff3 * t) + xcoeff2) * t + xcoeff1) * t + xcoeff0;  | 
 | 
        case 1:  | 
 | 
            return ((3 * xcoeff3 * t) + 2 * xcoeff2) * t + xcoeff1;  | 
 | 
        case 2:  | 
 | 
            return (6 * xcoeff3 * t) + 2 * xcoeff2;  | 
 | 
        case 3:  | 
 | 
            return 6 * xcoeff3;  | 
 | 
        default:  | 
 | 
            return 0;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public double dYforT(double t, int deriv) { | 
 | 
        switch (deriv) { | 
 | 
        case 0:  | 
 | 
            return (((ycoeff3 * t) + ycoeff2) * t + ycoeff1) * t + ycoeff0;  | 
 | 
        case 1:  | 
 | 
            return ((3 * ycoeff3 * t) + 2 * ycoeff2) * t + ycoeff1;  | 
 | 
        case 2:  | 
 | 
            return (6 * ycoeff3 * t) + 2 * ycoeff2;  | 
 | 
        case 3:  | 
 | 
            return 6 * ycoeff3;  | 
 | 
        default:  | 
 | 
            return 0;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public double nextVertical(double t0, double t1) { | 
 | 
        double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3}; | 
 | 
        int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);  | 
 | 
        for (int i = 0; i < numroots; i++) { | 
 | 
            if (eqn[i] > t0 && eqn[i] < t1) { | 
 | 
                t1 = eqn[i];  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return t1;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void enlarge(Rectangle2D r) { | 
 | 
        r.add(x0, y0);  | 
 | 
        double eqn[] = {xcoeff1, 2 * xcoeff2, 3 * xcoeff3}; | 
 | 
        int numroots = QuadCurve2D.solveQuadratic(eqn, eqn);  | 
 | 
        for (int i = 0; i < numroots; i++) { | 
 | 
            double t = eqn[i];  | 
 | 
            if (t > 0 && t < 1) { | 
 | 
                r.add(XforT(t), YforT(t));  | 
 | 
            }  | 
 | 
        }  | 
 | 
        r.add(x1, y1);  | 
 | 
    }  | 
 | 
 | 
 | 
    public Curve getSubCurve(double ystart, double yend, int dir) { | 
 | 
        if (ystart <= y0 && yend >= y1) { | 
 | 
            return getWithDirection(dir);  | 
 | 
        }  | 
 | 
        double eqn[] = new double[14];  | 
 | 
        double t0, t1;  | 
 | 
        t0 = TforY(ystart);  | 
 | 
        t1 = TforY(yend);  | 
 | 
        eqn[0] = x0;  | 
 | 
        eqn[1] = y0;  | 
 | 
        eqn[2] = cx0;  | 
 | 
        eqn[3] = cy0;  | 
 | 
        eqn[4] = cx1;  | 
 | 
        eqn[5] = cy1;  | 
 | 
        eqn[6] = x1;  | 
 | 
        eqn[7] = y1;  | 
 | 
        if (t0 > t1) { | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            double t = t0;  | 
 | 
            t0 = t1;  | 
 | 
            t1 = t;  | 
 | 
        }  | 
 | 
        if (t1 < 1) { | 
 | 
            split(eqn, 0, t1);  | 
 | 
        }  | 
 | 
        int i;  | 
 | 
        if (t0 <= 0) { | 
 | 
            i = 0;  | 
 | 
        } else { | 
 | 
            split(eqn, 0, t0 / t1);  | 
 | 
            i = 6;  | 
 | 
        }  | 
 | 
        return new Order3(eqn[i+0], ystart,  | 
 | 
                          eqn[i+2], eqn[i+3],  | 
 | 
                          eqn[i+4], eqn[i+5],  | 
 | 
                          eqn[i+6], yend,  | 
 | 
                          dir);  | 
 | 
    }  | 
 | 
 | 
 | 
    public Curve getReversedCurve() { | 
 | 
        return new Order3(x0, y0, cx0, cy0, cx1, cy1, x1, y1, -direction);  | 
 | 
    }  | 
 | 
 | 
 | 
    public int getSegment(double coords[]) { | 
 | 
        if (direction == INCREASING) { | 
 | 
            coords[0] = cx0;  | 
 | 
            coords[1] = cy0;  | 
 | 
            coords[2] = cx1;  | 
 | 
            coords[3] = cy1;  | 
 | 
            coords[4] = x1;  | 
 | 
            coords[5] = y1;  | 
 | 
        } else { | 
 | 
            coords[0] = cx1;  | 
 | 
            coords[1] = cy1;  | 
 | 
            coords[2] = cx0;  | 
 | 
            coords[3] = cy0;  | 
 | 
            coords[4] = x0;  | 
 | 
            coords[5] = y0;  | 
 | 
        }  | 
 | 
        return PathIterator.SEG_CUBICTO;  | 
 | 
    }  | 
 | 
 | 
 | 
    public String controlPointString() { | 
 | 
        return (("("+round(getCX0())+", "+round(getCY0())+"), ")+ | 
 | 
                ("("+round(getCX1())+", "+round(getCY1())+"), ")); | 
 | 
    }  | 
 | 
}  |