/**
  * Reads a coordinate value with the specified dimensionality. Makes the X and Y ordinates precise
  * according to the precision model in use.
  */
 private void readCoordinate() throws IOException {
   for (int i = 0; i < inputDimension; i++) {
     if (i <= 1) {
       ordValues[i] = precisionModel.makePrecise(dis.readDouble());
     } else {
       ordValues[i] = dis.readDouble();
     }
   }
 }
 private GeometryCollection readGeometryCollection() throws IOException, ParseException {
   int numGeom = dis.readInt();
   Geometry[] geoms = new Geometry[numGeom];
   for (int i = 0; i < numGeom; i++) {
     geoms[i] = readGeometry();
   }
   return factory.createGeometryCollection(geoms);
 }
 private MultiPoint readMultiPoint() throws IOException, ParseException {
   int numGeom = dis.readInt();
   Point[] geoms = new Point[numGeom];
   for (int i = 0; i < numGeom; i++) {
     Geometry g = readGeometry();
     if (!(g instanceof Point)) throw new ParseException(INVALID_GEOM_TYPE_MSG + "MultiPoint");
     geoms[i] = (Point) g;
   }
   return factory.createMultiPoint(geoms);
 }
 private MultiLineString readMultiLineString() throws IOException, ParseException {
   int numGeom = dis.readInt();
   LineString[] geoms = new LineString[numGeom];
   for (int i = 0; i < numGeom; i++) {
     Geometry g = readGeometry();
     if (!(g instanceof LineString))
       throw new ParseException(INVALID_GEOM_TYPE_MSG + "MultiLineString");
     geoms[i] = (LineString) g;
   }
   return factory.createMultiLineString(geoms);
 }
  private Polygon readPolygon() throws IOException {
    int numRings = dis.readInt();
    LinearRing[] holes = null;
    if (numRings > 1) holes = new LinearRing[numRings - 1];

    LinearRing shell = readLinearRing();
    for (int i = 0; i < numRings - 1; i++) {
      holes[i] = readLinearRing();
    }
    return factory.createPolygon(shell, holes);
  }
 private LinearRing readLinearRing() throws IOException {
   int size = dis.readInt();
   CoordinateSequence pts = readCoordinateSequenceRing(size);
   return factory.createLinearRing(pts);
 }
  private Geometry readGeometry() throws IOException, ParseException {

    // determine byte order
    byte byteOrderWKB = dis.readByte();

    // always set byte order, since it may change from geometry to geometry
    if (byteOrderWKB == WKBConstants.wkbNDR) {
      dis.setOrder(ByteOrderValues.LITTLE_ENDIAN);
    } else if (byteOrderWKB == WKBConstants.wkbXDR) {
      dis.setOrder(ByteOrderValues.BIG_ENDIAN);
    } else if (isStrict) {
      throw new ParseException("Unknown geometry byte order (not NDR or XDR): " + byteOrderWKB);
    }
    // if not strict and not XDR or NDR, then we just use the dis default set at the
    // start of the geometry (if a multi-geometry).  This  allows WBKReader to work
    // with Spatialite native BLOB WKB, as well as other WKB variants that might just
    // specify endian-ness at the start of the multigeometry.

    int typeInt = dis.readInt();
    int geometryType = typeInt & 0xff;
    // determine if Z values are present
    boolean hasZ = (typeInt & 0x80000000) != 0;
    inputDimension = hasZ ? 3 : 2;
    // determine if SRIDs are present
    hasSRID = (typeInt & 0x20000000) != 0;

    int SRID = 0;
    if (hasSRID) {
      SRID = dis.readInt();
    }

    // only allocate ordValues buffer if necessary
    if (ordValues == null || ordValues.length < inputDimension)
      ordValues = new double[inputDimension];

    Geometry geom = null;
    switch (geometryType) {
      case WKBConstants.wkbPoint:
        geom = readPoint();
        break;
      case WKBConstants.wkbLineString:
        geom = readLineString();
        break;
      case WKBConstants.wkbPolygon:
        geom = readPolygon();
        break;
      case WKBConstants.wkbMultiPoint:
        geom = readMultiPoint();
        break;
      case WKBConstants.wkbMultiLineString:
        geom = readMultiLineString();
        break;
      case WKBConstants.wkbMultiPolygon:
        geom = readMultiPolygon();
        break;
      case WKBConstants.wkbGeometryCollection:
        geom = readGeometryCollection();
        break;
      default:
        throw new ParseException("Unknown WKB type " + geometryType);
    }
    setSRID(geom, SRID);
    return geom;
  }
 /**
  * Reads a {@link Geometry} in binary WKB format from an {@link InStream}.
  *
  * @param is the stream to read from
  * @return the Geometry read
  * @throws IOException if the underlying stream creates an error
  * @throws ParseException if the WKB is ill-formed
  */
 public Geometry read(InStream is) throws IOException, ParseException {
   dis.setInStream(is);
   Geometry g = readGeometry();
   return g;
 }