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 | } |