Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / impl / DrawGeneralPathXIterator.java @ 40435

History | View | Annotate | Download (5.96 KB)

1
/* gvSIG. Desktop Geographic Information System.
2
 *
3
 * Copyright ? 2007-${year} gvSIG Association
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
 * MA  02110-1301, USA.
19
 *
20
 * For any additional information, do not hesitate to contact us
21
 * at info AT gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.geom.impl;
24

    
25
import java.awt.geom.AffineTransform;
26
import java.awt.geom.PathIterator;
27

    
28
import org.gvsig.fmap.geom.primitive.GeneralPathX;
29
import org.gvsig.fmap.geom.primitive.Point;
30

    
31
/**
32
 * AWT {@link PathIterator} to draw a {@link GeneralPathX} object.
33
 * 
34
 * While iterating the {@link GeneralPathX) each point coordinates are 
35
 * converted to int. If a segment is a PathIterator#SEG_LINETO and the 
36
 * integer coordinates are the same as the previous point ones, the point 
37
 * is ignored and the next one is looked for.
38
 * 
39
 * @author gvSIG Team
40
 */
41
public class DrawGeneralPathXIterator implements PathIterator {
42

    
43
    protected int typeIdx = -1;
44
    protected int pointIdx = 0;
45
    protected GeneralPathX path;
46
    protected AffineTransform affine;
47

    
48
    /**
49
     * This array keeps the "real" coordinates (double precision) which
50
     * will afterwards be rounded to int. It is final and created with
51
     * its maximum possible size. This does not have a performance cost
52
     * because only relevant indices are read/written (also when applying
53
     * an affine transformation)
54
     */
55
    private final double[] currentPointRealCoords = new double[] { 0, 0, 0, 0, 0, 0 };
56
    
57
    /**
58
     * This array keeps the rounded (int) coordinates.
59
     * It is final and created with
60
     * its maximum possible size. This does not have a performance cost
61
     * because only relevant indices are read/written.
62
     */
63
    private final int[] currentPointCoords = new int[] { 0, 0, 0, 0, 0, 0 };
64
    
65
    private final int[] previousPointCoords = new int[] { 0, 0 };
66

    
67
    private int currentType = -1;
68
    private int previousType = -1;
69

    
70
    private static final int curvesize[] = { 1, 1, 2, 3, 0 };
71

    
72
    private final int numTypes;
73
    private final int numPoints;
74

    
75
    /**
76
     * Constructs an iterator given a GeneralPathX.
77
     * 
78
     * @see GeneralPathX#getPathIterator
79
     */
80
    public DrawGeneralPathXIterator(GeneralPathX path) {
81
        this(path, null);
82
    }
83

    
84
    /**
85
     * Constructs an iterator given a GeneralPathX and an optional
86
     * AffineTransform.
87
     * 
88
     * @see GeneralPathX#getPathIterator
89
     */
90
    public DrawGeneralPathXIterator(GeneralPathX path, AffineTransform at) {
91
        this.path = path;
92
        this.affine = at;
93
        // Go to the first segment
94
        this.pointIdx = 0;
95
        this.numPoints = path.getNumCoords();
96
        this.typeIdx = 0;
97
        this.numTypes = path.getNumTypes();
98
        if (numTypes > 0) {
99
            currentType = path.getTypeAt(typeIdx);
100
            readCurrentSegmentCoordsAsInt();
101
            previousType = currentType;
102
            previousPointCoords[0] = currentPointCoords[0];
103
            previousPointCoords[1] = currentPointCoords[1];
104
        }
105
    }
106

    
107
    public int getWindingRule() {
108
        return path.getWindingRule();
109
    }
110

    
111
    public boolean isDone() {
112
        return typeIdx >= numTypes;
113
    }
114

    
115
    public void next() {
116
        do {
117
            typeIdx++;
118
            pointIdx += curvesize[currentType];
119
            if (typeIdx < numTypes) {
120
                currentType = path.getTypeAt(typeIdx);
121
                if (SEG_CLOSE != currentType) {
122
                    readCurrentSegmentCoordsAsInt();
123
                }
124
            } else {
125
                // We have reached past the last segment
126
                return;
127
            }
128
        } while (isSameSegment());
129

    
130
        previousType = currentType;
131
        previousPointCoords[0] = currentPointCoords[0];
132
        previousPointCoords[1] = currentPointCoords[1];
133
    }
134

    
135
    private final boolean isSameSegment() {
136
        return SEG_LINETO == currentType
137
            && (SEG_LINETO == previousType || SEG_MOVETO == previousType)
138
            && currentPointCoords[0] == previousPointCoords[0]
139
            && currentPointCoords[1] == previousPointCoords[1];
140
    }
141

    
142
    private void readCurrentSegmentCoordsAsInt() {
143
        int currentSize = curvesize[currentType];
144

    
145
        for (int i = 0; i < currentSize; i++) {
146
            readPoint(i * 2, pointIdx + i);
147
        }
148

    
149
        if (affine != null && !affine.isIdentity()) {
150
            affine.transform(currentPointRealCoords, 0, currentPointRealCoords,
151
                0, currentSize);
152
        }
153

    
154
        for (int i = 0; i < currentSize * 2; i++) {
155
            currentPointCoords[i] = (int) currentPointRealCoords[i];
156
        }
157
    }
158

    
159
    private void readPoint(int currentCoordsPos, int currentPointIdx) {
160
        Point point = path.getPointAt(currentPointIdx);
161
        currentPointRealCoords[currentCoordsPos] = point.getX();
162
        currentPointRealCoords[currentCoordsPos + 1] = point.getY();
163
    }
164

    
165
    public int currentSegment(float[] coords) {
166
        if (SEG_CLOSE != currentType) {
167
            int size = curvesize[currentType] * 2;
168

    
169
            for (int i = 0; i < size; i++) {
170
                coords[i] = currentPointCoords[i];
171
            }
172
        }
173
        return currentType;
174
    }
175

    
176
    public int currentSegment(double[] coords) {
177
        int size = curvesize[currentType] * 2;
178

    
179
        for (int i = 0; i < size; i++) {
180
            coords[i] = currentPointCoords[i];
181
        }
182
        return currentType;
183
    }
184
}