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 fc8a1ac943516ab477cc6b7bd495130b2138f997 Author: jsorel <[email protected]> AuthorDate: Fri Oct 16 11:46:47 2026 +0200 feat(Math): add Vector.swizzle and Maths.removeWithin --- .../apache/sis/geometries/operation/Distance.java | 52 ++++++++++++++++++++++ .../main/org/apache/sis/maths/Maths.java | 32 +++++++++++++ .../main/org/apache/sis/maths/ReadOnly.java | 18 ++++++++ .../org/apache/sis/maths/AbstractVectorTest.java | 37 +++++++++++++++ 4 files changed, 139 insertions(+) diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/Distance.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/Distance.java index a12587e66f..379ede03bc 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/Distance.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/operation/Distance.java @@ -16,6 +16,7 @@ */ package org.apache.sis.geometries.operation; +import java.util.List; import org.apache.sis.geometries.Point; import org.apache.sis.maths.Maths; import org.apache.sis.maths.Vectors; @@ -136,6 +137,57 @@ public final class Distance { return Vectors.dot(t,t); } + /** + * Find nearest points between two lines. + * Only the two first coordinates of the positions are used. + * + * @param line1Coords line 1 coordinates + * @param buffer1 buffer to store nearest point on line 1, of length 2 + * @param line2Coords line 2 coordinates + * @param buffer2 buffer to store nearest point on line 2, of length 2 + * @param ratio size 2, will store for each line the ratio [0..1] of the nearest point + * between the start and end points of the segment where it is + * @param offset size 2, will store for each line the index of the segment where the nearest point is + * @param epsilon tolerance factor + */ + public static void nearest(List<? extends Vector<?>> line1Coords, double[] buffer1, + List<? extends Vector<?>> line2Coords, double[] buffer2, + double[] ratio, int[] offset, double epsilon){ + + double distance = Double.MAX_VALUE; + + final double[] tempRatio = new double[2]; + final double[] tempC1 = new double[buffer1.length]; + final double[] tempC2 = new double[buffer1.length]; + + final int nb1 = line1Coords.size()-1; + final int nb2 = line2Coords.size()-1; + + for(int i=0;i<nb1;i++){ + final Vector<?> s1 = line1Coords.get(i); + final Vector<?> e1 = line1Coords.get(i+1); + for(int k=0;k<nb2;k++){ + final Vector<?> s2 = line2Coords.get(k); + final Vector<?> e2 = line2Coords.get(k+1); + + final double dist = Math.sqrt(distanceSquare( + new double[]{s1.get(0),s1.get(1)}, new double[]{e1.get(0),e1.get(1)}, tempC1, + new double[]{s2.get(0),s2.get(1)}, new double[]{e2.get(0),e2.get(1)}, tempC2, + tempRatio,epsilon)); + if(dist<distance){ + //keep informations + distance = dist; + offset[0] = i; + offset[1] = k; + ratio[0] = tempRatio[0]; + ratio[1] = tempRatio[1]; + System.arraycopy(tempC1, 0, buffer1, 0, tempC1.length); + System.arraycopy(tempC2, 0, buffer2, 0, tempC2.length); + } + } + } + } + /** * Point to point distance. */ diff --git a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Maths.java b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Maths.java index f00c32484b..fb90d5880b 100644 --- a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Maths.java +++ b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/maths/Maths.java @@ -1278,4 +1278,36 @@ public final class Maths { } } } + + /** + * Remove element at index. + * Move elements after index by -1. + * Last element is set to null + * + * @param values original array + * @param index removed element index + * @return removed object + */ + public static Object removeWithin(Object[] values, int index) { + final Object removedValue = values[index]; + System.arraycopy(values, index+1, values, index, values.length-index-1); + values[values.length-1] = null; //remove reference + return removedValue; + } + + /** + * Remove element at index. + * Move elements after index by -1. + * Last element is set to zero + * + * @param values original array + * @param index removed element index + * @return removed value + */ + public static int removeWithin(int[] values, int index) { + final int removedValue = values[index]; + System.arraycopy(values, index+1, values, index, values.length-index-1); + values[values.length-1] = 0; + return removedValue; + } } 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 33d3a4db8d..9ff8cffef5 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 @@ -347,6 +347,24 @@ public final class ReadOnly { } return v; } + + /** + * Create a new tuple with the values of the given axes, in the given order. + * Axes can be omitted or repeated, for example {@code swizzle(1, 0)} swaps the + * two first values and {@code swizzle(0, 0, 0)} repeats the first one. + * Vector CRS will be lost. + * + * @param axes indices of the values of this tuple to copy, one per dimension of the result + * @return Vector of dimension {@code axes.length} + * @throws IndexOutOfBoundsException if an axis index is not valid + */ + default org.apache.sis.maths.Vector<?> swizzle(int ... axes) throws IndexOutOfBoundsException { + final org.apache.sis.maths.Vector<?> v = Vectors.create(axes.length, getDataType()); + for (int i = 0; i < axes.length; i++) { + v.set(i, get(axes[i])); + } + return v; + } } public static interface Affine<T extends Affine<T>> extends Transform { 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 e61ef375c6..78bbd04e5e 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 @@ -68,6 +68,7 @@ public abstract class AbstractVectorTest { testToArray(tuple); testEquality(tuple); testCopyDataType(tuple); + testSwizzle(tuple); switch (tuple.getDataType()) { case BYTE : @@ -265,6 +266,42 @@ public abstract class AbstractVectorTest { } } + /** + * Test the creation of a tuple from some axes of another one. + */ + private void testSwizzle(Vector<?> tuple) { + final int dim = tuple.getDimension(); + for (int i = 0; i < dim; i++) { + tuple.set(i, i+1); + } + //reverse order + final int[] reverse = new int[dim]; + final double[] expected = new double[dim]; + for (int i = 0; i < dim; i++) { + reverse[i] = dim - 1 - i; + expected[i] = dim - i; + } + Vector<?> swizzled = tuple.swizzle(reverse); + assertEquals(tuple.getDataType(), swizzled.getDataType()); + assertArrayEquals(expected, swizzled.toArrayDouble(), TOLERANCE); + + //repeated and omitted axes + swizzled = tuple.swizzle(dim - 1, 0, dim - 1); + assertArrayEquals(new double[] {dim, 1, dim}, swizzled.toArrayDouble(), TOLERANCE); + + //the result is independent of the original tuple + swizzled.set(1, 100); + assertEquals(1, tuple.get(0), TOLERANCE); + + //test out of range + try { + tuple.swizzle(dim); + fail(UNVALID_INDEX_EXPECTED); + } catch (IndexOutOfBoundsException ex) { + //ok + } + } + private void testExtremum(Vector<?> tuple, double value) { for (int i=0;i<tuple.getDimension();i++) {
