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 @ 40559

History | View | Annotate | Download (8.39 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
/* gvSIG. Geographic Information System of the Valencian Government
25
*
26
* Copyright (C) 2007-2008 Infrastructures and Transports Department
27
* of the Valencian Government (CIT)
28
* 
29
* This program is free software; you can redistribute it and/or
30
* modify it under the terms of the GNU General Public License
31
* as published by the Free Software Foundation; either version 2
32
* of the License, or (at your option) any later version.
33
* 
34
* This program is distributed in the hope that it will be useful,
35
* but WITHOUT ANY WARRANTY; without even the implied warranty of
36
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
* GNU General Public License for more details.
38
* 
39
* You should have received a copy of the GNU General Public License
40
* along with this program; if not, write to the Free Software
41
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
42
* MA  02110-1301, USA.
43
* 
44
*/
45

    
46
/*
47
* AUTHORS (In addition to CIT):
48
* 2008 PRODEVELOP S.L. Main Development
49
*/
50
 
51
package org.gvsig.fmap.geom.operation.ensureOrientation;
52

    
53
import com.vividsolutions.jts.algorithm.CGAlgorithms;
54
import com.vividsolutions.jts.geom.Coordinate;
55
import com.vividsolutions.jts.geom.CoordinateList;
56
import com.vividsolutions.jts.geom.CoordinateSequences;
57
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
58

    
59
import org.gvsig.fmap.geom.Geometry;
60
import org.gvsig.fmap.geom.GeometryLocator;
61
import org.gvsig.fmap.geom.operation.GeometryOperation;
62
import org.gvsig.fmap.geom.operation.GeometryOperationContext;
63
import org.gvsig.fmap.geom.operation.GeometryOperationException;
64
import org.gvsig.fmap.geom.primitive.GeneralPathX;
65

    
66
/**
67
 * Use this function class to ensure you get real polygons or holes
68
 * En JTS, con bCCW = false obtienes un poligono exterior.
69
 * Nota: Solo se le da la vuelta (si es que lo necesita) al
70
 * poligono exterior. El resto, por ahora, no se tocan.
71
 * Si se necesita tenerlos en cuenta, habr?a que mirar
72
 * si est?n dentro del otro, y entonces revisar que tiene
73
 * un CCW contrario al exterior.
74
 * @param bCCW true if you want the GeneralPath in CCW order
75
 * @return true si se le ha dado la vuelta. (true if flipped)
76
 * TODO: TERMINAR ESTO!! NO EST? COMPLETO!! NO sirve para multipoligonos
77
 */
78
/**
79
 * @author Carlos S?nchez Peri??n <a href = "mailto:csanchez@prodevelop.es"> e-mail </a>
80
 */
81
public class EnsureOrientation extends GeometryOperation{
82
    public static final String NAME = "ensureOrientation";
83
        public static final int CODE = GeometryLocator.getGeometryManager().
84
            getGeometryOperationCode(NAME);
85
        
86
        private GeneralPathX generalPathX = null;
87
        
88
        private Boolean bCCW;
89
                
90
        public int getOperationIndex() {
91
                return CODE;
92
        }
93

    
94
        public Object invoke(Geometry geom, GeometryOperationContext ctx)throws GeometryOperationException {
95
                bCCW = (Boolean) ctx.getAttribute("bCCW");
96
                if (bCCW==null)
97
                        throw new GeometryOperationException(new Exception("The function Parameter hasn't been passed or is null."));
98
                
99
                generalPathX = geom.getGeneralPath();
100
                if (generalPathX==null){
101
                        //if there isn't path the operation hasn't sense.
102
                        return null;
103
                }
104
                
105
        byte[] pointTypesAux = new byte[generalPathX.getNumTypes()+1];
106
        double[] pointCoordsAux = new double[(generalPathX.getNumCoords() * 2) + 2];
107
        int i;
108
        int pointIdx = 0;
109

    
110
        Coordinate c1, c2, c3;
111
        CoordinateList coordList = new CoordinateList();
112
        CoordinateList firstList = new CoordinateList();
113
        boolean bFirstList = true;
114
        Coordinate cInicio = null;
115

    
116
        for (i=0; i< generalPathX.getNumTypes(); i++)
117
        {
118
                int type = generalPathX.getTypeAt(i);
119

    
120
                switch (type)
121
                {
122
                case GeneralPathX.SEG_MOVETO:
123
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
124
                        cInicio = c1;
125
                        coordList.add(c1, true);
126
                        if (i>0) bFirstList = false;
127
                        if (bFirstList)
128
                        {
129
                                firstList.add(c1,true);
130
                        }
131
                        break;
132
                case GeneralPathX.SEG_LINETO:
133
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
134
                        coordList.add(c1, true);
135
                        if (bFirstList)
136
                        {
137
                                firstList.add(c1,true);
138
                        }
139
                        break;
140
                case GeneralPathX.SEG_QUADTO:
141
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
142
                        coordList.add(c1, true);
143
                        c2= new Coordinate(generalPathX.getPointAt(pointIdx+1).getX(),generalPathX.getPointAt(pointIdx+1).getY());
144
                        coordList.add(c2, true);
145
                        if (bFirstList)
146
                        {
147
                                firstList.add(c1,true);
148
                                firstList.add(c2,true);
149
                        }
150

    
151
                        break;
152
                case GeneralPathX.SEG_CUBICTO:
153
                        c1= new Coordinate(generalPathX.getPointAt(pointIdx).getX(), generalPathX.getPointAt(pointIdx).getY());
154
                        coordList.add(c1, true);
155
                        c2= new Coordinate(generalPathX.getPointAt(pointIdx+1).getX(),generalPathX.getPointAt(pointIdx+1).getY());
156
                        coordList.add(c2, true);
157
                        c3= new Coordinate(generalPathX.getPointAt(pointIdx+2).getX(),generalPathX.getPointAt(pointIdx+2).getY());
158
                        coordList.add(c3, true);
159
                        if (bFirstList)
160
                        {
161
                                firstList.add(c1,true);
162
                                firstList.add(c2,true);
163
                                firstList.add(c3,true);
164
                        }
165

    
166
                        break;
167
                case GeneralPathX.SEG_CLOSE:
168
                        coordList.add(cInicio, true);
169
                        if (bFirstList)
170
                        {
171
                                firstList.add(cInicio,true);
172
                        }
173
                        break;
174

    
175
                }
176
                pointIdx += GeneralPathX.curvesize[type];
177
        }
178
                // Guardamos el path dandole la vuelta
179
                Coordinate[] coords = coordList.toCoordinateArray();
180
                boolean bFlipped = false;
181
                if (CGAlgorithms.isCCW(coords) != bCCW.booleanValue()) // Le damos la vuelta
182
                {
183
                        CoordinateArraySequence seq = new CoordinateArraySequence(coords);
184
                        CoordinateSequences.reverse(seq);
185
                        coords = seq.toCoordinateArray();
186

    
187

    
188
                        // En el primer punto metemos un moveto
189
                        pointCoordsAux[0] = coords[0].x;
190
                        pointCoordsAux[1] = coords[0].y;
191
                        pointTypesAux[0] = GeneralPathX.SEG_MOVETO;
192
                        int idx = 2;
193
                        i=0;
194
                        int j=1;
195
                        for (int k=0; k < coords.length; k++)
196
                        {
197
                                pointCoordsAux[idx++] = coords[k].x;
198
                                pointCoordsAux[idx++] = coords[k].y;
199
                        int type = generalPathX.getTypeAt(i++);
200
                        pointIdx += GeneralPathX.curvesize[type];
201
                        switch (type)
202
                        {
203
                        case GeneralPathX.SEG_MOVETO:
204
                                pointTypesAux[j] = GeneralPathX.SEG_LINETO;
205
                                break;
206
                        case GeneralPathX.SEG_LINETO:
207
                                pointTypesAux[j] = GeneralPathX.SEG_LINETO;
208
                                break;
209
                        case GeneralPathX.SEG_QUADTO:
210
                                pointTypesAux[j] = GeneralPathX.SEG_QUADTO;
211
                                break;
212
                        case GeneralPathX.SEG_CUBICTO:
213
                                pointTypesAux[j] = GeneralPathX.SEG_CUBICTO;
214
                                break;
215
                        case GeneralPathX.SEG_CLOSE:
216
                                // TODO: IMPLEMENTAR ESTO!!!
217
                                break;
218

    
219
                        }
220
                        j++;
221

    
222
                        }
223
                        generalPathX.setPointTypes(pointTypesAux);
224
                        generalPathX.setPointCoords(pointCoordsAux);
225
                generalPathX.setNumCoords(generalPathX.getNumCoords()+2);
226
                generalPathX.setNumTypes(generalPathX.getNumTypes()+1);
227
                bFlipped  = true;
228
                }
229
                return new Boolean((boolean) bFlipped);
230
        }
231

    
232
}