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 42330 fdiaz
/**
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 43092 jjdelcerro
import org.apache.commons.io.EndianUtils;
30 42330 fdiaz
import org.gvsig.fmap.geom.Geometry;
31
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
32
import org.gvsig.fmap.geom.Geometry.TYPES;
33 47432 fdiaz
import org.gvsig.fmap.geom.GeometryException;
34 42330 fdiaz
import org.gvsig.fmap.geom.aggregate.Aggregate;
35 47432 fdiaz
import org.gvsig.fmap.geom.aggregate.MultiLine;
36 42330 fdiaz
import org.gvsig.fmap.geom.aggregate.MultiPoint;
37 47432 fdiaz
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
38
import org.gvsig.fmap.geom.primitive.Line;
39 42330 fdiaz
import org.gvsig.fmap.geom.primitive.Point;
40 47432 fdiaz
import org.gvsig.fmap.geom.primitive.Polygon;
41
import org.gvsig.fmap.geom.primitive.Ring;
42 42330 fdiaz
import org.gvsig.fmap.geom.type.GeometryType;
43
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
44
45 47432 fdiaz
public class OGCWKBEncoder {
46 42330 fdiaz
47 47432 fdiaz
    public interface wkbGeometryType {
48 42330 fdiaz
49 47432 fdiaz
        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 42330 fdiaz
60 47432 fdiaz
        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 42330 fdiaz
71 47432 fdiaz
        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 42330 fdiaz
82 47432 fdiaz
        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 42330 fdiaz
93 47432 fdiaz
        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 42330 fdiaz
98 47432 fdiaz
    public interface wkbByteOrder {
99 42330 fdiaz
100 47432 fdiaz
        public final static byte wkbXDR = 0;                // Big Endian
101
        public final static byte wkbNDR = 1;                // Little Endian
102
    }
103 42330 fdiaz
104 47432 fdiaz
    private int byteOrder;
105 42330 fdiaz
106 47432 fdiaz
    public OGCWKBEncoder() {
107
        this(wkbByteOrder.wkbXDR);
108
    }
109 42330 fdiaz
110 47432 fdiaz
    public OGCWKBEncoder(int byteOrder) {
111
        this.byteOrder = byteOrder;
112
    }
113 42330 fdiaz
114 47432 fdiaz
    public byte[] encode(Geometry geometry)
115
            throws GeometryTypeNotSupportedException,
116
            WKBEncodingException,
117
            IOException {
118
        ByteArrayOutputStream stream;
119 42330 fdiaz
120 47432 fdiaz
        if (geometry.getType() == TYPES.POINT) {
121
            stream = new ByteArrayOutputStream(50);
122
        } else {
123
            stream = new ByteArrayOutputStream(512);
124
        }
125 42330 fdiaz
126 47432 fdiaz
        encode(geometry, stream);
127
        return stream.toByteArray();
128 42330 fdiaz
129 47432 fdiaz
    }
130 42330 fdiaz
131 47432 fdiaz
    public void encode(Geometry geometry, ByteArrayOutputStream stream)
132
            throws GeometryTypeNotSupportedException, WKBEncodingException,
133
            IOException {
134
        encode(geometry, new DataOutputStream(stream));
135
    }
136 42330 fdiaz
137 47432 fdiaz
    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 42330 fdiaz
144 47432 fdiaz
        } 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 43092 jjdelcerro
                }
154 47432 fdiaz
            } catch (GeometryException ex) {
155
                throw new WKBEncodingException(ex);
156
            }
157 42330 fdiaz
158 47432 fdiaz
        } 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 43092 jjdelcerro
            }
171 47432 fdiaz
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 43092 jjdelcerro
//
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 47432 fdiaz
    }
215 42330 fdiaz
216 47432 fdiaz
    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 42330 fdiaz
224 47432 fdiaz
        Aggregate collection = (Aggregate) geometry;
225 42330 fdiaz
226 47432 fdiaz
        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 42330 fdiaz
233 47432 fdiaz
    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 42330 fdiaz
239 47432 fdiaz
        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 42330 fdiaz
246 47432 fdiaz
    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 42330 fdiaz
252 47432 fdiaz
        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 42330 fdiaz
258 47432 fdiaz
        }
259
    }
260 42330 fdiaz
261 47432 fdiaz
    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 42330 fdiaz
269 47432 fdiaz
    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 42330 fdiaz
275 47432 fdiaz
        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 42330 fdiaz
282 47432 fdiaz
        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 42330 fdiaz
296
297 47432 fdiaz
    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 42330 fdiaz
306 47432 fdiaz
    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 43092 jjdelcerro
        }
313 47432 fdiaz
    }
314 42330 fdiaz
315 47432 fdiaz
    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 43092 jjdelcerro
        }
320 47432 fdiaz
    }
321 43092 jjdelcerro
322 47432 fdiaz
    private void encodeWKBGeomHead(int wkbBaseType, GeometryType geometryType,
323
            DataOutputStream stream) throws GeometryTypeNotSupportedException,
324
            IOException {
325 42330 fdiaz
326 47432 fdiaz
        stream.writeByte(this.byteOrder);
327 42330 fdiaz
328 47432 fdiaz
        int finalType = wkbBaseType % wkbGeometryType.wkb_baseToZ;
329 42330 fdiaz
330 47432 fdiaz
        switch (geometryType.getSubType()) {
331
            case SUBTYPES.GEOM2D:
332
                break;
333
            case SUBTYPES.GEOM2DM:
334
                finalType = finalType + wkbGeometryType.wkb_baseToM;
335
                break;
336 42330 fdiaz
337 47432 fdiaz
            case SUBTYPES.GEOM3D:
338
                finalType = finalType + wkbGeometryType.wkb_baseToZ;
339
                break;
340 42330 fdiaz
341 47432 fdiaz
            case SUBTYPES.GEOM3DM:
342
                finalType = finalType + wkbGeometryType.wkb_baseToZM;
343
                break;
344 42330 fdiaz
345 47432 fdiaz
            default:
346
                throw new GeometryTypeNotSupportedException(geometryType.getType(),
347
                        geometryType.getSubType());
348 42330 fdiaz
349 47432 fdiaz
        }
350
        encodeInteger(finalType, stream);
351
    }
352 42330 fdiaz
353 47432 fdiaz
    private void encodePoint(Geometry geometry, DataOutputStream stream)
354
            throws GeometryTypeNotSupportedException, IOException {
355
        GeometryType geometryType = geometry.getGeometryType();
356
        encodeWKBGeomHead(wkbGeometryType.wkbPoint, geometryType,
357
                stream);
358 42330 fdiaz
359 47432 fdiaz
        Point point = (Point) geometry;
360
        encodeCoordinates(point.getCoordinates(), stream);
361
    }
362 42330 fdiaz
363 47432 fdiaz
    private void encodeMultiPoint(Geometry geometry, DataOutputStream stream)
364
            throws GeometryTypeNotSupportedException, IOException {
365
        GeometryType geometryType = geometry.getGeometryType();
366
        encodeWKBGeomHead(wkbGeometryType.wkbMultiPoint, geometryType, stream);
367 42330 fdiaz
368 47432 fdiaz
        MultiPoint points = (MultiPoint) geometry;
369 42330 fdiaz
370 47432 fdiaz
        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 42330 fdiaz
377
}