svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.sqlite / org.gvsig.sqlite.provider / src / main / java / org / gvsig / sqlite / dal / geopackage / GeopackageGeometryBuilder.java @ 47606
History | View | Annotate | Download (5.03 KB)
1 |
package org.gvsig.sqlite.dal.geopackage; |
---|---|
2 |
|
3 |
import java.io.IOException; |
4 |
import java.nio.ByteOrder; |
5 |
import org.gvsig.fmap.geom.Geometry; |
6 |
import org.gvsig.fmap.geom.primitive.Envelope; |
7 |
import static org.gvsig.sqlite.dal.geopackage.GeopackageUtils.GEOMETRY_MAGIC_NUMBER; |
8 |
import static org.gvsig.sqlite.dal.geopackage.GeopackageUtils.GEOMETRY_VERSION_1; |
9 |
import org.sqlite.SQLiteConnection; |
10 |
|
11 |
|
12 |
/*
|
13 |
* Based on portions of code from GeoPackage Libraries
|
14 |
* of National Geospatial-Intelligence Agency (NGA)
|
15 |
* https://github.com/ngageoint/geopackage-java
|
16 |
*/
|
17 |
|
18 |
/**
|
19 |
*
|
20 |
* @author jjdelcerro
|
21 |
*/
|
22 |
@SuppressWarnings("UseSpecificCatch") |
23 |
public class GeopackageGeometryBuilder { |
24 |
|
25 |
private int srsId; |
26 |
private Envelope envelope;
|
27 |
private Geometry geometry;
|
28 |
|
29 |
@SuppressWarnings("FieldMayBeFinal") |
30 |
private ByteOrder byteOrder; |
31 |
|
32 |
private boolean extended; |
33 |
private boolean empty; |
34 |
|
35 |
/*friend*/ GeopackageGeometryBuilder() {
|
36 |
this.byteOrder = GeopackageUtils.DEFAULT_BYTE_ORDER;
|
37 |
} |
38 |
|
39 |
public void setGeometry(SQLiteConnection conn, Geometry geometry) { |
40 |
this.geometry = geometry;
|
41 |
this.srsId = GeopackageUtils.getSrsId(conn, geometry);
|
42 |
if( this.geometry == null || this.geometry.isEmpty()) { |
43 |
this.envelope = null; |
44 |
this.extended = false; |
45 |
this.empty = true; |
46 |
} else {
|
47 |
this.empty = false; |
48 |
this.extended = false; |
49 |
this.envelope = this.geometry.getEnvelope(); |
50 |
} |
51 |
} |
52 |
|
53 |
public byte[] build() { |
54 |
|
55 |
try {
|
56 |
ByteWriter writer = new ByteWriter();
|
57 |
|
58 |
// Write GP as the 2 byte magic number
|
59 |
writer.writeString(GEOMETRY_MAGIC_NUMBER); |
60 |
|
61 |
// Write a byte as the version, value of 0 = version 1
|
62 |
writer.writeByte(GEOMETRY_VERSION_1); |
63 |
|
64 |
// Build and write a flags byte
|
65 |
byte flags = buildFlagsByte();
|
66 |
writer.writeByte(flags); |
67 |
writer.setByteOrder(byteOrder); |
68 |
|
69 |
// Write the 4 byte srs id int
|
70 |
writer.writeInt(srsId); |
71 |
|
72 |
// Write the envelope
|
73 |
writeEnvelope(writer); |
74 |
|
75 |
// Save off where the WKB bytes start
|
76 |
int wkbGeometryIndex = writer.size();
|
77 |
|
78 |
// Write the Well-Known Binary Geometry if not marked as empty
|
79 |
if (!empty) {
|
80 |
byte[] wkb = geometry.convertToWKB(); |
81 |
writer.writeBytes(wkb); |
82 |
} |
83 |
|
84 |
// Get the bytes
|
85 |
byte[] bytes = writer.getBytes(); |
86 |
|
87 |
// Close the writer
|
88 |
writer.close(); |
89 |
|
90 |
return bytes;
|
91 |
} catch (Throwable ex) { |
92 |
throw new RuntimeException("Can't build geometry bytes", ex); |
93 |
} |
94 |
} |
95 |
|
96 |
/**
|
97 |
* Build the flags byte from the flag values
|
98 |
*
|
99 |
* @return envelope indicator
|
100 |
*/
|
101 |
private byte buildFlagsByte() { |
102 |
|
103 |
byte flag = 0; |
104 |
|
105 |
// Add the binary type to bit 5, 0 for standard and 1 for extended
|
106 |
int binaryType = extended ? 1 : 0; |
107 |
flag += (binaryType << 5);
|
108 |
|
109 |
// Add the empty geometry flag to bit 4, 0 for non-empty and 1 for
|
110 |
// empty
|
111 |
int emptyValue = empty ? 1 : 0; |
112 |
flag += (emptyValue << 4);
|
113 |
|
114 |
// Add the envelope contents indicator code (3-bit unsigned integer to
|
115 |
// bits 3, 2, and 1)
|
116 |
int envelopeIndicator = envelope == null ? 0 : getIndicator(envelope); |
117 |
flag += (envelopeIndicator << 1);
|
118 |
|
119 |
// Add the byte order to bit 0, 0 for Big Endian and 1 for Little
|
120 |
// Endian
|
121 |
int byteOrderValue = (byteOrder == ByteOrder.BIG_ENDIAN) ? 0 : 1; |
122 |
flag += byteOrderValue; |
123 |
|
124 |
return flag;
|
125 |
} |
126 |
|
127 |
/**
|
128 |
* Get the envelope flag indicator
|
129 |
*
|
130 |
* 1 for xy, 2 for xyz, 3 for xym, 4 for xyzm (null would be 0)
|
131 |
*
|
132 |
* @param envelope geometry envelope
|
133 |
*
|
134 |
* @return indicator
|
135 |
*/
|
136 |
public static int getIndicator(Envelope envelope) { |
137 |
int indicator = 1; |
138 |
if (envelope.hasZ()) {
|
139 |
indicator++; |
140 |
} |
141 |
if (envelope.hasM()) {
|
142 |
indicator += 2;
|
143 |
} |
144 |
return indicator;
|
145 |
} |
146 |
|
147 |
/**
|
148 |
* Write the envelope bytes
|
149 |
*
|
150 |
* @param writer byte writer
|
151 |
* @throws IOException
|
152 |
*/
|
153 |
private void writeEnvelope(ByteWriter writer) throws IOException { |
154 |
|
155 |
if (envelope != null) { |
156 |
|
157 |
// Write x and y values
|
158 |
writer.writeDouble(envelope.getMinimum(Geometry.DIMENSIONS.X)); |
159 |
writer.writeDouble(envelope.getMaximum(Geometry.DIMENSIONS.X)); |
160 |
writer.writeDouble(envelope.getMinimum(Geometry.DIMENSIONS.Y)); |
161 |
writer.writeDouble(envelope.getMaximum(Geometry.DIMENSIONS.Y)); |
162 |
|
163 |
// Write z values
|
164 |
if (envelope.hasZ()) {
|
165 |
writer.writeDouble(envelope.getMinimum(Geometry.DIMENSIONS.Z)); |
166 |
writer.writeDouble(envelope.getMaximum(Geometry.DIMENSIONS.Z)); |
167 |
} |
168 |
|
169 |
// // Write m values
|
170 |
// if (envelope.hasM()) {
|
171 |
// writer.writeDouble(envelope.getMinM());
|
172 |
// writer.writeDouble(envelope.getMaxM());
|
173 |
// }
|
174 |
} |
175 |
} |
176 |
|
177 |
} |