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 3963a3a53f596a265b12722e50eaa43baab0bf25 Merge: 5c39a43 fbff2d9 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Dec 8 19:01:16 2021 +0100 Merge branch 'fix/jts3d' into geoapi-4.0 with modifications: for consistency with `Wrapper.getCoordinatesDimension(…)` expectation, replace all `new Coordinate(x,y)` by `new CoordinateXY(x,y)` in SIS code base. .../apache/sis/internal/feature/jts/Factory.java | 7 +- .../apache/sis/internal/feature/jts/Wrapper.java | 44 +++++++- .../sis/internal/feature/jts/package-info.java | 2 +- .../sis/internal/feature/jts/FactoryTest.java | 32 +++--- .../apache/sis/internal/feature/jts/JTSTest.java | 114 ++++++++++++++++++++- .../internal/filter/sqlmm/RegistryTestCase.java | 4 +- .../apache/sis/internal/map/SEPortrayerTest.java | 14 +-- 7 files changed, 183 insertions(+), 34 deletions(-) diff --cc core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Factory.java index 79478b4,79478b4..d9bc10c --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Factory.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Factory.java @@@ -33,6 -33,6 +33,7 @@@ import org.apache.sis.util.resources.Er // Optional dependencies import org.locationtech.jts.geom.Coordinate; ++import org.locationtech.jts.geom.CoordinateXY; import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@@ -54,7 -54,7 +55,7 @@@ import org.locationtech.jts.io.WKTReade * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) * @author Alexis Manin (Geomatys) -- * @version 1.1 ++ * @version 1.2 * @since 0.7 * @module */ @@@ -143,7 -143,7 +144,7 @@@ public final class Factory extends Geom */ @Override public Object createPoint(final double x, final double y) { -- return factory.createPoint(new Coordinate(x, y)); ++ return factory.createPoint(new CoordinateXY(x, y)); } /** @@@ -185,7 -185,7 +186,7 @@@ if (is3D) { c = new Coordinate(x, y, v.doubleValue(i++)); } else { -- c = new Coordinate(x, y); ++ c = new CoordinateXY(x, y); } coordList.add(c); } else { diff --cc core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java index 5892025,5c52319..47721db --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/Wrapper.java @@@ -46,6 -46,6 +46,7 @@@ import org.apache.sis.util.Debug // Optional dependencies import org.locationtech.jts.geom.Coordinate; ++import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Envelope; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryCollection; @@@ -72,7 -73,7 +73,7 @@@ import org.opengis.filter.DistanceOpera * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) * @author Alexis Manin (Geomatys) -- * @version 1.1 ++ * @version 1.2 * @since 1.1 * @module */ @@@ -152,13 -153,18 +153,50 @@@ final class Wrapper extends GeometryWra public void setCoordinateReferenceSystem(final CoordinateReferenceSystem crs) { final int dimension = ReferencingUtilities.getDimension(crs); if (dimension != Factory.BIDIMENSIONAL) { -- ArgumentChecks.ensureDimensionMatches("crs", -- (dimension <= Factory.BIDIMENSIONAL) ? Factory.BIDIMENSIONAL : 3, crs); - final int coordsDim = getCoordinatesDimension(geometry); - if (coordsDim < dimension) { - throw new MismatchedDimensionException(Errors.format( - Errors.Keys.MismatchedDimension_3, "crs", coordsDim, dimension)); - } ++ // The check for 2-dimensional case is for backward compatibility. May be temporary. ++ ArgumentChecks.ensureDimensionMatches("crs", getCoordinatesDimension(geometry), crs); } JTS.setCoordinateReferenceSystem(geometry, crs); } /** ++ * Gets the number of dimensions of geometry vertex (sequence of coordinate points), which can be 2 or 3. ++ * Note that this is different than the {@linkplain Geometry#getDimension() geometry topological dimension}, ++ * which can be 0, 1 or 2. ++ * ++ * @param geometry the geometry for which to get <em>vertex</em> (not topological) dimension. ++ * @return vertex dimension of the given geometry. ++ * @throws IllegalArgumentException if the type of the given geometry is not recognized. ++ */ ++ private static int getCoordinatesDimension(final Geometry geometry) { ++ final CoordinateSequence cs; ++ if (geometry instanceof Point) { ++ // Most efficient method (no allocation) in JTS 1.18. ++ cs = ((Point) geometry).getCoordinateSequence(); ++ } else if (geometry instanceof LineString) { ++ // Most efficient method (no allocation) in JTS 1.18. ++ cs = ((LineString) geometry).getCoordinateSequence(); ++ } else if (geometry instanceof Polygon) { ++ return getCoordinatesDimension(((Polygon) geometry).getExteriorRing()); ++ } else if (geometry instanceof GeometryCollection) { ++ final GeometryCollection gc = (GeometryCollection) geometry; ++ final int n = gc.getNumGeometries(); ++ if (n == 0) { ++ return Factory.TRIDIMENSIONAL; // Undefined coordinates, JTS assumes 3 for empty geometries. ++ } ++ for (int i=0; i<n; i++) { ++ // If at least one geometry is 3D, consider the whole geometry as 3D. ++ final int d = getCoordinatesDimension(gc.getGeometryN(i)); ++ if (d > Factory.BIDIMENSIONAL) return d; ++ } ++ return Factory.BIDIMENSIONAL; ++ } else { ++ throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1, geometry.getGeometryType())); ++ } ++ return cs.getDimension(); ++ } ++ ++ /** * Returns the envelope of the wrapped JTS geometry. Never null, but may be empty. * In current implementation, <var>z</var> values of three-dimensional envelopes * are {@link Double#NaN}. It may change in a future version if we have a way to diff --cc core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/package-info.java index 190a783,190a783..5afdd4c --- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/package-info.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/jts/package-info.java @@@ -24,7 -24,7 +24,7 @@@ * may change in incompatible ways in any future version without notice. * * @author Johann Sorel (Geomatys) -- * @version 1.0 ++ * @version 1.2 * @since 1.0 * @module */ diff --cc core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/FactoryTest.java index 323a9a5,323a9a5..0af9433 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/FactoryTest.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/FactoryTest.java @@@ -17,7 -17,7 +17,7 @@@ package org.apache.sis.internal.feature.jts; import org.apache.sis.internal.feature.GeometriesTestCase; --import org.locationtech.jts.geom.Coordinate; ++import org.locationtech.jts.geom.CoordinateXY; import org.locationtech.jts.geom.MultiLineString; import org.junit.Test; @@@ -29,7 -29,7 +29,7 @@@ import static org.junit.Assert.* * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) -- * @version 1.1 ++ * @version 1.2 * @since 1.0 * @module */ @@@ -58,16 -58,16 +58,16 @@@ public final strictfp class FactoryTes * If there is more than 2 geometries, it is caller responsibility to verify the other ones. */ private static void verifyTwoFirstGeometries(final MultiLineString mp) { -- assertArrayEquals(new Coordinate[] { -- new Coordinate(4, 5), -- new Coordinate(7, 9), -- new Coordinate(9, 3), -- new Coordinate(4, 5)}, mp.getGeometryN(0).getCoordinates()); ++ assertArrayEquals(new CoordinateXY[] { ++ new CoordinateXY(4, 5), ++ new CoordinateXY(7, 9), ++ new CoordinateXY(9, 3), ++ new CoordinateXY(4, 5)}, mp.getGeometryN(0).getCoordinates()); -- assertArrayEquals(new Coordinate[] { -- new Coordinate(-3, -2), -- new Coordinate(-2, -5), -- new Coordinate(-1, -6)}, mp.getGeometryN(1).getCoordinates()); ++ assertArrayEquals(new CoordinateXY[] { ++ new CoordinateXY(-3, -2), ++ new CoordinateXY(-2, -5), ++ new CoordinateXY(-1, -6)}, mp.getGeometryN(1).getCoordinates()); } /** @@@ -80,10 -80,10 +80,10 @@@ final MultiLineString mp = (MultiLineString) geometry; assertEquals("numGeometries", 3, mp.getNumGeometries()); verifyTwoFirstGeometries(mp); -- assertArrayEquals(new Coordinate[] { -- new Coordinate(13, 11), -- new Coordinate(14, 12), -- new Coordinate(15, 11), -- new Coordinate(13, 10)}, mp.getGeometryN(2).getCoordinates()); ++ assertArrayEquals(new CoordinateXY[] { ++ new CoordinateXY(13, 11), ++ new CoordinateXY(14, 12), ++ new CoordinateXY(15, 11), ++ new CoordinateXY(13, 10)}, mp.getGeometryN(2).getCoordinates()); } } diff --cc core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java index 3a1c386,265c58d..0e20243 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/feature/jts/JTSTest.java @@@ -17,6 -17,8 +17,7 @@@ package org.apache.sis.internal.feature.jts; import java.util.Collections; -import org.apache.sis.geometry.GeneralEnvelope; + import org.opengis.geometry.MismatchedDimensionException; import org.opengis.util.FactoryException; import org.opengis.referencing.operation.TransformException; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@@ -25,6 -28,8 +27,9 @@@ import org.locationtech.jts.geom.Coordi import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.apache.sis.referencing.CommonCRS; ++import org.apache.sis.geometry.GeneralEnvelope; + import org.apache.sis.internal.feature.Geometries; + import org.apache.sis.internal.feature.GeometryWrapper; import org.apache.sis.internal.referencing.j2d.AffineTransform2D; import org.apache.sis.test.TestCase; import org.junit.Test; @@@ -36,7 -41,7 +41,7 @@@ import static org.junit.Assert.* * Tests {@link JTS} implementation. * * @author Johann Sorel (Geomatys) -- * @version 1.0 ++ * @version 1.2 * @since 1.0 * @module */ @@@ -49,7 -54,7 +54,7 @@@ public final strictfp class JTSTest ext @Test public void testGetCoordinateReferenceSystem() throws FactoryException { final GeometryFactory factory = new GeometryFactory(); -- final Geometry geometry = factory.createPoint(new Coordinate(5, 6)); ++ final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6)); CoordinateReferenceSystem crs = JTS.getCoordinateReferenceSystem(geometry); assertNull(crs); @@@ -72,6 -77,115 +77,109 @@@ } /** - * Tests {@link Wrapper#setCoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)}. - * - * @throws FactoryException if an EPSG code can not be resolved. ++ * Tests {@link Wrapper#setCoordinateReferenceSystem(CoordinateReferenceSystem)}. + */ + @Test - public void testSetCoordinateReferenceSystem() throws FactoryException { ++ public void testSetCoordinateReferenceSystem() { + final GeometryFactory factory = new GeometryFactory(); ++ final CoordinateReferenceSystem crs2D = CommonCRS.WGS84.geographic(); ++ final CoordinateReferenceSystem crs3D = CommonCRS.WGS84.geographic3D(); + + { /* - * Test set a 2D CRS on a 2 dimensions geometry. ++ * Test setting a 2D CRS on a 2 dimensional geometry. + */ - final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic(); + final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); - wrapper.setCoordinateReferenceSystem(crs); - assertEquals(crs, wrapper.getCoordinateReferenceSystem()); ++ wrapper.setCoordinateReferenceSystem(crs2D); ++ assertEquals(crs2D, wrapper.getCoordinateReferenceSystem()); + } + + { /* - * Test set a 2D CRS on a 3 dimensions geometry. - * This case is tolerate for backward compatibility. ++ * Test setting a 2D CRS on a 3 dimensional geometry. ++ * This case is tolerated for backward compatibility. + */ - final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic(); + final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); - wrapper.setCoordinateReferenceSystem(crs); - assertEquals(crs, wrapper.getCoordinateReferenceSystem()); ++ wrapper.setCoordinateReferenceSystem(crs2D); ++ assertEquals(crs2D, wrapper.getCoordinateReferenceSystem()); + } + + { /* - * Test set a 3D CRS on a 3 dimensions geometry. ++ * Test setting a 3D CRS on a 3 dimensional geometry. + */ - final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D(); + final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); - wrapper.setCoordinateReferenceSystem(crs); - assertEquals(crs, wrapper.getCoordinateReferenceSystem()); ++ wrapper.setCoordinateReferenceSystem(crs3D); ++ assertEquals(crs3D, wrapper.getCoordinateReferenceSystem()); + } + + { /* - * Test set a 3D CRS on a 2 dimensions geometry. ++ * Test setting a 3D CRS on a 2 dimensional geometry. + */ - final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D(); + final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6)); - GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); ++ final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); + try { - wrapper.setCoordinateReferenceSystem(crs); - fail("Setting a 3D crs on a 2D geometry must fail"); ++ wrapper.setCoordinateReferenceSystem(crs3D); ++ fail("Setting a 3D crs on a 2D geometry must fail."); + } catch (MismatchedDimensionException ex) { - //ok ++ assertTrue(ex.getMessage().contains("crs")); ++ // ok + } + } + } + + /** + * Tests {@link Wrapper#getEnvelope()}. - * - * @throws FactoryException if an EPSG code can not be resolved. + */ + @Test - public void testGetEnvelope() throws FactoryException { ++ public void testGetEnvelope() { + final GeometryFactory factory = new GeometryFactory(); + + { /* - * Test 2D Envelope on a 2 dimensions geometry. ++ * Test 2D Envelope on a 2 dimensional geometry. + */ - final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic(); ++ final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic(); + final Geometry geometry = factory.createPoint(new CoordinateXY(5, 6)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); + wrapper.setCoordinateReferenceSystem(crs); + final GeneralEnvelope envelope = wrapper.getEnvelope(); + assertEquals(crs, envelope.getCoordinateReferenceSystem()); - assertArrayEquals(new double[]{5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT); - assertArrayEquals(new double[]{5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT); ++ assertArrayEquals(new double[] {5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT); ++ assertArrayEquals(new double[] {5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT); + } + + { /* - * Test 2D Envelope on a 3 dimensions geometry. - * This case is tolerate for backward compatibility. ++ * Test 2D Envelope on a 3 dimensional geometry. ++ * This case is tolerated for backward compatibility. + */ - final CoordinateReferenceSystem crs = CommonCRS.ED50.geographic(); ++ final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic(); + final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); + wrapper.setCoordinateReferenceSystem(crs); + final GeneralEnvelope envelope = wrapper.getEnvelope(); + assertEquals(crs, envelope.getCoordinateReferenceSystem()); - assertArrayEquals(new double[]{5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT); - assertArrayEquals(new double[]{5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT); ++ assertArrayEquals(new double[] {5, 6}, envelope.getLowerCorner().getCoordinate(), STRICT); ++ assertArrayEquals(new double[] {5, 6}, envelope.getUpperCorner().getCoordinate(), STRICT); + } + + { /* - * Test 3D Envelope on a 3 dimensions geometry. - * TODO : JTS do not return 3D envelopes for geoemtry internal envelope - * should we loop on the full geometry ? ++ * Test 3D Envelope on a 3 dimensional geometry. ++ * ++ * TODO: JTS does not set the Z values for geometry internal envelope. ++ * Should we loop over all coordinates in the geometry? + */ - /* + final CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic3D(); + final Geometry geometry = factory.createPoint(new Coordinate(5, 6, 7)); + final GeometryWrapper<?> wrapper = Geometries.wrap(geometry).get(); + wrapper.setCoordinateReferenceSystem(crs); + final GeneralEnvelope envelope = wrapper.getEnvelope(); + assertEquals(crs, envelope.getCoordinateReferenceSystem()); - assertArrayEquals(new double[]{5, 6, 7}, envelope.getLowerCorner().getCoordinate(), STRICT); - assertArrayEquals(new double[]{5, 6, 7}, envelope.getUpperCorner().getCoordinate(), STRICT); - */ ++ assertArrayEquals(new double[] {5, 6, Double.NaN}, envelope.getLowerCorner().getCoordinate(), STRICT); ++ assertArrayEquals(new double[] {5, 6, Double.NaN}, envelope.getUpperCorner().getCoordinate(), STRICT); + } + } + + /** * Tests various {@code transform} methods. This includes (sometime indirectly): * * <ul> @@@ -86,7 -200,7 +194,7 @@@ @Test public void testTransform() throws FactoryException, TransformException { final GeometryFactory factory = new GeometryFactory(); -- final Geometry in = factory.createPoint(new Coordinate(5, 6)); ++ final Geometry in = factory.createPoint(new CoordinateXY(5, 6)); /* * Test transforming geometry without CRS. */ diff --cc core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java index d9c3f4f,d9c3f4f..9974d1a --- a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/sqlmm/RegistryTestCase.java @@@ -58,7 -58,7 +58,7 @@@ import org.opengis.filter.ValueReferenc * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) -- * @version 1.1 ++ * @version 1.2 * * @param <G> root class of geometry implementation. * @@@ -176,7 -176,7 +176,7 @@@ public abstract strictfp class Registry } /** -- * Creates a function where all parameters are literal values, the evaluate the function. ++ * Creates a function where all parameters are literal values, then evaluate the function. * The function is stored in the {@link #function} field. * * @param name name of the function to create. diff --cc core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java index d35ca20,d35ca20..53ed11d --- a/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java +++ b/core/sis-portrayal/src/test/java/org/apache/sis/internal/map/SEPortrayerTest.java @@@ -51,7 -51,7 +51,7 @@@ import org.apache.sis.test.TestCase import org.apache.sis.util.iso.Names; import static org.junit.Assert.*; import org.junit.Test; --import org.locationtech.jts.geom.Coordinate; ++import org.locationtech.jts.geom.CoordinateXY; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; @@@ -91,14 -91,14 +91,14 @@@ public class SEPortrayerTest extends Te fishbuilder.addAttribute(String.class).setName("description"); final FeatureType fishType = fishbuilder.build(); -- final Point point1 = gf.createPoint(new Coordinate(0, 0)); ++ final Point point1 = gf.createPoint(new CoordinateXY(0, 0)); point1.setUserData(crs); final Feature fish1 = fishType.newInstance(); fish1.setPropertyValue("id", "1"); fish1.setPropertyValue("geom", point1); fish1.setPropertyValue("description", "A red fish"); -- final Point point2 = gf.createPoint(new Coordinate(10, 20)); ++ final Point point2 = gf.createPoint(new CoordinateXY(10, 20)); point2.setUserData(crs); final Feature fish2 = fishType.newInstance(); fish2.setPropertyValue("id", "2"); @@@ -113,7 -113,7 +113,7 @@@ sharkbuilder.addAttribute(Double.class).setName("length"); final FeatureType sharkType = sharkbuilder.build(); -- final Point point3 = gf.createPoint(new Coordinate(30, 40)); ++ final Point point3 = gf.createPoint(new CoordinateXY(30, 40)); point3.setUserData(crs); final Feature shark1 = sharkType.newInstance(); shark1.setPropertyValue("id", "100"); @@@ -131,14 -131,14 +131,16 @@@ boatbuilder.addAttribute(String.class).setName("description"); final FeatureType boatType = boatbuilder.build(); -- final Polygon poly1 = gf.createPolygon(gf.createLinearRing(new Coordinate[]{new Coordinate(0, 0),new Coordinate(0, 1),new Coordinate(1, 1),new Coordinate(0, 0)})); ++ final Polygon poly1 = gf.createPolygon(gf.createLinearRing(new CoordinateXY[] { ++ new CoordinateXY(0, 0), new CoordinateXY(0, 1), new CoordinateXY(1, 1), new CoordinateXY(0, 0)})); poly1.setUserData(crs); final Feature boat1 = boatType.newInstance(); boat1.setPropertyValue("id", "10"); boat1.setPropertyValue("geom", poly1); boat1.setPropertyValue("description", "A fishing boat"); -- final Polygon poly2 = gf.createPolygon(gf.createLinearRing(new Coordinate[]{new Coordinate(0, 0),new Coordinate(0, 1),new Coordinate(1, 1),new Coordinate(0, 0)})); ++ final Polygon poly2 = gf.createPolygon(gf.createLinearRing(new CoordinateXY[] { ++ new CoordinateXY(0, 0), new CoordinateXY(0, 1), new CoordinateXY(1, 1), new CoordinateXY(0, 0)})); poly2.setUserData(crs); final Feature boat2 = boatType.newInstance(); boat2.setPropertyValue("id", "20");