Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.operation / src / main / java / org / gvsig / fmap / geom / operation / ensureOrientation / EnsureOrientation.java @ 40767

History | View | Annotate | Download (7.42 KB)

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

    
27
import com.vividsolutions.jts.algorithm.CGAlgorithms;
28
import com.vividsolutions.jts.geom.Coordinate;
29
import com.vividsolutions.jts.geom.CoordinateList;
30
import com.vividsolutions.jts.geom.CoordinateSequences;
31
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
32

    
33
import org.gvsig.fmap.geom.Geometry;
34
import org.gvsig.fmap.geom.GeometryLocator;
35
import org.gvsig.fmap.geom.operation.GeometryOperation;
36
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
37
import org.gvsig.fmap.geom.operation.GeometryOperationException;
38
import org.gvsig.fmap.geom.primitive.GeneralPathX;
39

    
40
/**
41
 * Use this function class to ensure you get real polygons or holes
42
 * En JTS, con bCCW = false obtienes un poligono exterior.
43
 * Nota: Solo se le da la vuelta (si es que lo necesita) al
44
 * poligono exterior. El resto, por ahora, no se tocan.
45
 * Si se necesita tenerlos en cuenta, habr?a que mirar
46
 * si est?n dentro del otro, y entonces revisar que tiene
47
 * un CCW contrario al exterior.
48
 * @param bCCW true if you want the GeneralPath in CCW order
49
 * @return true si se le ha dado la vuelta. (true if flipped)
50
 * TODO: TERMINAR ESTO!! NO EST? COMPLETO!! NO sirve para multipoligonos
51
 */
52
/**
53
 * @author Carlos S?nchez Peri??n <a href = "mailto:csanchez@prodevelop.es"> e-mail </a>
54
 */
55
public class EnsureOrientation extends GeometryOperation{
56
    public static final String NAME = "ensureOrientation";
57
        public static final int CODE = GeometryLocator.getGeometryManager().
58
            getGeometryOperationCode(NAME);
59
        
60
        private GeneralPathX generalPathX = null;
61
        
62
        private Boolean bCCW;
63
                
64
        public int getOperationIndex() {
65
                return CODE;
66
        }
67

    
68
        public Object invoke(Geometry geom, GeometryOperationContext ctx)throws GeometryOperationException {
69
                bCCW = (Boolean) ctx.getAttribute("bCCW");
70
                if (bCCW==null)
71
                        throw new GeometryOperationException(new Exception("The function Parameter hasn't been passed or is null."));
72
                
73
                generalPathX = geom.getGeneralPath();
74
                if (generalPathX==null){
75
                        //if there isn't path the operation hasn't sense.
76
                        return null;
77
                }
78
                
79
        byte[] pointTypesAux = new byte[generalPathX.getNumTypes()+1];
80
        double[] pointCoordsAux = new double[(generalPathX.getNumCoords() * 2) + 2];
81
        int i;
82
        int pointIdx = 0;
83

    
84
        Coordinate c1, c2, c3;
85
        CoordinateList coordList = new CoordinateList();
86
        CoordinateList firstList = new CoordinateList();
87
        boolean bFirstList = true;
88
        Coordinate cInicio = null;
89

    
90
        for (i=0; i< generalPathX.getNumTypes(); i++)
91
        {
92
                int type = generalPathX.getTypeAt(i);
93

    
94
                switch (type)
95
                {
96
                case GeneralPathX.SEG_MOVETO:
97
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
98
                        cInicio = c1;
99
                        coordList.add(c1, true);
100
                        if (i>0) bFirstList = false;
101
                        if (bFirstList)
102
                        {
103
                                firstList.add(c1,true);
104
                        }
105
                        break;
106
                case GeneralPathX.SEG_LINETO:
107
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
108
                        coordList.add(c1, true);
109
                        if (bFirstList)
110
                        {
111
                                firstList.add(c1,true);
112
                        }
113
                        break;
114
                case GeneralPathX.SEG_QUADTO:
115
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
116
                        coordList.add(c1, true);
117
                        c2= new Coordinate(generalPathX.getPointAt(pointIdx+1).getX(),generalPathX.getPointAt(pointIdx+1).getY());
118
                        coordList.add(c2, true);
119
                        if (bFirstList)
120
                        {
121
                                firstList.add(c1,true);
122
                                firstList.add(c2,true);
123
                        }
124

    
125
                        break;
126
                case GeneralPathX.SEG_CUBICTO:
127
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
128
                        coordList.add(c1, true);
129
                        c2= new Coordinate(generalPathX.getPointAt(pointIdx+1).getX(),generalPathX.getPointAt(pointIdx+1).getY());
130
                        coordList.add(c2, true);
131
                        c3= new Coordinate(generalPathX.getPointAt(pointIdx+2).getX(),generalPathX.getPointAt(pointIdx+2).getY());
132
                        coordList.add(c3, true);
133
                        if (bFirstList)
134
                        {
135
                                firstList.add(c1,true);
136
                                firstList.add(c2,true);
137
                                firstList.add(c3,true);
138
                        }
139

    
140
                        break;
141
                case GeneralPathX.SEG_CLOSE:
142
                        coordList.add(cInicio, true);
143
                        if (bFirstList)
144
                        {
145
                                firstList.add(cInicio,true);
146
                        }
147
                        break;
148

    
149
                }
150
                pointIdx += GeneralPathX.curvesize[type];
151
        }
152
                // Guardamos el path dandole la vuelta
153
                Coordinate[] coords = coordList.toCoordinateArray();
154
                boolean bFlipped = false;
155
                if (CGAlgorithms.isCCW(coords) != bCCW.booleanValue()) // Le damos la vuelta
156
                {
157
                        CoordinateArraySequence seq = new CoordinateArraySequence(coords);
158
                        CoordinateSequences.reverse(seq);
159
                        coords = seq.toCoordinateArray();
160

    
161

    
162
                        // En el primer punto metemos un moveto
163
                        pointCoordsAux[0] = coords[0].x;
164
                        pointCoordsAux[1] = coords[0].y;
165
                        pointTypesAux[0] = GeneralPathX.SEG_MOVETO;
166
                        int idx = 2;
167
                        i=0;
168
                        int j=1;
169
                        for (int k=0; k < coords.length; k++)
170
                        {
171
                                pointCoordsAux[idx++] = coords[k].x;
172
                                pointCoordsAux[idx++] = coords[k].y;
173
                        int type = generalPathX.getTypeAt(i++);
174
                        pointIdx += GeneralPathX.curvesize[type];
175
                        switch (type)
176
                        {
177
                        case GeneralPathX.SEG_MOVETO:
178
                                pointTypesAux[j] = GeneralPathX.SEG_LINETO;
179
                                break;
180
                        case GeneralPathX.SEG_LINETO:
181
                                pointTypesAux[j] = GeneralPathX.SEG_LINETO;
182
                                break;
183
                        case GeneralPathX.SEG_QUADTO:
184
                                pointTypesAux[j] = GeneralPathX.SEG_QUADTO;
185
                                break;
186
                        case GeneralPathX.SEG_CUBICTO:
187
                                pointTypesAux[j] = GeneralPathX.SEG_CUBICTO;
188
                                break;
189
                        case GeneralPathX.SEG_CLOSE:
190
                                // TODO: IMPLEMENTAR ESTO!!!
191
                                break;
192

    
193
                        }
194
                        j++;
195

    
196
                        }
197
                        generalPathX.setPointTypes(pointTypesAux);
198
                        generalPathX.setPointCoords(pointCoordsAux);
199
                generalPathX.setNumCoords(generalPathX.getNumCoords()+2);
200
                generalPathX.setNumTypes(generalPathX.getNumTypes()+1);
201
                bFlipped  = true;
202
                }
203
                return new Boolean((boolean) bFlipped);
204
        }
205

    
206
}