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
commit 3cb482cd8e35814b93712a05db5501fc05c554ae Author: jsorel <[email protected]> AuthorDate: Thu Oct 15 09:41:46 2026 +0200 feat(Math): add Vector.copy(DataType) and Vector.perpendicular(Vector n) --- .../main/org/apache/sis/maths/ReadOnly.java | 15 ++++++-- .../main/org/apache/sis/maths/Vector.java | 17 +++++++-- .../main/org/apache/sis/maths/Vectors.java | 40 ---------------------- .../org/apache/sis/maths/AbstractVectorTest.java | 40 ++++++++++++++++++++++ 4 files changed, 66 insertions(+), 46 deletions(-) diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/ReadOnly.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/ReadOnly.java index 2ba2034c93..33d3a4db8d 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/ReadOnly.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/ReadOnly.java @@ -186,9 +186,18 @@ public final class ReadOnly { * @return tuple copy. */ default org.apache.sis.maths.Vector<?> copy() { - org.apache.sis.maths.Vector<?> tuple = Vectors.create(getSampleSystem(), getDataType()); - tuple.set(this); - return tuple; + return Vectors.create(getSampleSystem(), getDataType()).set(this); + } + + /** + * Create a copy of this tuple, with values stored in the given data type. + * The copy has the same sample system as this tuple. + * + * @param dataType data type of the copy values. + * @return tuple copy. + */ + default org.apache.sis.maths.Vector<?> copy(DataType dataType) { + return Vectors.create(getSampleSystem(), dataType).set(this); } /** diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vector.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vector.java index 0e31d4ef6e..8cd77b98a0 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vector.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vector.java @@ -174,9 +174,7 @@ public interface Vector<T extends Vector <T>> extends ReadOnly.Vector<T>{ * @return tuple copy. */ default T copy() { - T tuple = (T) Vectors.create(getSampleSystem(), getDataType()); - tuple.set(this); - return tuple; + return (T) ReadOnly.Vector.super.copy(); } /** @@ -245,6 +243,19 @@ public interface Vector<T extends Vector <T>> extends ReadOnly.Vector<T>{ return (T) this; } + /** + * Remove from this vector its component along the given unit vector. + * The result is the projection of this vector on the hyperplane perpendicular to the given vector. + * + * @param unit unit vector, of length 1 + * @return this vector + */ + default T perpendicular(ReadOnly.Vector<?> unit) { + final double[] u = unit.toArrayDouble(); + set( Vectors.subtract(toArrayDouble(), Vectors.scale(u, dot(unit)))); + return (T) this; + } + /** * Linear interpolation from this vector to the other vector : (1-ratio)*this + ratio*other. * diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vectors.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vectors.java index a6e539a091..1fced5a5e6 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vectors.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Vectors.java @@ -232,46 +232,6 @@ public final class Vectors { return new VectorUnmodifiable(tuple); } - private static class WrapTuple extends AbstractVector<WrapTuple> implements Vector<WrapTuple> { - - private final Vector<?> pos; - - public WrapTuple(Vector<?> pos, int size) { - super(size); - this.pos = pos; - } - - public WrapTuple(Vector<?> pos) { - super(pos.getSampleSystem()); - this.pos = pos; - } - - @Override - public DataType getDataType() { - return pos.getDataType(); - } - - @Override - public double get(int indice) { - return pos.get(indice); - } - - @Override - public void set(int indice, double value) { - pos.set(indice, value); - } - - @Override - public int getDimension() { - return pos.getDimension(); - } - - @Override - public WrapTuple copy() { - return super.copy(); - } - } - private static class WrapDirectPostion extends AbstractVector<WrapDirectPostion> implements Vector<WrapDirectPostion> { private final DirectPosition pos; diff --git a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/maths/AbstractVectorTest.java b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/maths/AbstractVectorTest.java index 9a6a5779ff..e61ef375c6 100644 --- a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/maths/AbstractVectorTest.java +++ b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/maths/AbstractVectorTest.java @@ -67,6 +67,7 @@ public abstract class AbstractVectorTest { testCellGetSet(tuple); testToArray(tuple); testEquality(tuple); + testCopyDataType(tuple); switch (tuple.getDataType()) { case BYTE : @@ -101,6 +102,7 @@ public abstract class AbstractVectorTest { testAdd(tuple); testSubtract(tuple); testScale(tuple); + testPerpendicular(tuple); testCross(tuple); testDot(tuple); } @@ -245,6 +247,24 @@ public abstract class AbstractVectorTest { } + /** + * Test copy in another data type. + */ + private void testCopyDataType(Vector<?> tuple) { + for (int i = 0; i < tuple.getDimension(); i++) { + tuple.set(i, i+1); + } + for (final DataType dataType : new DataType[] {DataType.DOUBLE, DataType.FLOAT, DataType.SHORT}) { + final Vector<?> copy = tuple.copy(dataType); + assertEquals(dataType, copy.getDataType()); + assertEquals(tuple.getSampleSystem(), copy.getSampleSystem()); + assertArrayEquals(tuple.toArrayDouble(), copy.toArrayDouble(), TOLERANCE); + //the copy is independent of the original tuple + copy.set(0, 100); + assertEquals(1, tuple.get(0), TOLERANCE); + } + } + private void testExtremum(Vector<?> tuple, double value) { for (int i=0;i<tuple.getDimension();i++) { @@ -365,6 +385,26 @@ public abstract class AbstractVectorTest { assertArrayEquals(expected, vector.toArrayDouble(), TOLERANCE); } + /** + * Test removal of the component along a unit vector. + * The unit vector is along the first axis, so the result is exact for all data types. + */ + private void testPerpendicular(Vector<?> vector) { + final int dim = vector.getDimension(); + + final Vector<?> unit = Vectors.createDouble(dim); + unit.set(0, 1); + for (int i = 0; i < dim; i++) { + vector.set(i, i+1); + } + + final double[] expected = vector.toArrayDouble(); + expected[0] = 0; + vector.perpendicular(unit); + assertArrayEquals(expected, vector.toArrayDouble(), TOLERANCE); + assertEquals(0, vector.dot(unit), TOLERANCE); + } + /** * Test vector cross product. * Only tested if vector size is 3.
