You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by js...@apache.org on 2022/02/17 15:13:49 UTC

[sis] branch feat/postgis-hexewkb created (now e34e693)

This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a change to branch feat/postgis-hexewkb
in repository https://gitbox.apache.org/repos/asf/sis.git.


      at e34e693  PostGIS: add HexEWKB geometry reader

This branch includes the following new commits:

     new e34e693  PostGIS: add HexEWKB geometry reader

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[sis] 01/01: PostGIS: add HexEWKB geometry reader

Posted by js...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch feat/postgis-hexewkb
in repository https://gitbox.apache.org/repos/asf/sis.git

commit e34e693f46188689f697694a9eccc56b91b01ca5
Author: jsorel <jo...@geomatys.com>
AuthorDate: Thu Feb 17 16:06:43 2022 +0100

    PostGIS: add HexEWKB geometry reader
---
 storage/sis-sqlstore/pom.xml                       |   7 +-
 .../apache/sis/internal/sql/postgis/HexEWKB.java   | 193 +++++++++++++++++++++
 2 files changed, 199 insertions(+), 1 deletion(-)

diff --git a/storage/sis-sqlstore/pom.xml b/storage/sis-sqlstore/pom.xml
index 3053c18..e057e31 100644
--- a/storage/sis-sqlstore/pom.xml
+++ b/storage/sis-sqlstore/pom.xml
@@ -111,6 +111,11 @@
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>net.postgis</groupId>
+      <artifactId>postgis-jdbc</artifactId>
+      <version>2.3.0</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.sis.core</groupId>
       <artifactId>sis-metadata</artifactId>
       <version>${project.version}</version>
@@ -147,7 +152,7 @@
     <dependency>
       <groupId>org.locationtech.jts</groupId>
       <artifactId>jts-core</artifactId>
-      <scope>test</scope>
+      <scope>compile</scope>
     </dependency>
     <dependency>
       <groupId>com.esri.geometry</groupId>
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/HexEWKB.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/HexEWKB.java
new file mode 100644
index 0000000..041cf9f
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/HexEWKB.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sis.internal.sql.postgis;
+
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.CoordinateSequence;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryCollection;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.locationtech.jts.geom.LinearRing;
+import org.locationtech.jts.geom.MultiLineString;
+import org.locationtech.jts.geom.MultiPoint;
+import org.locationtech.jts.geom.MultiPolygon;
+import org.locationtech.jts.geom.Point;
+import org.locationtech.jts.geom.Polygon;
+import org.locationtech.jts.geom.impl.PackedCoordinateSequence;
+import org.postgis.binary.ByteGetter;
+import org.postgis.binary.ValueGetter;
+import static org.postgis.Geometry.*;
+
+/**
+ * PostGIS Hexa-EWKB Geometry reader/write classes.
+ *
+ * This format is the natural form returned by a query selection a geometry
+ * field whithout using any ST_X method.
+ *
+ * @see <a href="http://postgis.net/docs/using_postgis_dbmanagement.html#EWKB_EWKT">4.2.1. PostGIS EWKB and EWKT</a>
+ *
+ * @author Johann Sorel (Geomatys)
+ * @module
+ */
+final class PostgisHexEWKB {
+
+    private static final int MASK_Z = 0x80000000;
+    private static final int MASK_M = 0x40000000;
+    private static final int MASK_SRID = 0x20000000;
+    private static final int MASK_GEOMTYPE = 0x1FFFFFFF;
+
+    private final GeometryFactory gf;
+
+    PostgisHexEWKB(final GeometryFactory gf) {
+        this.gf = gf;
+    }
+
+    public Geometry read(final String value) {
+        if (value == null) {
+            return null;
+        }
+
+        final ByteGetter.StringByteGetter bytes = new ByteGetter.StringByteGetter(value);
+        final ValueGetter vg;
+        final int endianess = bytes.get(0);
+        if (endianess == ValueGetter.XDR.NUMBER) {
+            vg = new ValueGetter.XDR(bytes);
+        } else if (endianess == ValueGetter.NDR.NUMBER) {
+            vg = new ValueGetter.NDR(bytes);
+        } else {
+            throw new IllegalArgumentException("Illegal endianess value : " + endianess);
+        }
+
+        return readGeometry(vg, 0);
+    }
+
+    private Geometry readGeometry(final ValueGetter data, int srid) {
+        byte endian = data.getByte(); // skip and test endian flag
+        if (endian != data.endian) {
+            throw new IllegalArgumentException("Endian inconsistency!");
+        }
+
+        //parse flags
+        final int flags        = data.getInt();
+        final boolean flagZ    = (flags & MASK_Z) != 0;
+        final boolean flagM    = (flags & MASK_M) != 0;
+        final boolean flagSRID = (flags & MASK_SRID) != 0;
+        final int geomType     = (flags & MASK_GEOMTYPE);
+        final int nbDim        = 2 + ((flagZ) ? 1 : 0) + ((flagM) ? 1 : 0);
+
+        if (flagSRID) {
+            srid = data.getInt();
+        }
+
+        final Geometry geom;
+        switch (geomType) {
+            case POINT:              geom = readPoint(data, nbDim);           break;
+            case LINESTRING:         geom = readLineString(data, nbDim);      break;
+            case POLYGON:            geom = readPolygon(data, nbDim, srid);   break;
+            case MULTIPOINT:         geom = readMultiPoint(data, srid);       break;
+            case MULTILINESTRING:    geom = readMultiLineString(data, srid);  break;
+            case MULTIPOLYGON:       geom = readMultiPolygon(data, srid);     break;
+            case GEOMETRYCOLLECTION: geom = readCollection(data, srid);       break;
+            default: throw new IllegalArgumentException("Unknown geometry type : "+geomType);
+        }
+
+        geom.setSRID(srid);
+        return geom;
+    }
+
+    private Point readPoint(final ValueGetter data, final int nbDim) {
+        switch (nbDim) {
+            case 2:
+                return gf.createPoint(new Coordinate(data.getDouble(), data.getDouble()));
+            case 3:
+                return gf.createPoint(new Coordinate(data.getDouble(), data.getDouble(), data.getDouble()));
+            case 4:
+                final CoordinateSequence cs = new PackedCoordinateSequence.Double(1, nbDim, 0);
+                cs.setOrdinate(0, 0, data.getDouble());
+                cs.setOrdinate(0, 1, data.getDouble());
+                cs.setOrdinate(0, 2, data.getDouble());
+                cs.setOrdinate(0, 3, data.getDouble());
+                return gf.createPoint(cs);
+            default:
+                throw new IllegalArgumentException("Invalid dimension number : " + nbDim);
+        }
+    }
+
+    private CoordinateSequence readCS(final ValueGetter data, final int nbDim) {
+        final int nb = data.getInt();
+        final CoordinateSequence cs = new PackedCoordinateSequence.Double(nb, nbDim, 0);
+        for (int index = 0; index < nb; index++) {
+            for (int ordinal = 0; ordinal < nbDim; ordinal++) {
+                cs.setOrdinate(index, ordinal, data.getDouble());
+            }
+        }
+        return cs;
+    }
+
+    private MultiPoint readMultiPoint(final ValueGetter data, final int srid) {
+        final Point[] geoms = new Point[data.getInt()];
+        for (int i = 0; i < geoms.length; i++) {
+            geoms[i] = (Point) readGeometry(data, srid);
+        }
+        return gf.createMultiPoint(geoms);
+    }
+
+    private LineString readLineString(final ValueGetter data, final int nbDim) {
+        return gf.createLineString(readCS(data, nbDim));
+    }
+
+    private LinearRing readLinearRing(final ValueGetter data, final int nbDim) {
+        return gf.createLinearRing(readCS(data, nbDim));
+    }
+
+    private Polygon readPolygon(final ValueGetter data, final int nbDim, final int srid) {
+        final LinearRing[] inners = new LinearRing[data.getInt() - 1];
+        final LinearRing outter = readLinearRing(data, nbDim);
+        outter.setSRID(srid);
+        for (int i = 0; i < inners.length; i++) {
+            inners[i] = readLinearRing(data, nbDim);
+            inners[i].setSRID(srid);
+        }
+        return gf.createPolygon(outter, inners);
+    }
+
+    private MultiLineString readMultiLineString(final ValueGetter data, final int srid) {
+        final LineString[] geoms = new LineString[data.getInt()];
+        for (int i = 0; i < geoms.length; i++) {
+            geoms[i] = (LineString) readGeometry(data, srid);
+        }
+        return gf.createMultiLineString(geoms);
+    }
+
+    private MultiPolygon readMultiPolygon(final ValueGetter data, final int srid) {
+        final Polygon[] geoms = new Polygon[data.getInt()];
+        for (int i = 0; i < geoms.length; i++) {
+            geoms[i] = (Polygon) readGeometry(data, srid);
+        }
+        return gf.createMultiPolygon(geoms);
+    }
+
+    private GeometryCollection readCollection(final ValueGetter data, final int srid) {
+        final Geometry[] geoms = new Geometry[data.getInt()];
+        for (int i = 0; i < geoms.length; i++) {
+            geoms[i] = (Point) readGeometry(data, srid);
+        }
+        return gf.createGeometryCollection(geoms);
+    }
+
+}