jdk/src/share/classes/sun/awt/geom/Curve.java
author ohair
Tue, 25 May 2010 15:58:33 -0700
changeset 5506 202f599c92aa
parent 2 90ce3da70b43
child 24538 25bf8153fbfe
permissions -rw-r--r--
6943119: Rebrand source copyright notices Reviewed-by: darcy, weijun
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     2
 * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.awt.geom;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.awt.geom.Rectangle2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.awt.geom.QuadCurve2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.awt.geom.CubicCurve2D;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.awt.geom.PathIterator;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.awt.geom.IllegalPathStateException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.util.Vector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
public abstract class Curve {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
    public static final int INCREASING = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
    public static final int DECREASING = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
    protected int direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
    public static void insertMove(Vector curves, double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
        curves.add(new Order0(x, y));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    public static void insertLine(Vector curves,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
                                  double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
                                  double x1, double y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
        if (y0 < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
            curves.add(new Order1(x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
                                  x1, y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
                                  INCREASING));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
        } else if (y0 > y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
            curves.add(new Order1(x1, y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
                                  x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
                                  DECREASING));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
            // Do not add horizontal lines
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    public static void insertQuad(Vector curves,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
                                  double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
                                  double coords[])
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
        double y1 = coords[3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
        if (y0 > y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
            Order2.insert(curves, coords,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
                          coords[2], y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
                          coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
                          x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
                          DECREASING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
        } else if (y0 == y1 && y0 == coords[1]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
            // Do not add horizontal lines
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
            Order2.insert(curves, coords,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
                          x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
                          coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
                          coords[2], y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
                          INCREASING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    public static void insertCubic(Vector curves,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
                                   double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
                                   double coords[])
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
        double y1 = coords[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        if (y0 > y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
            Order3.insert(curves, coords,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
                          coords[4], y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
                          coords[2], coords[3],
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
                          coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
                          x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
                          DECREASING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
        } else if (y0 == y1 && y0 == coords[1] && y0 == coords[3]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
            // Do not add horizontal lines
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
            Order3.insert(curves, coords,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
                          x0, y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
                          coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
                          coords[2], coords[3],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
                          coords[4], y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
                          INCREASING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * Calculates the number of times the given path
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * crosses the ray extending to the right from (px,py).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * If the point lies on a part of the path,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * then no crossings are counted for that intersection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     * +1 is added for each crossing where the Y coordinate is increasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * -1 is added for each crossing where the Y coordinate is decreasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * The return value is the sum of all crossings for every segment in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * the path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     * The path must start with a SEG_MOVETO, otherwise an exception is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
     * thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * The caller must check p[xy] for NaN values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
     * The caller may also reject infinite p[xy] values as well.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    public static int pointCrossingsForPath(PathIterator pi,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                                            double px, double py)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
        if (pi.isDone()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        double coords[] = new double[6];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        if (pi.currentSegment(coords) != PathIterator.SEG_MOVETO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
            throw new IllegalPathStateException("missing initial moveto "+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                                                "in path definition");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        pi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        double movx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        double movy = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
        double curx = movx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        double cury = movy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        double endx, endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        int crossings = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        while (!pi.isDone()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
            switch (pi.currentSegment(coords)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            case PathIterator.SEG_MOVETO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                if (cury != movy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                    crossings += pointCrossingsForLine(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                                                       curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                                                       movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
                movx = curx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
                movy = cury = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            case PathIterator.SEG_LINETO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
                endx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
                endy = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
                crossings += pointCrossingsForLine(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
                                                   curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                                                   endx, endy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            case PathIterator.SEG_QUADTO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                endx = coords[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                endy = coords[3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                crossings += pointCrossingsForQuad(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                                                   curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                                                   coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
                                                   endx, endy, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
            case PathIterator.SEG_CUBICTO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
                endx = coords[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
                endy = coords[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
                crossings += pointCrossingsForCubic(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
                                                    curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
                                                    coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
                                                    coords[2], coords[3],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                                                    endx, endy, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            case PathIterator.SEG_CLOSE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                if (cury != movy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                    crossings += pointCrossingsForLine(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                                                       curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                                                       movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                curx = movx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                cury = movy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            pi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        if (cury != movy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            crossings += pointCrossingsForLine(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                                               curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                                               movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     * Calculates the number of times the line from (x0,y0) to (x1,y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * crosses the ray extending to the right from (px,py).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     * If the point lies on the line, then no crossings are recorded.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
     * +1 is returned for a crossing where the Y coordinate is increasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
     * -1 is returned for a crossing where the Y coordinate is decreasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    public static int pointCrossingsForLine(double px, double py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                                            double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                                            double x1, double y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
        if (py <  y0 && py <  y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        if (py >= y0 && py >= y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        // assert(y0 != y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
        if (px >= x0 && px >= x1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        if (px <  x0 && px <  x1) return (y0 < y1) ? 1 : -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        double xintercept = x0 + (py - y0) * (x1 - x0) / (y1 - y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        if (px >= xintercept) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        return (y0 < y1) ? 1 : -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     * Calculates the number of times the quad from (x0,y0) to (x1,y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
     * crosses the ray extending to the right from (px,py).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
     * If the point lies on a part of the curve,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
     * then no crossings are counted for that intersection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     * the level parameter should be 0 at the top-level call and will count
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * up for each recursion level to prevent infinite recursion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * +1 is added for each crossing where the Y coordinate is increasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * -1 is added for each crossing where the Y coordinate is decreasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    public static int pointCrossingsForQuad(double px, double py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                                            double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                                            double xc, double yc,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                                            double x1, double y1, int level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
        if (py <  y0 && py <  yc && py <  y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        if (py >= y0 && py >= yc && py >= y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        // Note y0 could equal y1...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        if (px >= x0 && px >= xc && px >= x1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        if (px <  x0 && px <  xc && px <  x1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            if (py >= y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                if (py < y1) return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                // py < y0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                if (py >= y1) return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            // py outside of y01 range, and/or y0==y1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        // double precision only has 52 bits of mantissa
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        if (level > 52) return pointCrossingsForLine(px, py, x0, y0, x1, y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
        double x0c = (x0 + xc) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        double y0c = (y0 + yc) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        double xc1 = (xc + x1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        double yc1 = (yc + y1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        xc = (x0c + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        yc = (y0c + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
        if (Double.isNaN(xc) || Double.isNaN(yc)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            // [xy]c are NaN if any of [xy]0c or [xy]c1 are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            // [xy]0c or [xy]c1 are NaN if any of [xy][0c1] are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            // These values are also NaN if opposing infinities are added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        return (pointCrossingsForQuad(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                                      x0, y0, x0c, y0c, xc, yc,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                                      level+1) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                pointCrossingsForQuad(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                                      xc, yc, xc1, yc1, x1, y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                                      level+1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
     * Calculates the number of times the cubic from (x0,y0) to (x1,y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
     * crosses the ray extending to the right from (px,py).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     * If the point lies on a part of the curve,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     * then no crossings are counted for that intersection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     * the level parameter should be 0 at the top-level call and will count
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * up for each recursion level to prevent infinite recursion
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     * +1 is added for each crossing where the Y coordinate is increasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * -1 is added for each crossing where the Y coordinate is decreasing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
    public static int pointCrossingsForCubic(double px, double py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
                                             double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
                                             double xc0, double yc0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                                             double xc1, double yc1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
                                             double x1, double y1, int level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        if (py <  y0 && py <  yc0 && py <  yc1 && py <  y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        if (py >= y0 && py >= yc0 && py >= yc1 && py >= y1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        // Note y0 could equal yc0...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        if (px >= x0 && px >= xc0 && px >= xc1 && px >= x1) return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        if (px <  x0 && px <  xc0 && px <  xc1 && px <  x1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            if (py >= y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                if (py < y1) return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
                // py < y0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                if (py >= y1) return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
            // py outside of y01 range, and/or y0==yc0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        // double precision only has 52 bits of mantissa
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
        if (level > 52) return pointCrossingsForLine(px, py, x0, y0, x1, y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
        double xmid = (xc0 + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        double ymid = (yc0 + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        xc0 = (x0 + xc0) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        yc0 = (y0 + yc0) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        xc1 = (xc1 + x1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        yc1 = (yc1 + y1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        double xc0m = (xc0 + xmid) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
        double yc0m = (yc0 + ymid) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        double xmc1 = (xmid + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        double ymc1 = (ymid + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        xmid = (xc0m + xmc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
        ymid = (yc0m + ymc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        if (Double.isNaN(xmid) || Double.isNaN(ymid)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            // [xy]mid are NaN if any of [xy]c0m or [xy]mc1 are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            // [xy]c0m or [xy]mc1 are NaN if any of [xy][c][01] are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
            // These values are also NaN if opposing infinities are added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        return (pointCrossingsForCubic(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
                                       x0, y0, xc0, yc0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
                                       xc0m, yc0m, xmid, ymid, level+1) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
                pointCrossingsForCubic(px, py,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
                                       xmid, ymid, xmc1, ymc1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
                                       xc1, yc1, x1, y1, level+1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * The rectangle intersection test counts the number of times
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     * that the path crosses through the shadow that the rectangle
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     * projects to the right towards (x => +INFINITY).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
     * During processing of the path it actually counts every time
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
     * the path crosses either or both of the top and bottom edges
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
     * of that shadow.  If the path enters from the top, the count
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * is incremented.  If it then exits back through the top, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     * same way it came in, the count is decremented and there is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * no impact on the winding count.  If, instead, the path exits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     * out the bottom, then the count is incremented again and a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * full pass through the shadow is indicated by the winding count
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     * having been incremented by 2.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     * Thus, the winding count that it accumulates is actually double
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
     * the real winding count.  Since the path is continuous, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
     * final answer should be a multiple of 2, otherwise there is a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
     * logic error somewhere.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
     * If the path ever has a direct hit on the rectangle, then a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
     * special value is returned.  This special value terminates
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
     * all ongoing accumulation on up through the call chain and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
     * ends up getting returned to the calling function which can
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     * then produce an answer directly.  For intersection tests,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     * the answer is always "true" if the path intersects the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     * rectangle.  For containment tests, the answer is always
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     * "false" if the path intersects the rectangle.  Thus, no
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     * further processing is ever needed if an intersection occurs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
    public static final int RECT_INTERSECTS = 0x80000000;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
     * Accumulate the number of times the path crosses the shadow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
     * extending to the right of the rectangle.  See the comment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
     * for the RECT_INTERSECTS constant for more complete details.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     * The return value is the sum of all crossings for both the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     * top and bottom of the shadow for every segment in the path,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     * or the special value RECT_INTERSECTS if the path ever enters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
     * the interior of the rectangle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     * The path must start with a SEG_MOVETO, otherwise an exception is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
     * thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
     * The caller must check r[xy]{min,max} for NaN values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    public static int rectCrossingsForPath(PathIterator pi,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                                           double rxmin, double rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                                           double rxmax, double rymax)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        if (rxmax <= rxmin || rymax <= rymin) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
        if (pi.isDone()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        double coords[] = new double[6];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        if (pi.currentSegment(coords) != PathIterator.SEG_MOVETO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            throw new IllegalPathStateException("missing initial moveto "+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
                                                "in path definition");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        pi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        double curx, cury, movx, movy, endx, endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        curx = movx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        cury = movy = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
        int crossings = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        while (crossings != RECT_INTERSECTS && !pi.isDone()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            switch (pi.currentSegment(coords)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            case PathIterator.SEG_MOVETO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                if (curx != movx || cury != movy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                    crossings = rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                                                     rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                                                     rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                                                     curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                                                     movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                // Count should always be a multiple of 2 here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                // assert((crossings & 1) != 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                movx = curx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                movy = cury = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
            case PathIterator.SEG_LINETO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                endx = coords[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                endy = coords[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                crossings = rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                                                 rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                                                 rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                                                 curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                                                 endx, endy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            case PathIterator.SEG_QUADTO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                endx = coords[2];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                endy = coords[3];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                crossings = rectCrossingsForQuad(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                                                 rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                                                 rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                                                 curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                                                 coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                                                 endx, endy, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            case PathIterator.SEG_CUBICTO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
                endx = coords[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                endy = coords[5];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                crossings = rectCrossingsForCubic(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                                                  rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                                                  rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                                                  curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                                                  coords[0], coords[1],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                                                  coords[2], coords[3],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                                                  endx, endy, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                curx = endx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                cury = endy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
            case PathIterator.SEG_CLOSE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                if (curx != movx || cury != movy) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                    crossings = rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                                                     rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                                                     rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                                                     curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                                                     movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
                curx = movx;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                cury = movy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                // Count should always be a multiple of 2 here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                // assert((crossings & 1) != 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            pi.next();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        if (crossings != RECT_INTERSECTS && (curx != movx || cury != movy)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            crossings = rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                                             rxmin, rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                                             rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                                             curx, cury,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                                             movx, movy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
        // Count should always be a multiple of 2 here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        // assert((crossings & 1) != 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * Accumulate the number of times the line crosses the shadow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * extending to the right of the rectangle.  See the comment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     * for the RECT_INTERSECTS constant for more complete details.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    public static int rectCrossingsForLine(int crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                                           double rxmin, double rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                                           double rxmax, double rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                                           double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                                           double x1, double y1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        if (y0 >= rymax && y1 >= rymax) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
        if (y0 <= rymin && y1 <= rymin) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        if (x0 <= rxmin && x1 <= rxmin) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        if (x0 >= rxmax && x1 >= rxmax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            // Line is entirely to the right of the rect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
            // and the vertical ranges of the two overlap by a non-empty amount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            // Thus, this line segment is partially in the "right-shadow"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            // Path may have done a complete crossing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
            // Or path may have entered or exited the right-shadow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            if (y0 < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                // y-increasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                // We know that y0 < rymax and y1 > rymin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
                if (y0 <= rymin) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
                if (y1 >= rymax) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            } else if (y1 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
                // y-decreasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                // We know that y1 < rymax and y0 > rymin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                if (y1 <= rymin) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
                if (y0 >= rymax) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        // Remaining case:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        // Both x and y ranges overlap by a non-empty amount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        // First do trivial INTERSECTS rejection of the cases
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        // where one of the endpoints is inside the rectangle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        if ((x0 > rxmin && x0 < rxmax && y0 > rymin && y0 < rymax) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            (x1 > rxmin && x1 < rxmax && y1 > rymin && y1 < rymax))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            return RECT_INTERSECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
        // Otherwise calculate the y intercepts and see where
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        // they fall with respect to the rectangle
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
        double xi0 = x0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
        if (y0 < rymin) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
            xi0 += ((rymin - y0) * (x1 - x0) / (y1 - y0));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        } else if (y0 > rymax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
            xi0 += ((rymax - y0) * (x1 - x0) / (y1 - y0));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        double xi1 = x1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        if (y1 < rymin) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            xi1 += ((rymin - y1) * (x0 - x1) / (y0 - y1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        } else if (y1 > rymax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
            xi1 += ((rymax - y1) * (x0 - x1) / (y0 - y1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        if (xi0 <= rxmin && xi1 <= rxmin) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        if (xi0 >= rxmax && xi1 >= rxmax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
            if (y0 < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                // y-increasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                // We know that y0 < rymax and y1 > rymin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
                if (y0 <= rymin) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
                if (y1 >= rymax) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            } else if (y1 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
                // y-decreasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                // We know that y1 < rymax and y0 > rymin
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
                if (y1 <= rymin) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
                if (y0 >= rymax) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
        return RECT_INTERSECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     * Accumulate the number of times the quad crosses the shadow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * extending to the right of the rectangle.  See the comment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * for the RECT_INTERSECTS constant for more complete details.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    public static int rectCrossingsForQuad(int crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
                                           double rxmin, double rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                                           double rxmax, double rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
                                           double x0, double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                                           double xc, double yc,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                                           double x1, double y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                                           int level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        if (y0 >= rymax && yc >= rymax && y1 >= rymax) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        if (y0 <= rymin && yc <= rymin && y1 <= rymin) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
        if (x0 <= rxmin && xc <= rxmin && x1 <= rxmin) return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        if (x0 >= rxmax && xc >= rxmax && x1 >= rxmax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            // Quad is entirely to the right of the rect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            // and the vertical range of the 3 Y coordinates of the quad
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
            // overlaps the vertical range of the rect by a non-empty amount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
            // We now judge the crossings solely based on the line segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
            // connecting the endpoints of the quad.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
            // Note that we may have 0, 1, or 2 crossings as the control
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            // point may be causing the Y range intersection while the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            // two endpoints are entirely above or below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
            if (y0 < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                // y-increasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                if (y0 <= rymin && y1 >  rymin) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                if (y0 <  rymax && y1 >= rymax) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
            } else if (y1 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                // y-decreasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
                if (y1 <= rymin && y0 >  rymin) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
                if (y1 <  rymax && y0 >= rymax) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        // The intersection of ranges is more complicated
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
        // First do trivial INTERSECTS rejection of the cases
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        // where one of the endpoints is inside the rectangle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        if ((x0 < rxmax && x0 > rxmin && y0 < rymax && y0 > rymin) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            (x1 < rxmax && x1 > rxmin && y1 < rymax && y1 > rymin))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
            return RECT_INTERSECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        // Otherwise, subdivide and look for one of the cases above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        // double precision only has 52 bits of mantissa
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        if (level > 52) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
            return rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
                                        rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
                                        x0, y0, x1, y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
        double x0c = (x0 + xc) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        double y0c = (y0 + yc) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        double xc1 = (xc + x1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        double yc1 = (yc + y1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        xc = (x0c + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
        yc = (y0c + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        if (Double.isNaN(xc) || Double.isNaN(yc)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
            // [xy]c are NaN if any of [xy]0c or [xy]c1 are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
            // [xy]0c or [xy]c1 are NaN if any of [xy][0c1] are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            // These values are also NaN if opposing infinities are added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
        crossings = rectCrossingsForQuad(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                                         rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
                                         x0, y0, x0c, y0c, xc, yc,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
                                         level+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        if (crossings != RECT_INTERSECTS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            crossings = rectCrossingsForQuad(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                                             rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                                             xc, yc, xc1, yc1, x1, y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                                             level+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
        return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
     * Accumulate the number of times the cubic crosses the shadow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
     * extending to the right of the rectangle.  See the comment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
     * for the RECT_INTERSECTS constant for more complete details.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
    public static int rectCrossingsForCubic(int crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                                            double rxmin, double rymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                                            double rxmax, double rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                                            double x0,  double y0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                                            double xc0, double yc0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                                            double xc1, double yc1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                                            double x1,  double y1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                                            int level)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
        if (y0 >= rymax && yc0 >= rymax && yc1 >= rymax && y1 >= rymax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        if (y0 <= rymin && yc0 <= rymin && yc1 <= rymin && y1 <= rymin) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        if (x0 <= rxmin && xc0 <= rxmin && xc1 <= rxmin && x1 <= rxmin) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        if (x0 >= rxmax && xc0 >= rxmax && xc1 >= rxmax && x1 >= rxmax) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            // Cubic is entirely to the right of the rect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            // and the vertical range of the 4 Y coordinates of the cubic
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
            // overlaps the vertical range of the rect by a non-empty amount
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            // We now judge the crossings solely based on the line segment
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
            // connecting the endpoints of the cubic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            // Note that we may have 0, 1, or 2 crossings as the control
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
            // points may be causing the Y range intersection while the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            // two endpoints are entirely above or below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
            if (y0 < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
                // y-increasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
                if (y0 <= rymin && y1 >  rymin) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
                if (y0 <  rymax && y1 >= rymax) crossings++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
            } else if (y1 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
                // y-decreasing line segment...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
                if (y1 <= rymin && y0 >  rymin) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
                if (y1 <  rymax && y0 >= rymax) crossings--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
        // The intersection of ranges is more complicated
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
        // First do trivial INTERSECTS rejection of the cases
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        // where one of the endpoints is inside the rectangle.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        if ((x0 > rxmin && x0 < rxmax && y0 > rymin && y0 < rymax) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            (x1 > rxmin && x1 < rxmax && y1 > rymin && y1 < rymax))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            return RECT_INTERSECTS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
        // Otherwise, subdivide and look for one of the cases above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        // double precision only has 52 bits of mantissa
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        if (level > 52) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
            return rectCrossingsForLine(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                                        rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                                        x0, y0, x1, y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        double xmid = (xc0 + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        double ymid = (yc0 + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        xc0 = (x0 + xc0) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        yc0 = (y0 + yc0) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
        xc1 = (xc1 + x1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        yc1 = (yc1 + y1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        double xc0m = (xc0 + xmid) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        double yc0m = (yc0 + ymid) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        double xmc1 = (xmid + xc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
        double ymc1 = (ymid + yc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        xmid = (xc0m + xmc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        ymid = (yc0m + ymc1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        if (Double.isNaN(xmid) || Double.isNaN(ymid)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
            // [xy]mid are NaN if any of [xy]c0m or [xy]mc1 are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            // [xy]c0m or [xy]mc1 are NaN if any of [xy][c][01] are NaN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
            // These values are also NaN if opposing infinities are added
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        crossings = rectCrossingsForCubic(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                                          rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                                          x0, y0, xc0, yc0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                                          xc0m, yc0m, xmid, ymid, level+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
        if (crossings != RECT_INTERSECTS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            crossings = rectCrossingsForCubic(crossings,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                                              rxmin, rymin, rxmax, rymax,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                                              xmid, ymid, xmc1, ymc1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                                              xc1, yc1, x1, y1, level+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
        return crossings;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
    public Curve(int direction) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
        this.direction = direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
    public final int getDirection() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
        return direction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
    public final Curve getWithDirection(int direction) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        return (this.direction == direction ? this : getReversedCurve());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
    public static double round(double v) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        //return Math.rint(v*10)/10;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
        return v;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
    public static int orderof(double x1, double x2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
        if (x1 < x2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
        if (x1 > x2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
            return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
    public static long signeddiffbits(double y1, double y2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
        return (Double.doubleToLongBits(y1) - Double.doubleToLongBits(y2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
    public static long diffbits(double y1, double y2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
        return Math.abs(Double.doubleToLongBits(y1) -
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                        Double.doubleToLongBits(y2));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
    public static double prev(double v) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
        return Double.longBitsToDouble(Double.doubleToLongBits(v)-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
    public static double next(double v) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
        return Double.longBitsToDouble(Double.doubleToLongBits(v)+1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
        return ("Curve["+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                getOrder()+", "+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                ("("+round(getX0())+", "+round(getY0())+"), ")+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                controlPointString()+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                ("("+round(getX1())+", "+round(getY1())+"), ")+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                (direction == INCREASING ? "D" : "U")+
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                "]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
    public String controlPointString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        return "";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
    public abstract int getOrder();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
    public abstract double getXTop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
    public abstract double getYTop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
    public abstract double getXBot();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
    public abstract double getYBot();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    public abstract double getXMin();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
    public abstract double getXMax();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
    public abstract double getX0();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
    public abstract double getY0();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
    public abstract double getX1();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
    public abstract double getY1();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
    public abstract double XforY(double y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
    public abstract double TforY(double y);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
    public abstract double XforT(double t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
    public abstract double YforT(double t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
    public abstract double dXforT(double t, int deriv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
    public abstract double dYforT(double t, int deriv);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    public abstract double nextVertical(double t0, double t1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
    public int crossingsFor(double x, double y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
        if (y >= getYTop() && y < getYBot()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
            if (x < getXMax() && (x < getXMin() || x < XforY(y))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
                return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
    public boolean accumulateCrossings(Crossings c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
        double xhi = c.getXHi();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        if (getXMin() >= xhi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
        double xlo = c.getXLo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        double ylo = c.getYLo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
        double yhi = c.getYHi();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        double y0 = getYTop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
        double y1 = getYBot();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        double tstart, ystart, tend, yend;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        if (y0 < ylo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
            if (y1 <= ylo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
            ystart = ylo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
            tstart = TforY(ylo);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
            if (y0 >= yhi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
            ystart = y0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
            tstart = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
        if (y1 > yhi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
            yend = yhi;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
            tend = TforY(yhi);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
            yend = y1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
            tend = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
        boolean hitLo = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
        boolean hitHi = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
        while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
            double x = XforT(tstart);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
            if (x < xhi) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
                if (hitHi || x > xlo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                hitLo = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
                if (hitLo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
                hitHi = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
            if (tstart >= tend) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
            tstart = nextVertical(tstart, tend);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
        if (hitLo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
            c.record(ystart, yend, direction);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
    public abstract void enlarge(Rectangle2D r);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
    public Curve getSubCurve(double ystart, double yend) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
        return getSubCurve(ystart, yend, direction);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
    public abstract Curve getReversedCurve();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
    public abstract Curve getSubCurve(double ystart, double yend, int dir);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
    public int compareTo(Curve that, double yrange[]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
        System.out.println(this+".compareTo("+that+")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
        System.out.println("target range = "+yrange[0]+"=>"+yrange[1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        double y0 = yrange[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
        double y1 = yrange[1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
        y1 = Math.min(Math.min(y1, this.getYBot()), that.getYBot());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        if (y1 <= yrange[0]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
            System.err.println("this == "+this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
            System.err.println("that == "+that);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
            System.out.println("target range = "+yrange[0]+"=>"+yrange[1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
            throw new InternalError("backstepping from "+yrange[0]+" to "+y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        yrange[1] = y1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
        if (this.getXMax() <= that.getXMin()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
            if (this.getXMin() == that.getXMax()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
                return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
        if (this.getXMin() >= that.getXMax()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
            return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
        // Parameter s for thi(s) curve and t for tha(t) curve
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        // [st]0 = parameters for top of current section of interest
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
        // [st]1 = parameters for bottom of valid range
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        // [st]h = parameters for hypothesis point
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
        // [d][xy]s = valuations of thi(s) curve at sh
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        // [d][xy]t = valuations of tha(t) curve at th
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        double s0 = this.TforY(y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        double ys0 = this.YforT(s0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
        if (ys0 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
            s0 = refineTforY(s0, ys0, y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
            ys0 = this.YforT(s0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
        double s1 = this.TforY(y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        if (this.YforT(s1) < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
            s1 = refineTforY(s1, this.YforT(s1), y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
            //System.out.println("s1 problem!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
        double t0 = that.TforY(y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
        double yt0 = that.YforT(t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
        if (yt0 < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
            t0 = that.refineTforY(t0, yt0, y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
            yt0 = that.YforT(t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        double t1 = that.TforY(y1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        if (that.YforT(t1) < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            t1 = that.refineTforY(t1, that.YforT(t1), y0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            //System.out.println("t1 problem!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        double xs0 = this.XforT(s0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
        double xt0 = that.XforT(t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
        double scale = Math.max(Math.abs(y0), Math.abs(y1));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
        double ymin = Math.max(scale * 1E-14, 1E-300);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
        if (fairlyClose(xs0, xt0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
            double bump = ymin;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
            double maxbump = Math.min(ymin * 1E13, (y1 - y0) * .1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
            double y = y0 + bump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
            while (y <= y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
                if (fairlyClose(this.XforY(y), that.XforY(y))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
                    if ((bump *= 2) > maxbump) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
                        bump = maxbump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
                    y -= bump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
                    while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
                        bump /= 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
                        double newy = y + bump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
                        if (newy <= y) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
                        if (fairlyClose(this.XforY(newy), that.XforY(newy))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
                            y = newy;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
                y += bump;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
            if (y > y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
                if (y < y1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
                    yrange[1] = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
                return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
        //double ymin = y1 * 1E-14;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        if (ymin <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            System.out.println("ymin = "+ymin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
        System.out.println("s range = "+s0+" to "+s1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
        System.out.println("t range = "+t0+" to "+t1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
        while (s0 < s1 && t0 < t1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
            double sh = this.nextVertical(s0, s1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
            double xsh = this.XforT(sh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
            double ysh = this.YforT(sh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
            double th = that.nextVertical(t0, t1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
            double xth = that.XforT(th);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
            double yth = that.YforT(th);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
            System.out.println("sh = "+sh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            System.out.println("th = "+th);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
            */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
            if (findIntersect(that, yrange, ymin, 0, 0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
                              s0, xs0, ys0, sh, xsh, ysh,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
                              t0, xt0, yt0, th, xth, yth)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
        } catch (Throwable t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
            System.err.println("Error: "+t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
            System.err.println("y range was "+yrange[0]+"=>"+yrange[1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
            System.err.println("s y range is "+ys0+"=>"+ysh);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
            System.err.println("t y range is "+yt0+"=>"+yth);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
            System.err.println("ymin is "+ymin);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
            if (ysh < yth) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
                if (ysh > yrange[0]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
                    if (ysh < yrange[1]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
                        yrange[1] = ysh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
                s0 = sh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
                xs0 = xsh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
                ys0 = ysh;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
                if (yth > yrange[0]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
                    if (yth < yrange[1]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
                        yrange[1] = yth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
                t0 = th;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
                xt0 = xth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
                yt0 = yth;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
        double ymid = (yrange[0] + yrange[1]) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
        System.out.println("final this["+s0+", "+sh+", "+s1+"]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
        System.out.println("final    y["+ys0+", "+ysh+"]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
        System.out.println("final that["+t0+", "+th+", "+t1+"]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
        System.out.println("final    y["+yt0+", "+yth+"]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
        System.out.println("final order = "+orderof(this.XforY(ymid),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
                                                    that.XforY(ymid)));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
        System.out.println("final range = "+yrange[0]+"=>"+yrange[1]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
        System.out.println("final sx = "+this.XforY(ymid));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
        System.out.println("final tx = "+that.XforY(ymid));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
        System.out.println("final order = "+orderof(this.XforY(ymid),
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
                                                    that.XforY(ymid)));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        return orderof(this.XforY(ymid), that.XforY(ymid));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
    public static final double TMIN = 1E-3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
    public boolean findIntersect(Curve that, double yrange[], double ymin,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
                                 int slevel, int tlevel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
                                 double s0, double xs0, double ys0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
                                 double s1, double xs1, double ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
                                 double t0, double xt0, double yt0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
                                 double t1, double xt1, double yt1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
        String pad = "        ";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
        pad = pad+pad+pad+pad+pad;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
        pad = pad+pad;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
        System.out.println("----------------------------------------------");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
        System.out.println(pad.substring(0, slevel)+ys0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
        System.out.println(pad.substring(0, slevel)+ys1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
        System.out.println(pad.substring(0, slevel)+(s1-s0));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
        System.out.println("-------");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
        System.out.println(pad.substring(0, tlevel)+yt0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
        System.out.println(pad.substring(0, tlevel)+yt1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
        System.out.println(pad.substring(0, tlevel)+(t1-t0));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
        */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
        if (ys0 > yt1 || yt0 > ys1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
        if (Math.min(xs0, xs1) > Math.max(xt0, xt1) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
            Math.max(xs0, xs1) < Math.min(xt0, xt1))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
        // Bounding boxes intersect - back off the larger of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
        // the two subcurves by half until they stop intersecting
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
        // (or until they get small enough to switch to a more
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
        //  intensive algorithm).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
        if (s1 - s0 > TMIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
            double s = (s0 + s1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
            double xs = this.XforT(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
            double ys = this.YforT(s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
            if (s == s0 || s == s1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
                System.out.println("s0 = "+s0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
                System.out.println("s1 = "+s1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
                throw new InternalError("no s progress!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
            if (t1 - t0 > TMIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
                double t = (t0 + t1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
                double xt = that.XforT(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
                double yt = that.YforT(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
                if (t == t0 || t == t1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
                    System.out.println("t0 = "+t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
                    System.out.println("t1 = "+t1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
                    throw new InternalError("no t progress!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
                if (ys >= yt0 && yt >= ys0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
                                      s0, xs0, ys0, s, xs, ys,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
                                      t0, xt0, yt0, t, xt, yt)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
                if (ys >= yt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                                      s0, xs0, ys0, s, xs, ys,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
                                      t, xt, yt, t1, xt1, yt1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
                if (yt >= ys) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
                                      s, xs, ys, s1, xs1, ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
                                      t0, xt0, yt0, t, xt, yt)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
                if (ys1 >= yt && yt1 >= ys) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
                                      s, xs, ys, s1, xs1, ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
                                      t, xt, yt, t1, xt1, yt1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
                if (ys >= yt0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
                                      s0, xs0, ys0, s, xs, ys,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
                                      t0, xt0, yt0, t1, xt1, yt1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
                if (yt1 >= ys) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
                    if (findIntersect(that, yrange, ymin, slevel+1, tlevel,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
                                      s, xs, ys, s1, xs1, ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
                                      t0, xt0, yt0, t1, xt1, yt1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
        } else if (t1 - t0 > TMIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
            double t = (t0 + t1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
            double xt = that.XforT(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
            double yt = that.YforT(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
            if (t == t0 || t == t1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
                System.out.println("t0 = "+t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
                System.out.println("t1 = "+t1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
                throw new InternalError("no t progress!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
            if (yt >= ys0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
                if (findIntersect(that, yrange, ymin, slevel, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
                                  s0, xs0, ys0, s1, xs1, ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
                                  t0, xt0, yt0, t, xt, yt)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
            if (ys1 >= yt) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
                if (findIntersect(that, yrange, ymin, slevel, tlevel+1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
                                  s0, xs0, ys0, s1, xs1, ys1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
                                  t, xt, yt, t1, xt1, yt1)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
            // No more subdivisions
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
            double xlk = xs1 - xs0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
            double ylk = ys1 - ys0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
            double xnm = xt1 - xt0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
            double ynm = yt1 - yt0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
            double xmk = xt0 - xs0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
            double ymk = yt0 - ys0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
            double det = xnm * ylk - ynm * xlk;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
            if (det != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
                double detinv = 1 / det;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
                double s = (xnm * ymk - ynm * xmk) * detinv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
                double t = (xlk * ymk - ylk * xmk) * detinv;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
                if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
                    s = s0 + s * (s1 - s0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
                    t = t0 + t * (t1 - t0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
                    if (s < 0 || s > 1 || t < 0 || t > 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
                        System.out.println("Uh oh!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
                    double y = (this.YforT(s) + that.YforT(t)) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
                    if (y <= yrange[1] && y > yrange[0]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
                        yrange[1] = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
            //System.out.println("Testing lines!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
    public double refineTforY(double t0, double yt0, double y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
        double t1 = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
        while (true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
            double th = (t0 + t1) / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
            if (th == t0 || th == t1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
                return t1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
            double y = YforT(th);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
            if (y < y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
                t0 = th;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
                yt0 = y;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
            } else if (y > y0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
                t1 = th;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
                return t1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
    public boolean fairlyClose(double v1, double v2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
        return (Math.abs(v1 - v2) <
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
                Math.max(Math.abs(v1), Math.abs(v2)) * 1E-10);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
    public abstract int getSegment(double coords[]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
}