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;
  }