001/*
002 * Copyright 1998-2003 Sun Microsystems, Inc.  All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025package sec.sun.awt.geom;
026
027public class Crossings {
028
029    public static final boolean debug = false;
030
031    int limit = 0;
032    double yranges[] = new double[10];
033
034    double xlo, ylo, xhi, yhi;
035
036    public Crossings(double xlo, double ylo, double xhi, double yhi) {
037        this.xlo = xlo;
038        this.ylo = ylo;
039        this.xhi = xhi;
040        this.yhi = yhi;
041    }
042
043    public final double getXLo() {
044        return xlo;
045    }
046
047    public final double getYLo() {
048        return ylo;
049    }
050
051    public final double getXHi() {
052        return xhi;
053    }
054
055    public final double getYHi() {
056        return yhi;
057    }
058
059    public final boolean isEmpty() {
060        return (limit == 0);
061    }
062
063    public boolean accumulateLine(double x0, double y0,
064            double x1, double y1) {
065        if (y0 <= y1) {
066            return accumulateLine2(x0, y0, x1, y1, 1);
067        } else {
068            return accumulateLine2(x1, y1, x0, y0, -1);
069        }
070    }
071
072    public boolean accumulateLine2(double x0, double y0,
073            double x1, double y1,
074            int direction) {
075        if (yhi <= y0 || ylo >= y1) {
076            return false;
077        }
078        if (x0 >= xhi && x1 >= xhi) {
079            return false;
080        }
081        if (y0 == y1) {
082            return (x0 >= xlo || x1 >= xlo);
083        }
084        double xstart, ystart, xend, yend;
085        double dx = (x1 - x0);
086        double dy = (y1 - y0);
087        if (y0 < ylo) {
088            xstart = x0 + (ylo - y0) * dx / dy;
089            ystart = ylo;
090        } else {
091            xstart = x0;
092            ystart = y0;
093        }
094        if (yhi < y1) {
095            xend = x0 + (yhi - y0) * dx / dy;
096            yend = yhi;
097        } else {
098            xend = x1;
099            yend = y1;
100        }
101        if (xstart >= xhi && xend >= xhi) {
102            return false;
103        }
104        if (xstart > xlo || xend > xlo) {
105            return true;
106        }
107        record(ystart, yend, direction);
108        return false;
109    }
110
111    public void record(double ystart, double yend, int direction) {
112        if (ystart >= yend) {
113            return;
114        }
115        int from = 0;
116        // Quickly jump over all pairs that are completely "above"
117        while (from < limit && ystart > yranges[from + 1]) {
118            from += 2;
119        }
120        int to = from;
121        while (from < limit) {
122            double yrlo = yranges[from++];
123            double yrhi = yranges[from++];
124            if (yend < yrlo) {
125                // Quickly handle insertion of the new range
126                yranges[to++] = ystart;
127                yranges[to++] = yend;
128                ystart = yrlo;
129                yend = yrhi;
130                continue;
131            }
132            // The ranges overlap - sort, collapse, insert, iterate
133            double yll, ylh, yhl, yhh;
134            if (ystart < yrlo) {
135                yll = ystart;
136                ylh = yrlo;
137            } else {
138                yll = yrlo;
139                ylh = ystart;
140            }
141            if (yend < yrhi) {
142                yhl = yend;
143                yhh = yrhi;
144            } else {
145                yhl = yrhi;
146                yhh = yend;
147            }
148            if (ylh == yhl) {
149                ystart = yll;
150                yend = yhh;
151            } else {
152                if (ylh > yhl) {
153                    ystart = yhl;
154                    yhl = ylh;
155                    ylh = ystart;
156                }
157                if (yll != ylh) {
158                    yranges[to++] = yll;
159                    yranges[to++] = ylh;
160                }
161                ystart = yhl;
162                yend = yhh;
163            }
164            if (ystart >= yend) {
165                break;
166            }
167        }
168        if (to < from && from < limit) {
169            System.arraycopy(yranges, from, yranges, to, limit - from);
170        }
171        to += (limit - from);
172        if (ystart < yend) {
173            if (to >= yranges.length) {
174                double newranges[] = new double[to + 10];
175                System.arraycopy(yranges, 0, newranges, 0, to);
176                yranges = newranges;
177            }
178            yranges[to++] = ystart;
179            yranges[to++] = yend;
180        }
181        limit = to;
182    }
183}