Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / operation / towkb / OGCWKBEncoder.java @ 47432

History | View | Annotate | Download (14.3 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
package org.gvsig.fmap.geom.jts.operation.towkb;
25

    
26
import java.io.ByteArrayOutputStream;
27
import java.io.DataOutputStream;
28
import java.io.IOException;
29
import org.apache.commons.io.EndianUtils;
30
import org.gvsig.fmap.geom.Geometry;
31
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
32
import org.gvsig.fmap.geom.Geometry.TYPES;
33
import org.gvsig.fmap.geom.GeometryException;
34
import org.gvsig.fmap.geom.aggregate.Aggregate;
35
import org.gvsig.fmap.geom.aggregate.MultiLine;
36
import org.gvsig.fmap.geom.aggregate.MultiPoint;
37
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
38
import org.gvsig.fmap.geom.primitive.Line;
39
import org.gvsig.fmap.geom.primitive.Point;
40
import org.gvsig.fmap.geom.primitive.Polygon;
41
import org.gvsig.fmap.geom.primitive.Ring;
42
import org.gvsig.fmap.geom.type.GeometryType;
43
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
44

    
45
public class OGCWKBEncoder {
46

    
47
    public interface wkbGeometryType {
48

    
49
        public final static int wkbPoint = 1;
50
        public final static int wkbLineString = 2;
51
        public final static int wkbPolygon = 3;
52
        public final static int wkbTriangle = 17;
53
        public final static int wkbMultiPoint = 4;
54
        public final static int wkbMultiLineString = 5;
55
        public final static int wkbMultiPolygon = 6;
56
        public final static int wkbGeometryCollection = 7;
57
        public final static int wkbPolyhedralSurface = 15;
58
        public final static int wkbTIN = 16;
59

    
60
        public final static int wkbPointZ = 1001;
61
        public final static int wkbLineStringZ = 1002;
62
        public final static int wkbPolygonZ = 1003;
63
        public final static int wkbTrianglez = 1017;
64
        public final static int wkbMultiPointZ = 1004;
65
        public final static int wkbMultiLineStringZ = 1005;
66
        public final static int wkbMultiPolygonZ = 1006;
67
        public final static int wkbGeometryCollectionZ = 1007;
68
        public final static int wkbPolyhedralSurfaceZ = 1015;
69
        public final static int wkbTINZ = 1016;
70

    
71
        public final static int wkbPointM = 2001;
72
        public final static int wkbLineStringM = 2002;
73
        public final static int wkbPolygonM = 2003;
74
        public final static int wkbTriangleM = 2017;
75
        public final static int wkbMultiPointM = 2004;
76
        public final static int wkbMultiLineStringM = 2005;
77
        public final static int wkbMultiPolygonM = 2006;
78
        public final static int wkbGeometryCollectionM = 2007;
79
        public final static int wkbPolyhedralSurfaceM = 2015;
80
        public final static int wkbTINM = 2016;
81

    
82
        public final static int wkbPointZM = 3001;
83
        public final static int wkbLineStringZM = 3002;
84
        public final static int wkbPolygonZM = 3003;
85
        public final static int wkbTriangleZM = 3017;
86
        public final static int wkbMultiPointZM = 3004;
87
        public final static int wkbMultiLineStringZM = 3005;
88
        public final static int wkbMultiPolygonZM = 3006;
89
        public final static int wkbGeometryCollectionZM = 3007;
90
        public final static int wkbPolyhedralSurfaceZM = 3015;
91
        public final static int wkbTinZM = 3016;
92

    
93
        public final static int wkb_baseToZ = wkbPointZ - wkbPoint;
94
        public final static int wkb_baseToM = wkbPointM - wkbPoint;
95
        public final static int wkb_baseToZM = wkbPointZM - wkbPoint;
96
    }
97

    
98
    public interface wkbByteOrder {
99

    
100
        public final static byte wkbXDR = 0;                // Big Endian
101
        public final static byte wkbNDR = 1;                // Little Endian
102
    }
103

    
104
    private int byteOrder;
105

    
106
    public OGCWKBEncoder() {
107
        this(wkbByteOrder.wkbXDR);
108
    }
109

    
110
    public OGCWKBEncoder(int byteOrder) {
111
        this.byteOrder = byteOrder;
112
    }
113

    
114
    public byte[] encode(Geometry geometry)
115
            throws GeometryTypeNotSupportedException,
116
            WKBEncodingException,
117
            IOException {
118
        ByteArrayOutputStream stream;
119

    
120
        if (geometry.getType() == TYPES.POINT) {
121
            stream = new ByteArrayOutputStream(50);
122
        } else {
123
            stream = new ByteArrayOutputStream(512);
124
        }
125

    
126
        encode(geometry, stream);
127
        return stream.toByteArray();
128

    
129
    }
130

    
131
    public void encode(Geometry geometry, ByteArrayOutputStream stream)
132
            throws GeometryTypeNotSupportedException, WKBEncodingException,
133
            IOException {
134
        encode(geometry, new DataOutputStream(stream));
135
    }
136

    
137
    public void encode(Geometry geometry, DataOutputStream stream)
138
            throws GeometryTypeNotSupportedException,
139
            WKBEncodingException,
140
            IOException {
141
        if (geometry.getGeometryType().isTypeOf(TYPES.POINT)) {
142
            encodePoint(geometry, stream);
143

    
144
        } else if (geometry.getGeometryType().isTypeOf(TYPES.LINE)) {
145
            encodeLineString((Line)geometry, stream);
146
        } else if (geometry.getGeometryType().isTypeOf(TYPES.CURVE)) {
147
            try {
148
                MultiLine lines = geometry.toLines();
149
                if(lines.getPrimitivesNumber() == 1){
150
                    encodeLineString((Line) lines.getPrimitiveAt(0), stream);
151
                } else {
152
                    encodeMultiLineString(lines, stream);
153
                }
154
            } catch (GeometryException ex) {
155
                throw new WKBEncodingException(ex);
156
            }
157

    
158
        } else if (geometry.getGeometryType().isTypeOf(TYPES.POLYGON)) {
159
            encodePolygon((Polygon) geometry, stream);
160
        } else if (geometry.getGeometryType().isTypeOf(TYPES.SURFACE)) {
161
            try {
162
                MultiPolygon pols = geometry.toPolygons();
163
                if(pols.getPrimitivesNumber() == 1){
164
                    encodePolygon((Polygon) pols.getPrimitiveAt(0), stream);
165
                } else {
166
                    encodeMultiPolygon(pols, stream);
167
                }
168
            } catch (GeometryException ex) {
169
                throw new WKBEncodingException(ex);
170
            }
171

    
172
        } else if (geometry.getGeometryType().isTypeOf(TYPES.AGGREGATE)) {
173
            switch (geometry.getType()) {
174
                case TYPES.MULTIPOINT:
175
                    encodeMultiPoint(geometry, stream);
176
                    break;
177
                case TYPES.MULTICURVE:
178
                    try {
179
                        encodeMultiLineString(geometry.toLines(), stream);
180
                    } catch (GeometryException ex) {
181
                        throw new WKBEncodingException(ex);
182
                    }
183
                    break;
184
                case TYPES.MULTILINE:
185
                    encodeMultiLineString((MultiLine) geometry, stream);
186
                    break;
187

    
188
                case TYPES.MULTISURFACE:
189
                    try {
190
                        encodeMultiPolygon(geometry.toPolygons(), stream);
191
                    } catch (GeometryException ex) {
192
                        throw new WKBEncodingException(ex);
193
                    }
194
                    break;
195
                case TYPES.MULTIPOLYGON:
196
                    encodeMultiPolygon((MultiPolygon) geometry, stream);
197
                    break;
198

    
199
                case TYPES.AGGREGATE:
200
                    encodeCollection(geometry, stream);
201
                    break;
202
            }
203

    
204
        } else {
205
            throw new GeometryTypeNotSupportedException(geometry.getType(),
206
                    geometry.getGeometryType().getSubType());
207
        }
208
//
209
//            // FIXME geom.subtype != SUBTYPES.GEOM2D NOT SUPPORTED !!!!
210
//            if (geometry.getGeometryType().getSubType() != SUBTYPES.GEOM2D) {
211
//                throw new GeometryTypeNotSupportedException(geometry.getType(),
212
//                        geometry.getGeometryType().getSubType());
213
//            }
214
    }
215

    
216
    private void encodeCollection(Geometry geometry, DataOutputStream stream)
217
            throws GeometryTypeNotSupportedException,
218
            WKBEncodingException,
219
            IOException {
220
        GeometryType geometryType = geometry.getGeometryType();
221
        encodeWKBGeomHead(wkbGeometryType.wkbGeometryCollection, geometryType,
222
                stream);
223

    
224
        Aggregate collection = (Aggregate) geometry;
225

    
226
        int nGeometries = collection.getPrimitivesNumber();
227
        encodeInteger(nGeometries, stream);
228
        for (int i = 0; i < nGeometries; i++) {
229
            encode(collection.getPrimitiveAt(i), stream);
230
        }
231
    }
232

    
233
    private void encodeMultiPolygon(MultiPolygon geometry, DataOutputStream stream)
234
            throws GeometryTypeNotSupportedException,
235
            WKBPolygonNotClosedException, IOException {
236
        GeometryType geometryType = geometry.getGeometryType();
237
        encodeWKBGeomHead(wkbGeometryType.wkbMultiPolygon, geometryType, stream);
238

    
239
        int nGeometries = geometry.getPrimitivesNumber();
240
        encodeInteger(nGeometries, stream);
241
        for (int i = 0; i < nGeometries; i++) {
242
            encodePolygon((Polygon) geometry.getPrimitiveAt(i), stream);
243
        }
244
    }
245

    
246
    private void encodePolygon(Polygon geometry, DataOutputStream stream)
247
            throws GeometryTypeNotSupportedException,
248
            WKBPolygonNotClosedException, IOException {
249
        GeometryType geometryType = geometry.getGeometryType();
250
        encodeWKBGeomHead(wkbGeometryType.wkbPolygon, geometryType, stream);
251

    
252
        encodeInteger(1 + geometry.getNumInteriorRings(), stream);
253
        encodeLinearRing(geometry, stream);
254
        for (int i = 0; i < geometry.getNumInteriorRings(); i++) {
255
            Ring ring = geometry.getInteriorRing(i);
256
            encodeLinearRing(ring, stream);
257

    
258
        }
259
    }
260

    
261
    private void encodeLinearRing(Ring geom, DataOutputStream stream)
262
            throws IOException {
263
        encodeInteger(geom.getNumVertices(), stream);
264
        for (Point point : geom) {
265
            encodeCoordinates(point.getCoordinates(), stream);
266
        }
267
    }
268

    
269
    private void encodeMultiLineString(MultiLine geometry, DataOutputStream stream)
270
            throws GeometryTypeNotSupportedException,
271
            WKBPolygonNotClosedException, IOException {
272
        GeometryType geometryType = geometry.getGeometryType();
273
        encodeWKBGeomHead(wkbGeometryType.wkbMultiLineString, geometryType, stream);
274

    
275
        int nGeometries = geometry.getPrimitivesNumber();
276
        encodeInteger(nGeometries, stream);
277
        for (int i = 0; i < nGeometries; i++) {
278
            encodeLineString((Line) geometry.getPrimitiveAt(i), stream);
279
        }
280
    }
281

    
282
        private void encodeLineString(Line geometry, DataOutputStream stream)
283
            throws GeometryTypeNotSupportedException,
284
            WKBPolygonNotClosedException, IOException {
285
        GeometryType geometryType = geometry.getGeometryType();
286
        encodeWKBGeomHead(wkbGeometryType.wkbLineString, geometryType, stream);
287
        
288
        int nVertices = geometry.getNumVertices();
289
        encodeInteger(nVertices, stream);
290
        
291
        for (Point point : geometry) {
292
            encodeCoordinates(point.getCoordinates(), stream);
293
        }
294
    }
295

    
296

    
297
    private void encodeDouble(double data, DataOutputStream stream)
298
            throws IOException {
299
        if (this.byteOrder == wkbByteOrder.wkbXDR) {
300
            stream.writeDouble(data);
301
        } else {
302
            EndianUtils.writeSwappedDouble(stream, data);
303
        }
304
    }
305

    
306
    private void encodeInteger(int data, DataOutputStream stream)
307
            throws IOException {
308
        if (this.byteOrder == wkbByteOrder.wkbXDR) {
309
            stream.writeInt(data);
310
        } else {
311
            EndianUtils.writeSwappedInteger(stream, data);
312
        }
313
    }
314

    
315
    private void encodeCoordinates(double[] coordinates, DataOutputStream stream)
316
            throws IOException {
317
        for (int i = 0; i < coordinates.length; i++) {
318
            encodeDouble(coordinates[i], stream);
319
        }
320
    }
321

    
322
    private void encodeWKBGeomHead(int wkbBaseType, GeometryType geometryType,
323
            DataOutputStream stream) throws GeometryTypeNotSupportedException,
324
            IOException {
325

    
326
        stream.writeByte(this.byteOrder);
327

    
328
        int finalType = wkbBaseType % wkbGeometryType.wkb_baseToZ;
329

    
330
        switch (geometryType.getSubType()) {
331
            case SUBTYPES.GEOM2D:
332
                break;
333
            case SUBTYPES.GEOM2DM:
334
                finalType = finalType + wkbGeometryType.wkb_baseToM;
335
                break;
336

    
337
            case SUBTYPES.GEOM3D:
338
                finalType = finalType + wkbGeometryType.wkb_baseToZ;
339
                break;
340

    
341
            case SUBTYPES.GEOM3DM:
342
                finalType = finalType + wkbGeometryType.wkb_baseToZM;
343
                break;
344

    
345
            default:
346
                throw new GeometryTypeNotSupportedException(geometryType.getType(),
347
                        geometryType.getSubType());
348

    
349
        }
350
        encodeInteger(finalType, stream);
351
    }
352

    
353
    private void encodePoint(Geometry geometry, DataOutputStream stream)
354
            throws GeometryTypeNotSupportedException, IOException {
355
        GeometryType geometryType = geometry.getGeometryType();
356
        encodeWKBGeomHead(wkbGeometryType.wkbPoint, geometryType,
357
                stream);
358

    
359
        Point point = (Point) geometry;
360
        encodeCoordinates(point.getCoordinates(), stream);
361
    }
362

    
363
    private void encodeMultiPoint(Geometry geometry, DataOutputStream stream)
364
            throws GeometryTypeNotSupportedException, IOException {
365
        GeometryType geometryType = geometry.getGeometryType();
366
        encodeWKBGeomHead(wkbGeometryType.wkbMultiPoint, geometryType, stream);
367

    
368
        MultiPoint points = (MultiPoint) geometry;
369

    
370
        int nGeometries = points.getPrimitivesNumber();
371
        encodeInteger(nGeometries, stream);
372
        for (int i = 0; i < nGeometries; i++) {
373
            encodePoint(points.getPrimitiveAt(i), stream);
374
        }
375
    }
376

    
377
}