jdk/src/java.desktop/share/classes/sun/java2d/marlin/DCurve.java
author lbourges
Wed, 17 May 2017 22:05:11 +0200
changeset 47126 188ef162f019
permissions -rw-r--r--
8180055: Upgrade the Marlin renderer in Java2D Summary: added the double-precision variant + MarlinFX backports + Improved MarlinTileGenerator + higher precision of the cubic / quadratic curve Reviewed-by: flar, pnarayanan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47126
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     1
/*
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     2
 * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     4
 *
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    10
 *
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    15
 * accompanied this code).
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    16
 *
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    20
 *
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    23
 * questions.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    24
 */
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    25
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    26
package sun.java2d.marlin;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    27
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    28
final class DCurve {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    29
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    30
    double ax, ay, bx, by, cx, cy, dx, dy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    31
    double dax, day, dbx, dby;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    32
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    33
    DCurve() {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    34
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    35
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    36
    void set(double[] points, int type) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    37
        switch(type) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    38
        case 8:
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    39
            set(points[0], points[1],
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    40
                points[2], points[3],
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    41
                points[4], points[5],
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    42
                points[6], points[7]);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    43
            return;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    44
        case 6:
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    45
            set(points[0], points[1],
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    46
                points[2], points[3],
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    47
                points[4], points[5]);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    48
            return;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    49
        default:
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    50
            throw new InternalError("Curves can only be cubic or quadratic");
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    51
        }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    52
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    53
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    54
    void set(double x1, double y1,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    55
             double x2, double y2,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    56
             double x3, double y3,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    57
             double x4, double y4)
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    58
    {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    59
        ax = 3.0d * (x2 - x3) + x4 - x1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    60
        ay = 3.0d * (y2 - y3) + y4 - y1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    61
        bx = 3.0d * (x1 - 2.0d * x2 + x3);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    62
        by = 3.0d * (y1 - 2.0d * y2 + y3);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    63
        cx = 3.0d * (x2 - x1);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    64
        cy = 3.0d * (y2 - y1);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    65
        dx = x1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    66
        dy = y1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    67
        dax = 3.0d * ax; day = 3.0d * ay;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    68
        dbx = 2.0d * bx; dby = 2.0d * by;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    69
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    70
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    71
    void set(double x1, double y1,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    72
             double x2, double y2,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    73
             double x3, double y3)
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    74
    {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    75
        ax = 0.0d; ay = 0.0d;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    76
        bx = x1 - 2.0d * x2 + x3;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    77
        by = y1 - 2.0d * y2 + y3;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    78
        cx = 2.0d * (x2 - x1);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    79
        cy = 2.0d * (y2 - y1);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    80
        dx = x1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    81
        dy = y1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    82
        dax = 0.0d; day = 0.0d;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    83
        dbx = 2.0d * bx; dby = 2.0d * by;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    84
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    85
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    86
    double xat(double t) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    87
        return t * (t * (t * ax + bx) + cx) + dx;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    88
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    89
    double yat(double t) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    90
        return t * (t * (t * ay + by) + cy) + dy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    91
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    92
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    93
    double dxat(double t) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    94
        return t * (t * dax + dbx) + cx;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    95
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    96
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    97
    double dyat(double t) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    98
        return t * (t * day + dby) + cy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
    99
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   100
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   101
    int dxRoots(double[] roots, int off) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   102
        return DHelpers.quadraticRoots(dax, dbx, cx, roots, off);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   103
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   104
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   105
    int dyRoots(double[] roots, int off) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   106
        return DHelpers.quadraticRoots(day, dby, cy, roots, off);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   107
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   108
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   109
    int infPoints(double[] pts, int off) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   110
        // inflection point at t if -f'(t)x*f''(t)y + f'(t)y*f''(t)x == 0
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   111
        // Fortunately, this turns out to be quadratic, so there are at
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   112
        // most 2 inflection points.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   113
        final double a = dax * dby - dbx * day;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   114
        final double b = 2.0d * (cy * dax - day * cx);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   115
        final double c = cy * dbx - cx * dby;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   116
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   117
        return DHelpers.quadraticRoots(a, b, c, pts, off);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   118
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   119
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   120
    // finds points where the first and second derivative are
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   121
    // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   122
    // * is a dot product). Unfortunately, we have to solve a cubic.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   123
    private int perpendiculardfddf(double[] pts, int off) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   124
        assert pts.length >= off + 4;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   125
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   126
        // these are the coefficients of some multiple of g(t) (not g(t),
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   127
        // because the roots of a polynomial are not changed after multiplication
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   128
        // by a constant, and this way we save a few multiplications).
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   129
        final double a = 2.0d * (dax*dax + day*day);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   130
        final double b = 3.0d * (dax*dbx + day*dby);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   131
        final double c = 2.0d * (dax*cx + day*cy) + dbx*dbx + dby*dby;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   132
        final double d = dbx*cx + dby*cy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   133
        return DHelpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   134
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   135
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   136
    // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   137
    // a variant of the false position algorithm to find the roots. False
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   138
    // position requires that 2 initial values x0,x1 be given, and that the
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   139
    // function must have opposite signs at those values. To find such
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   140
    // values, we need the local extrema of the ROC function, for which we
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   141
    // need the roots of its derivative; however, it's harder to find the
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   142
    // roots of the derivative in this case than it is to find the roots
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   143
    // of the original function. So, we find all points where this curve's
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   144
    // first and second derivative are perpendicular, and we pretend these
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   145
    // are our local extrema. There are at most 3 of these, so we will check
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   146
    // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   147
    // points, so roc-w can have at least 6 roots. This shouldn't be a
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   148
    // problem for what we're trying to do (draw a nice looking curve).
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   149
    int rootsOfROCMinusW(double[] roots, int off, final double w, final double err) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   150
        // no OOB exception, because by now off<=6, and roots.length >= 10
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   151
        assert off <= 6 && roots.length >= 10;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   152
        int ret = off;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   153
        int numPerpdfddf = perpendiculardfddf(roots, off);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   154
        double t0 = 0.0d, ft0 = ROCsq(t0) - w*w;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   155
        roots[off + numPerpdfddf] = 1.0d; // always check interval end points
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   156
        numPerpdfddf++;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   157
        for (int i = off; i < off + numPerpdfddf; i++) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   158
            double t1 = roots[i], ft1 = ROCsq(t1) - w*w;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   159
            if (ft0 == 0.0d) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   160
                roots[ret++] = t0;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   161
            } else if (ft1 * ft0 < 0.0d) { // have opposite signs
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   162
                // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   163
                // ROC(t) >= 0 for all t.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   164
                roots[ret++] = falsePositionROCsqMinusX(t0, t1, w*w, err);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   165
            }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   166
            t0 = t1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   167
            ft0 = ft1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   168
        }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   169
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   170
        return ret - off;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   171
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   172
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   173
    private static double eliminateInf(double x) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   174
        return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE :
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   175
            (x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x));
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   176
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   177
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   178
    // A slight modification of the false position algorithm on wikipedia.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   179
    // This only works for the ROCsq-x functions. It might be nice to have
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   180
    // the function as an argument, but that would be awkward in java6.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   181
    // TODO: It is something to consider for java8 (or whenever lambda
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   182
    // expressions make it into the language), depending on how closures
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   183
    // and turn out. Same goes for the newton's method
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   184
    // algorithm in DHelpers.java
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   185
    private double falsePositionROCsqMinusX(double x0, double x1,
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   186
                                           final double x, final double err)
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   187
    {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   188
        final int iterLimit = 100;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   189
        int side = 0;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   190
        double t = x1, ft = eliminateInf(ROCsq(t) - x);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   191
        double s = x0, fs = eliminateInf(ROCsq(s) - x);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   192
        double r = s, fr;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   193
        for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   194
            r = (fs * t - ft * s) / (fs - ft);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   195
            fr = ROCsq(r) - x;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   196
            if (sameSign(fr, ft)) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   197
                ft = fr; t = r;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   198
                if (side < 0) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   199
                    fs /= (1 << (-side));
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   200
                    side--;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   201
                } else {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   202
                    side = -1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   203
                }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   204
            } else if (fr * fs > 0) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   205
                fs = fr; s = r;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   206
                if (side > 0) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   207
                    ft /= (1 << side);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   208
                    side++;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   209
                } else {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   210
                    side = 1;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   211
                }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   212
            } else {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   213
                break;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   214
            }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   215
        }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   216
        return r;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   217
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   218
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   219
    private static boolean sameSign(double x, double y) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   220
        // another way is to test if x*y > 0. This is bad for small x, y.
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   221
        return (x < 0.0d && y < 0.0d) || (x > 0.0d && y > 0.0d);
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   222
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   223
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   224
    // returns the radius of curvature squared at t of this curve
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   225
    // see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   226
    private double ROCsq(final double t) {
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   227
        // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   228
        final double dx = t * (t * dax + dbx) + cx;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   229
        final double dy = t * (t * day + dby) + cy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   230
        final double ddx = 2.0d * dax * t + dbx;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   231
        final double ddy = 2.0d * day * t + dby;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   232
        final double dx2dy2 = dx*dx + dy*dy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   233
        final double ddx2ddy2 = ddx*ddx + ddy*ddy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   234
        final double ddxdxddydy = ddx*dx + ddy*dy;
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   235
        return dx2dy2*((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy));
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   236
    }
188ef162f019 8180055: Upgrade the Marlin renderer in Java2D
lbourges
parents:
diff changeset
   237
}