1
2
3
4
5
6
7
8
9 package org.locationtech.spatial4j.io.jts;
10
11 import org.locationtech.spatial4j.context.jts.JtsSpatialContext;
12 import org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory;
13 import org.locationtech.spatial4j.exception.InvalidShapeException;
14 import org.locationtech.spatial4j.io.BinaryCodec;
15 import org.locationtech.spatial4j.shape.Shape;
16 import org.locationtech.jts.geom.Geometry;
17 import org.locationtech.jts.geom.PrecisionModel;
18 import org.locationtech.jts.io.InStream;
19 import org.locationtech.jts.io.OutStream;
20 import org.locationtech.jts.io.ParseException;
21 import org.locationtech.jts.io.WKBConstants;
22 import org.locationtech.jts.io.WKBReader;
23 import org.locationtech.jts.io.WKBWriter;
24
25 import java.io.DataInput;
26 import java.io.DataOutput;
27 import java.io.IOException;
28
29
30
31
32 public class JtsBinaryCodec extends BinaryCodec {
33
34 protected final boolean useFloat;
35
36 public JtsBinaryCodec(JtsSpatialContext ctx, JtsSpatialContextFactory factory) {
37 super(ctx, factory);
38
39 useFloat = (factory.precisionModel.getType() == PrecisionModel.FLOATING_SINGLE);
40 }
41
42 @Override
43 protected double readDim(DataInput dataInput) throws IOException {
44 if (useFloat)
45 return dataInput.readFloat();
46 return super.readDim(dataInput);
47 }
48
49 @Override
50 protected void writeDim(DataOutput dataOutput, double v) throws IOException {
51 if (useFloat)
52 dataOutput.writeFloat((float) v);
53 else
54 super.writeDim(dataOutput, v);
55 }
56
57 @Override
58 protected byte typeForShape(Shape s) {
59 byte type = super.typeForShape(s);
60 if (type == 0) {
61 type = TYPE_GEOM;
62 }
63 return type;
64 }
65
66 @Override
67 protected Shape readShapeByTypeIfSupported(final DataInput dataInput, byte type) throws IOException {
68 if (type != TYPE_GEOM)
69 return super.readShapeByTypeIfSupported(dataInput, type);
70 return readJtsGeom(dataInput);
71 }
72
73 @Override
74 protected boolean writeShapeByTypeIfSupported(DataOutput dataOutput, Shape s, byte type) throws IOException {
75 if (type != TYPE_GEOM)
76 return super.writeShapeByTypeIfSupported(dataOutput, s, type);
77 writeJtsGeom(dataOutput, s);
78 return true;
79 }
80
81 public Shape readJtsGeom(final DataInput dataInput) throws IOException {
82 JtsSpatialContext ctx = (JtsSpatialContext)super.ctx;
83 WKBReader reader = new WKBReader(ctx.getGeometryFactory());
84 try {
85 InStream inStream = new InStream() {
86 boolean first = true;
87 @Override
88 public void read(byte[] buf) throws IOException {
89 if (first) {
90 if (buf.length != 1)
91 throw new IllegalStateException("Expected initial read of one byte, not: " + buf.length);
92 buf[0] = WKBConstants.wkbXDR;
93 first = false;
94 } else {
95
96 dataInput.readFully(buf);
97 }
98 }
99 };
100 Geometry geom = reader.read(inStream);
101
102
103 return ctx.makeShape(geom, false, false);
104 } catch (ParseException ex) {
105 throw new InvalidShapeException("error reading WKT", ex);
106 }
107 }
108
109 public void writeJtsGeom(final DataOutput dataOutput, Shape s) throws IOException {
110 JtsSpatialContext ctx = (JtsSpatialContext)super.ctx;
111 Geometry geom = ctx.getGeometryFrom(s);
112 new WKBWriter().write(geom, new OutStream() {
113 boolean first = true;
114 @Override
115 public void write(byte[] buf, int len) throws IOException {
116 if (first) {
117 first = false;
118
119 if (len != 1 || buf[0] != WKBConstants.wkbXDR)
120 throw new IllegalStateException("Unexpected WKB byte order mark");
121 return;
122 }
123 dataOutput.write(buf, 0, len);
124 }
125 });
126 }
127 }