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

asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 26a370725f feat(Geometry): add method to map SIS geometry as JTS
26a370725f is described below

commit 26a370725f427033e640fd178859324504159f1c
Author: jsorel <[email protected]>
AuthorDate: Wed Aug 26 12:12:01 2026 +0200

    feat(Geometry): add method to map SIS geometry as JTS
---
 .../main/org/apache/sis/geometries/Geometries.java |  89 +----
 .../org/apache/sis/geometries/PointSequence.java   |  10 +-
 .../apache/sis/geometries/adapter/JTSAdapter.java  | 438 +++++++++++++++++++++
 .../geometries/operation/GeometryProcessor.java    |   4 +-
 4 files changed, 455 insertions(+), 86 deletions(-)

diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
index 44935dfb4a..4669d5dadf 100644
--- 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/Geometries.java
@@ -30,6 +30,7 @@ import java.util.Map.Entry;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.CoordinateSequence;
 import javax.measure.Unit;
+import org.apache.sis.geometries.adapter.JTSAdapter;
 import org.opengis.geometry.Envelope;
 import org.opengis.referencing.IdentifiedObject;
 import static org.opengis.referencing.IdentifiedObject.ALIAS_KEY;
@@ -42,19 +43,16 @@ import org.opengis.referencing.datum.EngineeringDatum;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.util.FactoryException;
 import org.opengis.util.InternationalString;
-import org.apache.sis.geometries.math.DataType;
 import org.apache.sis.geometries.math.SampleSystem;
 import org.apache.sis.geometries.math.Tuple;
 import org.apache.sis.geometries.math.NDArrays;
 import org.apache.sis.geometries.math.Vector;
 import org.apache.sis.geometries.math.Vector3D;
 import org.apache.sis.geometries.math.Vectors;
-import org.apache.sis.geometries.math.Cursor;
 import org.apache.sis.geometries.math.Array;
 import org.apache.sis.geometries.math.Matrix3D;
 import org.apache.sis.geometries.mesh.MeshPrimitive;
 import org.apache.sis.geometries.mesh.MultiMeshPrimitive;
-import org.apache.sis.geometries.internal.shared.ArraySequence;
 import org.apache.sis.geometry.wrapper.jts.JTS;
 import org.apache.sis.measure.Units;
 import org.apache.sis.referencing.CRS;
@@ -712,87 +710,20 @@ public final class Geometries {
 
     /**
      * Convert given JTS geometry to SIS Geometry.
+     * @param copy if true create a copy of the coordinate sequence, otherwise 
create a view
      */
-    public static Geometry fromJTS(org.locationtech.jts.geom.Geometry jts) {
-        if (jts == null) {
-            return null;
-        }
-        CoordinateReferenceSystem crs = 
org.apache.sis.geometry.wrapper.Geometries.wrap(jts).get().getCoordinateReferenceSystem();
-        if (crs == null) crs = Geometries.getUndefinedCRS(2);
-        return fromJTS(jts, crs);
+    public static Geometry fromJTS(org.locationtech.jts.geom.Geometry jts, 
boolean copy) {
+        return JTSAdapter.fromJTS(jts, copy);
     }
 
     /**
-     * Convert given JTS geometry to SIS Geometry.
-     */
-    private static Geometry fromJTS(org.locationtech.jts.geom.Geometry jts, 
CoordinateReferenceSystem crs) {
-        if (jts == null) {
-            return null;
-        } else if (jts instanceof org.locationtech.jts.geom.Point cdt) {
-            return 
GeometryFactory.createPoint(toPointSequence(cdt.getCoordinateSequence(), crs));
-
-        } else if (jts instanceof org.locationtech.jts.geom.MultiPoint cdt) {
-            return 
GeometryFactory.createMultiPoint(toPointSequence(jts.getFactory().getCoordinateSequenceFactory().create(cdt.getCoordinates()),
 crs));
-
-        } else if (jts instanceof org.locationtech.jts.geom.LinearRing cdt) {
-            return 
GeometryFactory.createLinearRing(toPointSequence(cdt.getCoordinateSequence(), 
crs));
-
-        } else if (jts instanceof org.locationtech.jts.geom.LineString cdt) {
-            return 
GeometryFactory.createLineString(toPointSequence(cdt.getCoordinateSequence(), 
crs));
-
-        } else if (jts instanceof org.locationtech.jts.geom.MultiLineString 
cdt) {
-            final LineString[] strings = new 
LineString[cdt.getNumGeometries()];
-            for (int i = 0; i < strings.length; i++) {
-                strings[i] = (LineString) fromJTS(cdt.getGeometryN(i), crs);
-            }
-            return GeometryFactory.createMultiLineString(strings);
-        } else if (jts instanceof org.locationtech.jts.geom.Polygon cdt) {
-            final LinearRing exterior = (LinearRing) 
fromJTS(cdt.getExteriorRing(), crs);
-            final List<LinearRing> interiors = new 
ArrayList<>(cdt.getNumInteriorRing());
-            for (int i = 0, n = cdt.getNumInteriorRing(); i < n; i++) {
-                interiors.add((LinearRing) fromJTS(cdt.getInteriorRingN(i), 
crs));
-            }
-            return GeometryFactory.createPolygon(exterior, interiors);
-
-        } else if (jts instanceof org.locationtech.jts.geom.MultiPolygon cdt) {
-            final Surface[] geoms = new Surface[cdt.getNumGeometries()];
-            for (int i = 0; i < geoms.length; i++) {
-                geoms[i] = (Surface) fromJTS(cdt.getGeometryN(i), crs);
-            }
-            return GeometryFactory.createMultiSurface(geoms);
-
-        } else if (jts instanceof org.locationtech.jts.geom.GeometryCollection 
cdt) {
-            final Geometry[] geoms = new Geometry[cdt.getNumGeometries()];
-            for (int i = 0; i < geoms.length; i++) {
-                geoms[i] = fromJTS(cdt.getGeometryN(i), crs);
-            }
-            return GeometryFactory.createGeometryCollection(geoms);
-
-        } else {
-            throw new IllegalArgumentException("Unknown JTS geometry type");
-        }
-    }
-
-    /**
-     * Convert JTS coordinate sequence to SIS PointSequence.
+     * View a geometry as a JTS geometry.
+     *
+     * @param copy if true create a copy of the point sequence, otherwise 
create a view
+     * @return JTS equivalent
      */
-    private static PointSequence toPointSequence(CoordinateSequence cs, 
CoordinateReferenceSystem crs) {
-        final int size = cs.size();
-        final int dimension = crs.getCoordinateSystem().getDimension();
-        final Array positions = NDArrays.of(SampleSystem.of(crs), 
DataType.DOUBLE, size);
-        final Cursor cursor = positions.cursor();
-        int i = 0;
-        while (cursor.next()) {
-            final Tuple samples = cursor.samples();
-            samples.set(0, cs.getOrdinate(i, 0));
-            samples.set(1, cs.getOrdinate(i, 1));
-            if (dimension > 2) {
-                //JTS only goes up to 3 dimensions
-                samples.set(2, cs.getOrdinate(i, 2));
-            }
-            i++;
-        }
-        return new ArraySequence(positions);
+    public static org.locationtech.jts.geom.Geometry asJTS(Geometry geom, 
boolean copy, org.locationtech.jts.geom.GeometryFactory gf) {
+        return JTSAdapter.asJTS(geom, copy, gf);
     }
 
 }
diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/PointSequence.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/PointSequence.java
index e2d93fbabb..b217d3bbda 100644
--- 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/PointSequence.java
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/PointSequence.java
@@ -23,7 +23,6 @@ import org.apache.sis.geometries.math.DataType;
 import org.apache.sis.geometries.math.Tuple;
 import org.apache.sis.geometries.math.NDArrays;
 import org.apache.sis.geometries.math.Array;
-import org.apache.sis.geometry.GeneralEnvelope;
 
 
 /**
@@ -86,7 +85,7 @@ public interface PointSequence {
      * @param index searched index
      * @return copy of the position
      */
-    Tuple getPosition(int index);
+    Tuple<?> getPosition(int index);
 
     /**
      * Set position attribute value.
@@ -94,7 +93,7 @@ public interface PointSequence {
      * @param index searched index
      * @param value new attribute value
      */
-    void setPosition(int index, Tuple value);
+    void setPosition(int index, Tuple<?> value);
 
     /**
      * Get attribute value.
@@ -103,7 +102,7 @@ public interface PointSequence {
      * @param name attribute name
      * @return copy of the attribute
      */
-    Tuple getAttribute(int index, String name);
+    Tuple<?> getAttribute(int index, String name);
 
     /**
      * Set attribute value.
@@ -112,7 +111,7 @@ public interface PointSequence {
      * @param name attribute name
      * @param value new attribute value
      */
-    void setAttribute(int index, String name, Tuple value);
+    void setAttribute(int index, String name, Tuple<?> value);
 
     /**
      * Get all attribute values as a TupleArray.
@@ -135,6 +134,7 @@ public interface PointSequence {
     /**
      * Get attribute values range
      *
+     * @param name
      * @return BBox in attribute sample system
      */
     default BBox getAttributeRange(String name) {
diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/JTSAdapter.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/JTSAdapter.java
new file mode 100644
index 0000000000..78e2462072
--- /dev/null
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/adapter/JTSAdapter.java
@@ -0,0 +1,438 @@
+/*
+ * 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.geometries.adapter;
+
+import org.apache.sis.geometries.*;
+import java.util.ArrayList;
+import java.util.List;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.CoordinateSequence;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.geometries.math.DataType;
+import org.apache.sis.geometries.math.SampleSystem;
+import org.apache.sis.geometries.math.Tuple;
+import org.apache.sis.geometries.math.NDArrays;
+import org.apache.sis.geometries.math.Vector;
+import org.apache.sis.geometries.math.Vectors;
+import org.apache.sis.geometries.math.Cursor;
+import org.apache.sis.geometries.math.Array;
+import org.apache.sis.geometries.internal.shared.ArraySequence;
+import org.locationtech.jts.geom.CoordinateXY;
+
+
+/**
+ * Mesh geometry utilities.
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+public final class JTSAdapter {
+
+    /**
+     * Convert given JTS geometry to SIS Geometry.
+     * @param copy if true create a copy of the coordinate sequence, otherwise 
create a view
+     */
+    public static Geometry fromJTS(org.locationtech.jts.geom.Geometry jts, 
boolean copy) {
+        if (jts == null) {
+            return null;
+        }
+        CoordinateReferenceSystem crs = 
org.apache.sis.geometry.wrapper.Geometries.wrap(jts).get().getCoordinateReferenceSystem();
+        if (crs == null) crs = Geometries.getUndefinedCRS(2);
+        return fromJTS(jts, crs, copy);
+    }
+
+    /**
+     * Convert given JTS geometry to SIS Geometry.
+     * @param copy if true create a copy of the coordinate sequence, otherwise 
create a view
+     */
+    private static Geometry fromJTS(org.locationtech.jts.geom.Geometry jts, 
CoordinateReferenceSystem crs, boolean copy) {
+        if (jts == null) {
+            return null;
+        } else if (jts instanceof org.locationtech.jts.geom.Point cdt) {
+            return 
GeometryFactory.createPoint(toPointSequence(cdt.getCoordinateSequence(), crs, 
copy));
+
+        } else if (jts instanceof org.locationtech.jts.geom.MultiPoint cdt) {
+            return 
GeometryFactory.createMultiPoint(toPointSequence(jts.getFactory().getCoordinateSequenceFactory().create(cdt.getCoordinates()),
 crs, copy));
+
+        } else if (jts instanceof org.locationtech.jts.geom.LinearRing cdt) {
+            return 
GeometryFactory.createLinearRing(toPointSequence(cdt.getCoordinateSequence(), 
crs, copy));
+
+        } else if (jts instanceof org.locationtech.jts.geom.LineString cdt) {
+            return 
GeometryFactory.createLineString(toPointSequence(cdt.getCoordinateSequence(), 
crs, copy));
+
+        } else if (jts instanceof org.locationtech.jts.geom.MultiLineString 
cdt) {
+            final LineString[] strings = new 
LineString[cdt.getNumGeometries()];
+            for (int i = 0; i < strings.length; i++) {
+                strings[i] = (LineString) fromJTS(cdt.getGeometryN(i), crs, 
copy);
+            }
+            return GeometryFactory.createMultiLineString(strings);
+        } else if (jts instanceof org.locationtech.jts.geom.Polygon cdt) {
+            final LinearRing exterior = (LinearRing) 
fromJTS(cdt.getExteriorRing(), crs, copy);
+            final List<LinearRing> interiors = new 
ArrayList<>(cdt.getNumInteriorRing());
+            for (int i = 0, n = cdt.getNumInteriorRing(); i < n; i++) {
+                interiors.add((LinearRing) fromJTS(cdt.getInteriorRingN(i), 
crs, copy));
+            }
+            return GeometryFactory.createPolygon(exterior, interiors);
+
+        } else if (jts instanceof org.locationtech.jts.geom.MultiPolygon cdt) {
+            final Surface[] geoms = new Surface[cdt.getNumGeometries()];
+            for (int i = 0; i < geoms.length; i++) {
+                geoms[i] = (Surface) fromJTS(cdt.getGeometryN(i), crs, copy);
+            }
+            return GeometryFactory.createMultiSurface(geoms);
+
+        } else if (jts instanceof org.locationtech.jts.geom.GeometryCollection 
cdt) {
+            final Geometry[] geoms = new Geometry[cdt.getNumGeometries()];
+            for (int i = 0; i < geoms.length; i++) {
+                geoms[i] = fromJTS(cdt.getGeometryN(i), crs, copy);
+            }
+            return GeometryFactory.createGeometryCollection(geoms);
+
+        } else {
+            throw new IllegalArgumentException("Unknown JTS geometry type");
+        }
+    }
+
+    /**
+     * View a geometry as a JTS geometry.
+     *
+     * @param copy if true create a copy of the point sequence, otherwise 
create a view
+     * @return JTS equivalent
+     */
+    public static org.locationtech.jts.geom.Geometry asJTS(Geometry geom, 
boolean copy, org.locationtech.jts.geom.GeometryFactory gf) {
+
+        final org.locationtech.jts.geom.Geometry jts;
+
+        if (geom == null) {
+            return null;
+        } else if (geom instanceof Point cdt) {
+            final CoordinateSequence cs = 
toCoordinateSequence(cdt.asPointSequence(), copy, gf);
+            jts = new org.locationtech.jts.geom.Point(cs, gf);
+        } else if (geom instanceof MultiPoint cdt) {
+            final CoordinateSequence cs = 
toCoordinateSequence(cdt.asPointSequence(), copy, gf);
+            jts = gf.createMultiPoint(cs);
+        } else if (geom instanceof LinearRing cdt) {
+            final CoordinateSequence cs = 
toCoordinateSequence(cdt.getPoints(), copy, gf);
+            jts = new org.locationtech.jts.geom.LinearRing(cs, gf);
+        } else if (geom instanceof LineString cdt) {
+            final CoordinateSequence cs = 
toCoordinateSequence(cdt.getPoints(), copy, gf);
+            jts = new org.locationtech.jts.geom.LineString(cs, gf);
+        } else if (geom instanceof MultiLineString cdt) {
+            final org.locationtech.jts.geom.LineString[] children = new 
org.locationtech.jts.geom.LineString[cdt.getNumGeometries()];
+            for (int i = 0; i < children.length; i++) {
+                children[i] = (org.locationtech.jts.geom.LineString) 
asJTS(cdt.getGeometryN(i), copy, gf);
+            }
+            jts = gf.createMultiLineString(children);
+        } else if (geom instanceof Polygon cdt) {
+
+            final org.locationtech.jts.geom.LinearRing exterior = 
(org.locationtech.jts.geom.LinearRing) asJTS(cdt.getExteriorRing(), copy, gf);
+            final org.locationtech.jts.geom.LinearRing[] children = new 
org.locationtech.jts.geom.LinearRing[cdt.getNumInteriorRing()];
+            for (int i = 0; i < children.length; i++) {
+                children[i] = (org.locationtech.jts.geom.LinearRing) 
asJTS(cdt.getInteriorRingN(i), copy, gf);
+            }
+            jts = gf.createPolygon(exterior, children);
+        } else if (geom instanceof MultiPolygon cdt) {
+            final org.locationtech.jts.geom.Polygon[] children = new 
org.locationtech.jts.geom.Polygon[cdt.getNumGeometries()];
+            for (int i = 0; i < children.length; i++) {
+                children[i] = (org.locationtech.jts.geom.Polygon) 
asJTS(cdt.getGeometryN(i), copy, gf);
+            }
+            jts = gf.createMultiPolygon(children);
+        } else if (geom instanceof GeometryCollection cdt) {
+            final org.locationtech.jts.geom.Geometry[] children = new 
org.locationtech.jts.geom.Geometry[cdt.getNumGeometries()];
+            for (int i = 0; i < children.length; i++) {
+                children[i] = asJTS(cdt.getGeometryN(i), copy, gf);
+            }
+            jts = gf.createGeometryCollection(children);
+        } else {
+            throw new IllegalArgumentException("Unsupported geometry " + 
geom.getClass().getName());
+        }
+
+        jts.setUserData(geom.getCoordinateReferenceSystem());
+        return jts;
+    }
+
+    /**
+     * Convert JTS coordinate sequence to SIS PointSequence.
+     * @param copy if true create a copy of the coordinate sequence, otherwise 
create a view
+     */
+    private static PointSequence toPointSequence(CoordinateSequence cs, 
CoordinateReferenceSystem crs, boolean copy) {
+        final int size = cs.size();
+        final int dimension = crs.getCoordinateSystem().getDimension();
+
+        if (copy) {
+            final Array positions = NDArrays.of(SampleSystem.of(crs), 
DataType.DOUBLE, size);
+            final Cursor cursor = positions.cursor();
+            int i = 0;
+            while (cursor.next()) {
+                final Tuple samples = cursor.samples();
+                samples.set(0, cs.getOrdinate(i, 0));
+                samples.set(1, cs.getOrdinate(i, 1));
+                if (dimension > 2) {
+                    //JTS only goes up to 3 dimensions
+                    samples.set(2, cs.getOrdinate(i, 2));
+                }
+                i++;
+            }
+            return new ArraySequence(positions);
+        } else {
+            return new JTSSequence(cs, crs);
+        }
+    }
+
+    private static CoordinateSequence toCoordinateSequence(PointSequence ps, 
boolean copy, org.locationtech.jts.geom.GeometryFactory gf) {
+        final CoordinateReferenceSystem crs = 
ps.getCoordinateReferenceSystem();
+        final int dimension = ps.getDimension();
+        if (copy) {
+            final int size = ps.size();
+            final CoordinateSequence cs = 
gf.getCoordinateSequenceFactory().create(size, dimension);
+
+            for (int i = 0; i < size; i++) {
+                Tuple position = ps.getPosition(i);
+                for (int d = 0; d < dimension; d++) {
+                    cs.setOrdinate(i, d, position.get(d));
+                }
+            }
+            return cs;
+        } else {
+            return new SISSequence(ps);
+        }
+    }
+
+    private static class JTSSequence implements PointSequence {
+
+        private final CoordinateSequence jts;
+        private final CoordinateReferenceSystem crs;
+        private final int dim;
+        private final AttributesType type;
+
+        private JTSSequence(CoordinateSequence jts, CoordinateReferenceSystem 
crs) {
+            this.jts = jts;
+            this.crs = crs;
+            this.dim = jts.getDimension();
+
+            final AttributesType.Template at = new AttributesType.Template();
+            at.addOrReplaceAttribute(AttributesType.ATT_POSITION, 
SampleSystem.of(crs), DataType.DOUBLE);
+            type = at;
+        }
+
+        @Override
+        public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+            return crs;
+        }
+
+        @Override
+        public void setCoordinateReferenceSystem(CoordinateReferenceSystem cs) 
throws IllegalArgumentException {
+            throw new UnsupportedOperationException("Not supported.");
+        }
+
+        @Override
+        public AttributesType getAttributesType() {
+            return type;
+        }
+
+        @Override
+        public int size() {
+            return jts.size();
+        }
+
+        @Override
+        public Point getPoint(int index) {
+            return new JTSPoint(this, index);
+        }
+
+        @Override
+        public Tuple getPosition(int index) {
+            final Vector v = Vectors.create(crs, DataType.DOUBLE);
+            for (int i = 0; i < dim; i++) {
+                v.set(i, jts.getOrdinate(index, i));
+            }
+            return v;
+        }
+
+        @Override
+        public void setPosition(int index, Tuple value) {
+            for (int i = 0; i < dim; i++) {
+                jts.setOrdinate(index, i, value.get(i));
+            }
+        }
+
+        @Override
+        public Tuple getAttribute(int index, String name) {
+            if (AttributesType.ATT_POSITION.equals(name)) {
+                return getPosition(index);
+            }
+            throw new IllegalArgumentException("No attribute for name " + 
name);
+        }
+
+        @Override
+        public void setAttribute(int index, String name, Tuple value) {
+            if (AttributesType.ATT_POSITION.equals(name)) {
+                setPosition(index, value);
+            } else {
+                throw new IllegalArgumentException("No attribute for name " + 
name);
+            }
+        }
+
+    }
+
+    /**
+     * An indexed point in the jts sequence
+     */
+    private static class JTSPoint implements Point {
+
+        private final JTSSequence parent;
+        private final int index;
+
+        public JTSPoint(JTSSequence geometry, int index) {
+            this.parent = geometry;
+            this.index = index;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return false;
+        }
+
+        @Override
+        public Tuple getPosition() {
+            return parent.getPosition(index);
+        }
+
+        /**
+         * @return index in the parent.
+         */
+        public int getIndex() {
+            return index;
+        }
+
+        @Override
+        public Tuple getAttribute(String key) {
+            return parent.getAttribute(index, key);
+        }
+
+        @Override
+        public void setAttribute(String name, Tuple tuple) {
+            parent.setAttribute(index, name, tuple);
+        }
+
+        @Override
+        public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+            return parent.getCoordinateReferenceSystem();
+        }
+
+        @Override
+        public void setCoordinateReferenceSystem(CoordinateReferenceSystem 
crs) {
+            throw new UnsupportedOperationException("Not supported.");
+        }
+
+        @Override
+        public AttributesType getAttributesType() {
+            return parent.getAttributesType();
+        }
+    }
+
+    private static class SISSequence implements CoordinateSequence {
+
+        private final PointSequence points;
+
+        public SISSequence(PointSequence points) {
+            this.points = points;
+        }
+
+        @Override
+        public int getDimension() {
+            return points.getDimension();
+        }
+
+        @Override
+        public Coordinate getCoordinate(int i) {
+            return getCoordinateCopy(i);
+        }
+
+        @Override
+        public Coordinate getCoordinateCopy(int i) {
+            final Tuple<?> position = points.getPosition(i);
+            if (getDimension() == 2) {
+                return new CoordinateXY(position.get(0), position.get(1));
+            } else {
+                return new Coordinate(position.get(0), position.get(1), 
position.get(2));
+            }
+        }
+
+        @Override
+        public void getCoordinate(int index, Coordinate coord) {
+            final Tuple<?> position = points.getPosition(index);
+            coord.setX(position.get(0));
+            coord.setY(position.get(1));
+        }
+
+        @Override
+        public double getX(int index) {
+            return points.getPosition(index).get(0);
+        }
+
+        @Override
+        public double getY(int index) {
+            return points.getPosition(index).get(1);
+        }
+
+        @Override
+        public double getOrdinate(int index, int ordinateIndex) {
+            return points.getPosition(index).get(ordinateIndex);
+        }
+
+        @Override
+        public int size() {
+            return points.size();
+        }
+
+        @Override
+        public void setOrdinate(int index, int ordinateIndex, double value) {
+            final Tuple<?> position = points.getPosition(index);
+            position.set(ordinateIndex, value);
+            points.setPosition(index, position);
+        }
+
+        @Override
+        public Coordinate[] toCoordinateArray() {
+            final Coordinate[] array = new Coordinate[points.size()];
+            for (int i = 0; i < array.length; i++) {
+                array[i] = getCoordinate(i);
+            }
+            return array;
+        }
+
+        @Override
+        public org.locationtech.jts.geom.Envelope 
expandEnvelope(org.locationtech.jts.geom.Envelope env) {
+            final BBox bbox = 
points.getAttributeRange(AttributesType.ATT_POSITION);
+            env.expandToInclude(bbox.getMinimum(0), bbox.getMinimum(1));
+            env.expandToInclude(bbox.getMaximum(0), bbox.getMaximum(1));
+            return env;
+        }
+
+        @Override
+        public CoordinateSequence copy() {
+            return new 
org.locationtech.jts.geom.GeometryFactory().getCoordinateSequenceFactory().create(this);
+        }
+
+        @Override
+        public CoordinateSequence clone() {
+            return copy();
+        }
+
+    }
+
+}
diff --git 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
index 5db0eeb427..e457705174 100644
--- 
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
+++ 
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/GeometryProcessor.java
@@ -370,14 +370,14 @@ public final class GeometryProcessor {
 
         if (geom instanceof LinearRing cdt) {
             return Transform.transform(cdt, crs, transform);
+        } else if (geom instanceof Triangle cdt) {
+            return Transform.transform(cdt, crs, transform);
         } else if (geom instanceof Polygon cdt) {
             return Transform.transform(cdt, crs, transform);
         } else if (geom instanceof MultiMeshPrimitive<?> cdt) {
             return Transform.transform(cdt, crs, transform);
         } else if (geom instanceof MeshPrimitive cdt) {
             return Transform.transform(cdt, crs, transform);
-        } else if (geom instanceof Triangle cdt) {
-            return Transform.transform(cdt, crs, transform);
         }
 
         throw new UnsupportedOperationException();

Reply via email to