/* Copyright 2013 The jeo project. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.jeo.geopkg.geom; import java.io.IOException; import java.io.InputStream; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ByteArrayInStream; import com.vividsolutions.jts.io.ByteOrderDataInStream; import com.vividsolutions.jts.io.InStream; import com.vividsolutions.jts.io.InputStreamInStream; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKBReader; public class GeoPkgGeomReader { public Geometry read(byte[] bytes) throws IOException { return read(new ByteArrayInStream(bytes)); } public Geometry read(InputStream in) throws IOException { return read(new InputStreamInStream(in)); } Geometry read(InStream input) throws IOException { // read the header Header h = readHeader(input); // read the geometry try { Geometry g = new WKBReader().read(input); g.setSRID(h.srid); return g; } catch (ParseException e) { throw new IOException(e); } } /* * OptimizedGeoPackageBinary { * byte[3] magic = 0x47504230; // 'GPB' * byte flags; // see flags layout below * unit32 srid; * double[] envelope; // see flags envelope contents indicator code below * WKBGeometry geometry; // per OGC 06-103r4 clause 8 * * * flags layout: * bit 7 6 5 4 3 2 1 0 * use V V V V E E E B * use: * V: version number (4-bit unsigned integer) * 0 = version 1 * * E: envelope contents indicator code (3-bit unsigned integer) * value | description | envelope length (bytes) * 0 | no envelope (space saving slower indexing option) | 0 * 1 | envelope is [minx, maxx, miny, maxy] | 32 * 2 | envelope is [minx, maxx, miny, maxy, minz, maxz] | 48 * 3 | envelope is [minx, maxx, miny, maxy, minm, maxm] | 48 * 4 | envelope is [minx, maxx, miny, maxy, minz, maxz, minm, maxm] | 64 * B: byte order for header values (1-bit Boolean) * 0 = Big Endian (most significant bit first) * 1 = Little Endian (least significant bit first) */ Header readHeader(InStream in) throws IOException { Header h = new Header(); // read first 4 bytes // TODO: something with the magic number byte[] buf = new byte[4]; in.read(buf); // next byte flags h.flags = new Flags((byte)buf[3]); // set endianness ByteOrderDataInStream din = new ByteOrderDataInStream(in); din.setOrder(h.flags.endianess()); // read the srid h.srid = din.readInt(); // read the envlope if (h.flags.envelopeIndicator() != EnvelopeType.NONE) { double x1 = din.readDouble(); double x2 = din.readDouble(); double y1 = din.readDouble(); double y2 = din.readDouble(); if (h.flags.envelopeIndicator().value > 1) { // 2 = minz,maxz; 3 = minm,maxm - we ignore these for now din.readDouble(); din.readDouble(); } if (h.flags.envelopeIndicator().value > 3) { // 4 = minz,maxz,minm,maxm - we ignore these for now din.readDouble(); din.readDouble(); } h.envelope = new Envelope(x1, x2, y1, y2); } return h; } }