1
2
3
4
5
6
7
8
9 package org.locationtech.spatial4j.io;
10
11 import org.locationtech.spatial4j.context.SpatialContext;
12 import org.locationtech.spatial4j.context.SpatialContextFactory;
13 import org.locationtech.spatial4j.exception.InvalidShapeException;
14 import org.locationtech.spatial4j.shape.Circle;
15 import org.locationtech.spatial4j.shape.Point;
16 import org.locationtech.spatial4j.shape.Rectangle;
17 import org.locationtech.spatial4j.shape.Shape;
18 import org.locationtech.spatial4j.shape.ShapeCollection;
19
20 import java.io.DataInput;
21 import java.io.DataOutput;
22 import java.io.IOException;
23 import java.util.ArrayList;
24
25
26
27
28
29
30
31
32 public class BinaryCodec {
33
34 protected static final byte
35 TYPE_POINT = 1,
36 TYPE_RECT = 2,
37 TYPE_CIRCLE = 3,
38 TYPE_COLL = 4,
39 TYPE_GEOM = 5;
40
41
42
43 protected final SpatialContext ctx;
44
45
46 public BinaryCodec(SpatialContext ctx, SpatialContextFactory factory) {
47 this.ctx = ctx;
48 }
49
50 public Shape readShape(DataInput dataInput) throws IOException {
51 byte type = dataInput.readByte();
52 Shape s = readShapeByTypeIfSupported(dataInput, type);
53 if (s == null)
54 throw new IllegalArgumentException("Unsupported shape byte "+type);
55 return s;
56 }
57
58 public void writeShape(DataOutput dataOutput, Shape s) throws IOException {
59 boolean written = writeShapeByTypeIfSupported(dataOutput, s);
60 if (!written)
61 throw new IllegalArgumentException("Unsupported shape "+s.getClass());
62 }
63
64 protected Shape readShapeByTypeIfSupported(DataInput dataInput, byte type) throws IOException {
65 switch (type) {
66 case TYPE_POINT: return readPoint(dataInput);
67 case TYPE_RECT: return readRect(dataInput);
68 case TYPE_CIRCLE: return readCircle(dataInput);
69 case TYPE_COLL: return readCollection(dataInput);
70 default: return null;
71 }
72 }
73
74
75 protected boolean writeShapeByTypeIfSupported(DataOutput dataOutput, Shape s) throws IOException {
76 byte type = typeForShape(s);
77 dataOutput.writeByte(type);
78 return writeShapeByTypeIfSupported(dataOutput, s, type);
79
80 }
81
82 protected boolean writeShapeByTypeIfSupported(DataOutput dataOutput, Shape s, byte type) throws IOException {
83 switch (type) {
84 case TYPE_POINT: writePoint(dataOutput, (Point) s); break;
85 case TYPE_RECT: writeRect(dataOutput, (Rectangle) s); break;
86 case TYPE_CIRCLE: writeCircle(dataOutput, (Circle) s); break;
87 case TYPE_COLL: writeCollection(dataOutput, (ShapeCollection) s); break;
88 default:
89 return false;
90 }
91 return true;
92 }
93
94 protected byte typeForShape(Shape s) {
95 if (s instanceof Point) {
96 return TYPE_POINT;
97 } else if (s instanceof Rectangle) {
98 return TYPE_RECT;
99 } else if (s instanceof Circle) {
100 return TYPE_CIRCLE;
101 } else if (s instanceof ShapeCollection) {
102 return TYPE_COLL;
103 } else {
104 return 0;
105 }
106 }
107
108 protected double readDim(DataInput dataInput) throws IOException {
109 return dataInput.readDouble();
110 }
111
112 protected void writeDim(DataOutput dataOutput, double v) throws IOException {
113 dataOutput.writeDouble(v);
114 }
115
116 public Point readPoint(DataInput dataInput) throws IOException {
117 return ctx.makePoint(readDim(dataInput), readDim(dataInput));
118 }
119
120 public void writePoint(DataOutput dataOutput, Point pt) throws IOException {
121 writeDim(dataOutput, pt.getX());
122 writeDim(dataOutput, pt.getY());
123 }
124
125 public Rectangle readRect(DataInput dataInput) throws IOException {
126 return ctx.makeRectangle(readDim(dataInput), readDim(dataInput), readDim(dataInput), readDim(dataInput));
127 }
128
129 public void writeRect(DataOutput dataOutput, Rectangle r) throws IOException {
130 writeDim(dataOutput, r.getMinX());
131 writeDim(dataOutput, r.getMaxX());
132 writeDim(dataOutput, r.getMinY());
133 writeDim(dataOutput, r.getMaxY());
134 }
135
136 public Circle readCircle(DataInput dataInput) throws IOException {
137 return ctx.makeCircle(readPoint(dataInput), readDim(dataInput));
138 }
139
140 public void writeCircle(DataOutput dataOutput, Circle c) throws IOException {
141 writePoint(dataOutput, c.getCenter());
142 writeDim(dataOutput, c.getRadius());
143 }
144
145 public ShapeCollection readCollection(DataInput dataInput) throws IOException {
146 byte type = dataInput.readByte();
147 int size = dataInput.readInt();
148 ArrayList<Shape> shapes = new ArrayList<>(size);
149 for (int i = 0; i < size; i++) {
150 if (type == 0) {
151 shapes.add(readShape(dataInput));
152 } else {
153 Shape s = readShapeByTypeIfSupported(dataInput, type);
154 if (s == null)
155 throw new InvalidShapeException("Unsupported shape byte "+type);
156 shapes.add(s);
157 }
158 }
159 return ctx.makeCollection(shapes);
160 }
161
162 public void writeCollection(DataOutput dataOutput, ShapeCollection col) throws IOException {
163 byte type = (byte) 0;
164 dataOutput.writeByte(type);
165 dataOutput.writeInt(col.size());
166 for (int i = 0; i < col.size(); i++) {
167 Shape s = col.get(i);
168 if (type == 0) {
169 writeShape(dataOutput, s);
170 } else {
171 boolean written = writeShapeByTypeIfSupported(dataOutput, s, type);
172 if (!written)
173 throw new IllegalArgumentException("Unsupported shape type "+s.getClass());
174 }
175 }
176 }
177
178 }