This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 2b14e1bac60d9d6deb7fcd4084977891fcd065f4 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Aug 12 13:24:26 2024 +0200 Recognize more geometry types in SQL database. Derived from fixes by Johann Sorel. --- .../apache/sis/geometry/wrapper/GeometryType.java | 178 ++++++++++++++++----- .../apache/sis/geometry/wrapper/esri/Factory.java | 2 +- .../apache/sis/geometry/wrapper/j2d/Factory.java | 2 +- .../sis/geometry/wrapper/GeometryTypeTest.java | 25 ++- .../apache/sis/storage/sql/feature/Database.java | 2 +- .../sis/storage/sql/feature/SpatialSchema.java | 5 +- 6 files changed, 163 insertions(+), 51 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryType.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryType.java index bfdb51bfef..b338f9e50e 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryType.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/GeometryType.java @@ -29,6 +29,7 @@ import org.apache.sis.util.privy.Constants; /** * Implementation-neutral description of the type of geometry. * The name of each enumeration value is the name in WKT format. + * The ordinal value is the binary code, ignoring thousands. * * @author Martin Desruisseaux (Geomatys) * @@ -40,7 +41,7 @@ public enum GeometryType { * * @see Geometries#rootClass */ - GEOMETRY("Geometry"), + GEOMETRY("Geometry", false), /** * Zero-dimensional geometry containing a single point. @@ -49,7 +50,7 @@ public enum GeometryType { * * @see Geometries#pointClass */ - POINT("Point"), + POINT("Point", false), /** * Sequence of points connected by straight, non-self intersecting line pieces. @@ -57,7 +58,7 @@ public enum GeometryType { * * @see Geometries#polylineClass */ - LINESTRING("LineString"), + LINESTRING("LineString", false), /** * Geometry with a positive area (two-dimensional). @@ -65,27 +66,123 @@ public enum GeometryType { * * @see Geometries#polygonClass */ - POLYGON("Polygon"), + POLYGON("Polygon", false), /** * Set of points. */ - MULTIPOINT("MultiPoint"), + MULTIPOINT("MultiPoint", true), /** - * Set of linestrings. + * Set of line strings. */ - MULTILINESTRING("MultiLineString"), + MULTILINESTRING("MultiLineString", true), /** * Set of polygons. */ - MULTIPOLYGON("MultiPolygon"), + MULTIPOLYGON("MultiPolygon", true), /** * Set of geometries of any type except other geometry collection. */ - GEOMETRYCOLLECTION("GeometryCollection"); + GEOMETRYCOLLECTION("GeometryCollection", true), + + /** + * Curve with circular interpolation between points. + */ + CIRCULARSTRING("CircularString", false), + + /** + * Contiguous curves such that adjacent curves are joined at their end points. + */ + COMPOUNDCURVE("CompoundCurve", true), + + /** + * Planar surface consisting of a single patch. + */ + CURVEPOLYGON("CurvePolygon", false), + + /** + * Geometry collection made of curves. + */ + MULTICURVE("MultiCurve", true), + + /** + * Geometry collection made of surfaces. + */ + MULTISURFACE("MultiSurface", true), + + /** + * 1-dimensional geometry usually stored as a sequence of points. + * The subtype specifies the form of the interpolation between points. + */ + CURVE("Curve", false), + + /** + * 2-dimensional geometry associated with one exterior ring and zero or more interior rings. + */ + SURFACE("Surface", false), + + /** + * Surface composed of contiguous surfaces connected along their common boundary. + */ + POLYHEDRALSURFACE("PolyhedralSurface", true), + + /** + * Polyhedral surface composed only of triangles. + */ + TIN("Tin", true), + + /** + * Polygon with exactly four points (the last point being the same as the first point). + */ + TRIANGLE("Triangle", false), + + /** + * A circular curve in which the last point is the same as the first point. + */ + CIRCLE("Circle", false), + + /** + * Curve for the shortest distance on a sphere or ellipsoid. + */ + GEODESICSTRING("GeodesicString", false), + + /** + * Elliptical curve. + */ + ELLIPTICALCURVE("EllipticalCurve", false), + + /** + * Nurbs curve. + */ + NURBSCURVE("NurbsCurve", false), + + /** + * Clothoid. + */ + CLOTHOID("Clothoid", false), + + /** + * Curve describing a spiral. + */ + SPIRALCURVE("SpiralCurve", false), + + /** + * Surface made of other surfaces. + */ + COMPOUNDSURFACE("CompoundSurface", true), + + /** + * Brep solid. + */ + BREPSOLID("BrepSolid", false); + + /** + * All enumeration values, fetched at construction time for avoiding array copies. + */ + private static final GeometryType[] VALUES = values(); /** * Camel-case name of this geometry type. @@ -93,6 +190,13 @@ public enum GeometryType { */ public final String name; + /** + * Whether this geometry type is some sort of collection. + * Some of those types are {@link #MULTIPOINT}, {@link #MULTILINESTRING}, + * {@link #MULTIPOLYGON} or {@link #GEOMETRYCOLLECTION}. + */ + public final boolean isCollection; + /** * The geometry types as ISO 19103 type names, created when first needed. * For a given enumeration value, all {@code typeNames} values are identical @@ -111,9 +215,11 @@ public enum GeometryType { * Creates a new enumeration value. * * @param name camel-case name of the geometry. + * @param isCollection whether this geometry type is some sort of collection. */ - private GeometryType(final String name) { + private GeometryType(final String name, final boolean isCollection) { this.name = name; + this.isCollection = isCollection; typeNames = new EnumMap<>(GeometryLibrary.class); } @@ -167,14 +273,22 @@ public enum GeometryType { } /** - * Returns {@code true} if this geometry type is some sort of collection. - * Those types are {@link #MULTIPOINT}, {@link #MULTILINESTRING}, - * {@link #MULTIPOLYGON} or {@link #GEOMETRYCOLLECTION}. + * Returns the enumeration value for the given WKB type, or {@code null} if unknown. + * Types for geometries having <var>Z</var> and <var>M</var> are replaced by 2D types. * - * @return whether this geometry type is some kind of collections. + * @param type WKB geometry type. + * @return enumeration value for the given type, or {@code null} if the given type is not recognized. + * + * @see #binaryType() */ - public final boolean isCollection() { - return ordinal() >= MULTIPOINT.ordinal(); + public static GeometryType forBinaryType(int type) { + if (type >= 1000 && type < 4000) { + type %= 1000; + } + if (type >= 0 && type < VALUES.length) { + return VALUES[type]; + } + return null; } /** @@ -204,31 +318,17 @@ public enum GeometryType { } /** - * Returns the enumeration value for the given WKB type, or {@code null} if unknown. - * Types for geometries having <var>Z</var> and <var>M</var> are replaced by 2D types. + * Returns {@code true} if the given name is one of the enumerated geometry types, ignoring case. * - * @param type WKB geometry type. - * @return enumeration value for the given type, or {@code null} if the given type is not recognized. - * - * @see #binaryType() + * @param name the name to test. + * @return whether the given name is one of the enumerated geometry types, ignoring case. */ - public static GeometryType forBinaryType(int type) { - if (type >= 1000 && type < 4000) { - type %= 1000; - } - switch (type) { - default: return null; - case 0: return GEOMETRY; - case 1: return POINT; - case 2: return LINESTRING; - case 3: return POLYGON; - case 4: return MULTIPOINT; - case 5: return MULTILINESTRING; - case 6: return MULTIPOLYGON; - case 7: return GEOMETRYCOLLECTION; - // case 13: return CURVE; - // case 14: return SURFACE; - // case 15: return POLYHEDRALSURFACE; + public static boolean isKnown(final String name) { + for (GeometryType value : VALUES) { + if (value.name().equalsIgnoreCase(name)) { + return true; + } } + return false; } } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/esri/Factory.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/esri/Factory.java index 0b513f3691..856966f9ba 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/esri/Factory.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/esri/Factory.java @@ -251,7 +251,7 @@ public final class Factory extends Geometries<Geometry> { } if (geometry == null) { final MultiPath path = isPolygon ? new Polygon() : new Polyline(); - if (type.isCollection()) { + if (type.isCollection) { for (final Object component : data) { path.add((MultiPath) component, false); } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/j2d/Factory.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/j2d/Factory.java index 35e01829ba..d8b831efd0 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/j2d/Factory.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/geometry/wrapper/j2d/Factory.java @@ -288,7 +288,7 @@ public final class Factory extends Geometries<Shape> { if (!isFloat) break; } final Path2D path = createPath(isFloat, 20); - if (type.isCollection()) { + if (type.isCollection) { for (final Object component : data) { path.append((Shape) component, false); } diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/GeometryTypeTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/GeometryTypeTest.java index 94d06fa593..b28426063d 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/GeometryTypeTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/geometry/wrapper/GeometryTypeTest.java @@ -62,13 +62,24 @@ public final class GeometryTypeTest extends TestCase { } /** - * Tests {@link GeometryType#forBinaryType(int)} and verifies {@link GeometryType#binaryType()} values. + * Tests {@link GeometryType#forBinaryType(int)}. */ @Test - public void testBinaryType() { - for (final GeometryType type : GeometryType.values()) { - assertSame(type, GeometryType.forBinaryType(type.binaryType()), type.name()); - } + public void testForBinaryType() { + assertSame(GeometryType.GEOMETRY, GeometryType.forBinaryType( 0)); + assertSame(GeometryType.POINT, GeometryType.forBinaryType( 1)); + assertSame(GeometryType.LINESTRING, GeometryType.forBinaryType( 2)); + assertSame(GeometryType.POLYGON, GeometryType.forBinaryType( 3)); + assertSame(GeometryType.MULTIPOINT, GeometryType.forBinaryType( 4)); + assertSame(GeometryType.MULTILINESTRING, GeometryType.forBinaryType( 5)); + assertSame(GeometryType.MULTIPOLYGON, GeometryType.forBinaryType( 6)); + assertSame(GeometryType.GEOMETRYCOLLECTION, GeometryType.forBinaryType( 7)); + assertSame(GeometryType.CURVE, GeometryType.forBinaryType(13)); + assertSame(GeometryType.SURFACE, GeometryType.forBinaryType(14)); + assertSame(GeometryType.POLYHEDRALSURFACE, GeometryType.forBinaryType(15)); + assertSame(GeometryType.TRIANGLE, GeometryType.forBinaryType(17)); + assertSame(GeometryType.GEODESICSTRING, GeometryType.forBinaryType(19)); + assertSame(GeometryType.BREPSOLID, GeometryType.forBinaryType(25)); } /** @@ -76,8 +87,8 @@ public final class GeometryTypeTest extends TestCase { */ @Test public void testForName() { - assertSame(GeometryType.MULTIPOLYGON, GeometryType.forName("multi_Polygon")); - assertSame(GeometryType.MULTIPOLYGON, GeometryType.forName("MULTIPOLYGON")); + assertSame(GeometryType.MULTIPOLYGON, GeometryType.forName("multi_Polygon")); + assertSame(GeometryType.MULTIPOLYGON, GeometryType.forName("MULTIPOLYGON")); assertSame(GeometryType.GEOMETRYCOLLECTION, GeometryType.forName("GEOMETRY_COLLECTION")); assertSame(GeometryType.GEOMETRYCOLLECTION, GeometryType.forName("GeomCollection")); } diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java index 71503d3fd3..379a96a11a 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java @@ -584,7 +584,7 @@ public class Database<G> extends Syntax { */ @SuppressWarnings("fallthrough") protected ValueGetter<?> getMapping(final Column columnDefinition) { - if ("geometry".equalsIgnoreCase(columnDefinition.typeName)) { + if (GeometryType.isKnown(columnDefinition.typeName)) { return forGeometry(columnDefinition); } switch (columnDefinition.type) { diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java index 857530ca9b..a20176fc5b 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java @@ -35,10 +35,11 @@ package org.apache.sis.storage.sql.feature; public enum SpatialSchema { /** * Table and column names as specified by Geopackage. This is the same thing as {@link #SQL_MM} - * except for table names and for the case (Geopackage uses lower case). + * except for table names, for the case (Geopackage uses lower case) and for the addition of a + * {@code geometry_type_name} column. */ GEOPACKAGE("gpkg_spatial_ref_sys", "srs_id", "organization", "organization_coordsys_id", "definition", - "gpkg_geometry_columns", "table_catalog", "table_schema", "table_name", "column_name", null), + "gpkg_geometry_columns", "table_catalog", "table_schema", "table_name", "column_name", "geometry_type_name"), /** * Table and column names as specified by ISO-13249 SQL/MM. This is the same thing as {@link #SIMPLE_FEATURE}