001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package sec.sun.awt.geom;
006
007import armyc2.c2sd.graphics2d.PathIterator;
008
009/**
010 *
011 * @author Michael Deutch
012 */
013public class CrossingsObject {
014
015    public static final int CROSSINGS = 0;
016    public static final int NONZERO = 1;
017    public static final int EVENODD = 2;
018    public static final boolean debug = false;
019    int limit = 0;
020    double yranges[] = new double[10];
021    double xlo, ylo, xhi, yhi;
022    private int crosscounts[] = null;
023
024    private EvenOdd evenOdd = null;
025    private Crossings crossings = null;
026    private NonZero nonZero = null;
027    int type = -1;
028
029    public CrossingsObject(double xlo, double ylo, double xhi, double yhi, int type) {
030        //super(xlo, ylo, xhi, yhi);
031        this.xlo = xlo;
032        this.ylo = ylo;
033        this.xhi = xhi;
034        this.yhi = yhi;
035        this.type = type;
036        //crosscounts = new int[yranges.length / 2];
037        switch (type) {
038            case CROSSINGS:
039                crossings = new Crossings(xlo, ylo, xhi, yhi);
040                break;
041            case NONZERO:
042                nonZero = new NonZero(xlo, ylo, xhi, yhi);
043                crosscounts = new int[yranges.length / 2];
044                break;
045            case EVENODD:
046                evenOdd = new EvenOdd(xlo, ylo, xhi, yhi);
047                break;
048        }
049    }
050
051    public double getXLo() {
052        switch (type) {
053            case CROSSINGS:
054                return crossings.getXLo();
055            case EVENODD:
056                return evenOdd.getXLo();
057            case NONZERO:
058                return nonZero.getXLo();
059            default:
060                return -1;
061        }
062    }
063
064    public double getYLo() {
065        switch (type) {
066            case CROSSINGS:
067                return crossings.getYLo();
068            case EVENODD:
069                return evenOdd.getYLo();
070            case NONZERO:
071                return nonZero.getYLo();
072            default:
073                return -1;
074        }
075    }
076
077    public double getXHi() {
078        //return xhi;
079        switch (type) {
080            case CROSSINGS:
081                return crossings.getXHi();
082            case EVENODD:
083                return evenOdd.getXHi();
084            case NONZERO:
085                return nonZero.getXHi();
086            default:
087                return -1;
088        }
089    }
090
091    public double getYHi() {
092        //return yhi;
093        switch (type) {
094            case CROSSINGS:
095                return crossings.getYHi();
096            case EVENODD:
097                return evenOdd.getYHi();
098            case NONZERO:
099                return nonZero.getYHi();
100            default:
101                return -1;
102        }
103    }
104
105    public boolean isEmpty() {
106        //return (limit == 0);
107        switch (type) {
108            case CROSSINGS:
109                return crossings.isEmpty();
110            case EVENODD:
111                return evenOdd.isEmpty();
112            case NONZERO:
113                return nonZero.isEmpty();
114            default:
115                return true;
116        }
117    }
118
119    public void record(double ystart, double yend, int direction) {
120        switch (type) {
121            case CROSSINGS:
122                crossings.record(ystart, yend, direction);
123            case EVENODD:
124                evenOdd.record(ystart, yend, direction);
125            case NONZERO:
126                nonZero.record(ystart, yend, direction);
127            default:
128                return;
129        }
130
131    }
132
133    public static CrossingsObject findCrossings(Vector curves,
134            double xlo, double ylo,
135            double xhi, double yhi) {
136        //Crossings cross = new EvenOdd(xlo, ylo, xhi, yhi);
137        CrossingsObject cross = new CrossingsObject(xlo, ylo, xhi, yhi, CrossingsObject.EVENODD);
138        Enumeration enum_ = curves.elements();
139        while (enum_.hasMoreElements()) {
140            CurveObject c = (CurveObject) enum_.nextElement();
141            if (c.accumulateCrossings(cross)) {
142                return null;
143            }
144        }
145        return cross;
146    }
147
148    public CrossingsObject findCrossings2(PathIterator pi,
149            double xlo, double ylo,
150            double xhi, double yhi) {
151        CrossingsObject cross;
152        if (pi.getWindingRule() == pi.WIND_EVEN_ODD) {
153            cross = new CrossingsObject(xlo, ylo, xhi, yhi, EVENODD);
154        } else {
155            cross = new CrossingsObject(xlo, ylo, xhi, yhi, NONZERO);
156        }
157        // coords array is big enough for holding:
158        //     coordinates returned from currentSegment (6)
159        //     OR
160        //         two subdivided quadratic curves (2+4+4=10)
161        //         AND
162        //             0-1 horizontal splitting parameters
163        //             OR
164        //             2 parametric equation derivative coefficients
165        //     OR
166        //         three subdivided cubic curves (2+6+6+6=20)
167        //         AND
168        //             0-2 horizontal splitting parameters
169        //             OR
170        //             3 parametric equation derivative coefficients
171        double coords[] = new double[23];
172        double movx = 0;
173        double movy = 0;
174        double curx = 0;
175        double cury = 0;
176        double newx, newy;
177        while (!pi.isDone()) {
178            int type = pi.currentSegment(coords);
179            switch (type) {
180                case PathIterator.SEG_MOVETO:
181                    if (movy != cury
182                            && cross.accumulateLine(curx, cury, movx, movy)) {
183                        return null;
184                    }
185                    movx = curx = coords[0];
186                    movy = cury = coords[1];
187                    break;
188                case PathIterator.SEG_LINETO:
189                    newx = coords[0];
190                    newy = coords[1];
191                    if (cross.accumulateLine(curx, cury, newx, newy)) {
192                        return null;
193                    }
194                    curx = newx;
195                    cury = newy;
196                    break;
197                case PathIterator.SEG_QUADTO:
198                    newx = coords[2];
199                    newy = coords[3];
200                    if (cross.accumulateQuad(curx, cury, coords)) {
201                        return null;
202                    }
203                    curx = newx;
204                    cury = newy;
205                    break;
206                case PathIterator.SEG_CUBICTO:
207                    newx = coords[4];
208                    newy = coords[5];
209                    if (cross.accumulateCubic(curx, cury, coords)) {
210                        return null;
211                    }
212                    curx = newx;
213                    cury = newy;
214                    break;
215                case PathIterator.SEG_CLOSE:
216                    if (movy != cury
217                            && cross.accumulateLine(curx, cury, movx, movy)) {
218                        return null;
219                    }
220                    curx = movx;
221                    cury = movy;
222                    break;
223            }
224            pi.next();
225        }
226        if (movy != cury) {
227            if (cross.accumulateLine(curx, cury, movx, movy)) {
228                return null;
229            }
230        }
231        return cross;
232    }
233
234    public boolean accumulateLine(double x0, double y0,
235            double x1, double y1) {
236        switch (this.type) {
237            case CROSSINGS:
238                return crossings.accumulateLine(x0, y0, x1, y1);
239            case EVENODD:
240                return evenOdd.accumulateLine(x0, y0, x1, y1);
241            case NONZERO:
242                return nonZero.accumulateLine(x0, y0, x1, y1);
243            default:
244                return false;
245        }
246    }
247
248    public boolean accumulateLine2(double x0, double y0,
249            double x1, double y1,
250            int direction) {
251        switch (this.type) {
252            case CROSSINGS:
253                return crossings.accumulateLine2(x0, y0, x1, y1, direction);
254            case EVENODD:
255                return evenOdd.accumulateLine2(x0, y0, x1, y1, direction);
256            case NONZERO:
257                return nonZero.accumulateLine2(x0, y0, x1, y1, direction);
258            default:
259                return false;
260        }
261
262    }
263
264    private Vector tmp = new Vector();
265
266    public boolean accumulateQuad(double x0, double y0, double coords[]) {
267        if (y0 < ylo && coords[1] < ylo && coords[3] < ylo) {
268            return false;
269        }
270        if (y0 > yhi && coords[1] > yhi && coords[3] > yhi) {
271            return false;
272        }
273        if (x0 > xhi && coords[0] > xhi && coords[2] > xhi) {
274            return false;
275        }
276        if (x0 < xlo && coords[0] < xlo && coords[2] < xlo) {
277            if (y0 < coords[3]) {
278                record(Math.max(y0, ylo), Math.min(coords[3], yhi), 1);
279            } else if (y0 > coords[3]) {
280                record(Math.max(coords[3], ylo), Math.min(y0, yhi), -1);
281            }
282            return false;
283        }
284        Curve.insertQuad(tmp, x0, y0, coords);
285        Enumeration enum_ = tmp.elements();
286        while (enum_.hasMoreElements()) {
287            CurveObject c = (CurveObject) enum_.nextElement();
288            if (c.accumulateCrossings(this)) {
289                return true;
290            }
291        }
292        tmp.clear();
293        return false;
294    }
295
296    public boolean accumulateCubic(double x0, double y0, double coords[]) {
297        if (y0 < ylo && coords[1] < ylo
298                && coords[3] < ylo && coords[5] < ylo) {
299            return false;
300        }
301        if (y0 > yhi && coords[1] > yhi
302                && coords[3] > yhi && coords[5] > yhi) {
303            return false;
304        }
305        if (x0 > xhi && coords[0] > xhi
306                && coords[2] > xhi && coords[4] > xhi) {
307            return false;
308        }
309        if (x0 < xlo && coords[0] < xlo
310                && coords[2] < xlo && coords[4] < xlo) {
311            if (y0 <= coords[5]) {
312                record(Math.max(y0, ylo), Math.min(coords[5], yhi), 1);
313            } else {
314                record(Math.max(coords[5], ylo), Math.min(y0, yhi), -1);
315            }
316            return false;
317        }
318        Curve.insertCubic(tmp, x0, y0, coords);
319        Enumeration enum_ = tmp.elements();
320        while (enum_.hasMoreElements()) {
321            CurveObject c = (CurveObject) enum_.nextElement();
322            if (c.accumulateCrossings(this)) {
323                return true;
324            }
325        }
326        tmp.clear();
327        return false;
328    }
329}