Statistics
| Revision:

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
}