This is an automated email from the ASF dual-hosted git repository.
jsorel 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 517b8edb7e feat(Math): remove several matrix static methods, now part
of matrix classes
517b8edb7e is described below
commit 517b8edb7e8a970f7ef7c24abdbf93c57f95df9e
Author: jsorel <[email protected]>
AuthorDate: Fri Mar 13 14:34:37 2026 +0100
feat(Math): remove several matrix static methods, now part of matrix classes
---
.../apache/sis/geometries/math/AbstractMatrix.java | 13 ++
.../sis/geometries/math/AbstractSimilarity.java | 137 +++++++-----
.../org/apache/sis/geometries/math/Matrices.java | 247 ---------------------
.../org/apache/sis/geometries/math/Matrix.java | 13 ++
.../org/apache/sis/geometries/math/Matrix3D.java | 38 +++-
.../org/apache/sis/geometries/math/MatrixND.java | 57 ++++-
.../org/apache/sis/geometries/math/ReadOnly.java | 14 +-
.../org/apache/sis/geometries/math/Similarity.java | 62 +++---
.../apache/sis/geometries/math/Similarity3D.java | 26 +--
.../apache/sis/geometries/math/SimilarityND.java | 54 ++---
10 files changed, 258 insertions(+), 403 deletions(-)
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractMatrix.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractMatrix.java
index 72747bd6c1..a820d69ec0 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractMatrix.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractMatrix.java
@@ -465,6 +465,19 @@ abstract class AbstractMatrix<T extends AbstractMatrix<T>>
extends SimplifiedTra
return set((ReadOnly.Matrix)t);
}
+ @Override
+ public T roundZeros(double epsilon){
+ for (int x=0;x<nbCol;x++){
+ for (int y=0;y<nbRow;y++){
+ double d = get(y, x);
+ if (!(d>epsilon || d<-epsilon)){
+ set(y,x, 0.0);
+ }
+ }
+ }
+ return (T) this;
+ }
+
/**
* invert matrix
*/
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractSimilarity.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractSimilarity.java
index 0b995e23e3..676c48f0b1 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractSimilarity.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractSimilarity.java
@@ -74,9 +74,9 @@ public abstract class AbstractSimilarity<T extends
AbstractSimilarity<T>> extend
if (dirty){
dirty = false;
//update matrix
- final Vector<?> translation = getTranslation();
- final Matrix<?> rotation = getRotation();
- final Vector<?> scale = getScale();
+ final ReadOnly.Vector<?> translation = getTranslation();
+ final ReadOnly.Matrix<?> rotation = getRotation();
+ final ReadOnly.Vector<?> scale = getScale();
matrix.setToIdentity();
matrix.set(rotation);
matrix.scale(scale.extend(1).toArrayDouble());
@@ -136,58 +136,96 @@ public abstract class AbstractSimilarity<T extends
AbstractSimilarity<T>> extend
return (T) this;
}
+ /**
+ * Decompose a matrix in rotation, scale and translation.
+ * The matrix is expected to be orthogonal of size 3x3 or 4x4.
+ */
@Override
public T setFromMatrix(ReadOnly.Matrix<?> matrix) {
- Matrices.decomposeMatrix(matrix, getRotation(), getScale(),
getTranslation());
- notifyChanged();
- return (T) this;
+ return update((Matrix<?> rotation, Vector<?> scale, Vector<?>
translation) -> {
+ final int dimension = matrix.getNumCol()-1;
+ if (dimension == 2){
+ final double scaleX = Math.sqrt(matrix.get(0,0)*matrix.get(0,0)
+ + matrix.get(1,0)*matrix.get(1,0));
+ final double scaleY = Math.sqrt(matrix.get(0,1)*matrix.get(0,1)
+ + matrix.get(1,1)*matrix.get(1,1));
+
+ final double[] invertScale = new double[]{1d/scaleX,1d/scaleY};
+ final Matrix<?> rot = matrix.getRange(0, 1, 0, 1);
+ rot.scale(invertScale);
+
+ rotation.set(rot);
+ scale.set(0,scaleX);
+ scale.set(1,scaleY);
+ translation.set(0, matrix.get(0,2));
+ translation.set(1, matrix.get(1,2));
+ } else if (dimension == 3){
+ final double scaleX = Math.sqrt(matrix.get(0,0)*matrix.get(0,0)
+ + matrix.get(1,0)*matrix.get(1,0)
+ + matrix.get(2,0)*matrix.get(2,0));
+ final double scaleY = Math.sqrt(matrix.get(0,1)*matrix.get(0,1)
+ + matrix.get(1,1)*matrix.get(1,1)
+ + matrix.get(2,1)*matrix.get(2,1));
+ final double scaleZ = Math.sqrt(matrix.get(0,2)*matrix.get(0,2)
+ + matrix.get(1,2)*matrix.get(1,2)
+ + matrix.get(2,2)*matrix.get(2,2));
+ final double[] invertScale = new
double[]{1d/scaleX,1d/scaleY,1d/scaleZ};
+ final Matrix<?> rot = matrix.getRange(0, 2, 0, 2);
+ rot.scale(invertScale);
+
+ rotation.set(rot);
+ scale.set(0, scaleX);
+ scale.set(1, scaleY);
+ scale.set(2, scaleZ);
+ translation.set(0,matrix.get(0,3));
+ translation.set(1,matrix.get(1,3));
+ translation.set(2,matrix.get(2,3));
+
+ } else {
+ throw new UnsupportedOperationException("Only works for 2D and
3D for now. TODO");
+ }
+ return ALL_UPDATED;
+ });
}
@Override
public T setToTranslation(double[] trs){
- boolean change = false;
- final Matrix<?> rotation = getRotation();
- if (!rotation.isIdentity()){
- change = true;
- rotation.setToIdentity();
- }
- final Vector<?> scale = getScale();
- if (!scale.isAll(1.0)){
- change = true;
- scale.setAll(1.0);
- }
- final Vector<?> translation = getTranslation();
- if (!Arrays.equals(trs, translation.toArrayDouble())){
- change = true;
- translation.set(trs);
- }
-
- if (change) notifyChanged();
-
- return (T) this;
+ return update((Matrix<?> rotation, Vector<?> scale, Vector<?>
translation) -> {
+ boolean change = false;
+ if (!rotation.isIdentity()){
+ change = true;
+ rotation.setToIdentity();
+ }
+ if (!scale.isAll(1.0)){
+ change = true;
+ scale.setAll(1.0);
+ }
+ if (!Arrays.equals(trs, translation.toArrayDouble())){
+ change = true;
+ translation.set(trs);
+ }
+ return change ? ALL_UPDATED : 0;
+ });
}
@Override
public T setToIdentity(){
- boolean change = false;
- final Matrix<?> rotation = getRotation();
- if (!rotation.isIdentity()){
- change = true;
- rotation.setToIdentity();
- }
- final Vector<?> scale = getScale();
- if (!scale.isAll(1.0)){
- change = true;
- scale.setAll(1.0);
- }
- final Vector<?> translation = getTranslation();
- if (!translation.isAll(0.0)){
- change = true;
- translation.setAll(0.0);
- }
-
- if (change) notifyChanged();
- return (T) this;
+ return update((Matrix<?> rotation, Vector<?> scale, Vector<?>
translation) -> {
+ boolean change = false;
+ if (!rotation.isIdentity()){
+ change = true;
+ rotation.setToIdentity();
+ }
+ if (!scale.isAll(1.0)){
+ change = true;
+ scale.setAll(1.0);
+ }
+ if (!translation.isAll(0.0)){
+ change = true;
+ translation.setAll(0.0);
+ }
+ return change ? ALL_UPDATED : 0;
+ });
}
@Override
@@ -251,10 +289,8 @@ public abstract class AbstractSimilarity<T extends
AbstractSimilarity<T>> extend
}
@Override
- public Matrix<?> toMatrix(Matrix<?> buffer) {
- if (buffer == null) return toMatrix();
- buffer.set(viewMatrix());
- return buffer;
+ public Affine<?> toAffine() {
+ return viewAffine().copy();
}
protected PropertyChangeSupport getEventManager() {
@@ -280,8 +316,7 @@ public abstract class AbstractSimilarity<T extends
AbstractSimilarity<T>> extend
* Flag to indicate the transform parameters has changed.
* This is used to recalculate the general matrix when needed.
*/
- @Override
- public void notifyChanged(){
+ protected void notifyChanged(){
dirty = true;
inverseDirty = true;
affineDirty = true;
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrices.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrices.java
index 5ab0b06afe..cba3dd01ad 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrices.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrices.java
@@ -26,61 +26,6 @@ public final class Matrices {
private Matrices(){}
- /**
- * Checks if the given matrix is the identity matrix.
- *
- * @param m matrix to test.
- * @return true if matrix is an Identity matrix.
- */
- public static boolean isIdentity(final double[][] m){
- if ( m.length!=m[0].length ) return false; // m must be a square matrix
- for ( int x=0; x<m[0].length; x++) {
- for ( int y=0; y<m.length; y++) {
- if (x==y){
- if ( m[y][x] != 1 ) return false;
- } else {
- if ( m[y][x] != 0 ) return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Sets the given matrix to identity matrix.
- *
- * @param m a square matrix.
- * @throws IllegalArgumentException when m is not a square matrix.
- */
- public static void setToIdentity( double[][] m ){
- if (m.length != m[0].length) {
- throw new IllegalArgumentException("The m matrix must be a square
matrix.");
- }
- for (int x = 0; x < m[0].length; x++) {
- for (int y = 0; y < m.length; y++) {
- if (x == y) {
- m[y][x] = 1.;
- } else {
- m[y][x] = 0.;
- }
- }
- }
- }
-
- /**
- * Creates a n*n identity matrix.
- *
- * @param n number of rows and columns.
- * @return an n*n identity matrix.
- */
- public static double[][] identity(int n) {
- double[][] identity = new double[n][n];
- for (int i = 0; i < n; i++) {
- identity[i][i] = 1.;
- }
- return identity;
- }
-
/**
* Adds m1 and m2, the result is stored in m1, returns m1.
* see {@link Matrices#add(un.science.math.Matrix, un.science.math.Matrix,
un.science.math.Matrix)}
@@ -387,99 +332,6 @@ public final class Matrices {
return sum;
}
- /**
- * replace valeus close to 0 with zero, removing -0 if present
- * @param matrix
- * @param epsilon
- */
- public static void roundZeros(double[][] matrix, double epsilon){
- for (int x=0;x<matrix.length;x++){
- for (int y=0;y<matrix[0].length;y++){
- if (!(matrix[x][y]>epsilon || matrix[x][y]<-epsilon)){
- matrix[x][y] = 0.0;
- }
- }
- }
- }
-
- public static Tuple<?> transformLocal(final double[][] matrix, final
Tuple<?> vector) {
- return transform(matrix, vector, vector);
- }
-
- public static Tuple<?> transform(final double[][] matrix, final
ReadOnly.Tuple<?> vector, Tuple<?> buffer) {
- if (buffer==null) buffer = Vectors.createDouble(matrix.length);
- final double[] array = new double[matrix.length];
- transform(matrix, vector.toArrayDouble(), array);
- buffer.set(array);
- return buffer;
- }
-
- /**
- * Transform given vector.
- *
- * @param matrix input matrix
- * @param vector vector to transform
- * @param buffer result vector buffer, can be null
- * @return the product of matrix and vector.
- */
- public static double[] transform(final double[][] matrix, final double[]
vector, double[] buffer) {
- if (vector.length != matrix[0].length){
- throw new IllegalArgumentException("matrix column size and vector
size differ : "+matrix[0].length+","+vector.length);
- }
-
- final int nbRow = matrix.length;
- final int nbCol = matrix[0].length;
- final double[] res = new double[nbRow];
-
- for (int r = 0; r < nbRow; r++) {
- double s = 0;
- for (int c = 0; c < nbCol; c++) {
- s += matrix[r][c] * vector[c];
- }
- res[r] = s;
- }
-
- if ( buffer == null ) {
- buffer = new double[matrix.length];
- }
- System.arraycopy(res, 0, buffer, 0, res.length);
-
- return buffer;
- }
-
- /**
- * Transforms given vector.
- *
- * @param matrix transformation matrix.
- * @param vector considered as a column matrix.
- * @param buffer result vector buffer, can be null
- * @return the product of matrix and vector.
- */
- public static float[] transform(final double[][] matrix, final float[]
vector, float[] buffer) {
- if (vector.length != matrix[0].length){
- throw new IllegalArgumentException("matrix column size and vector
size differ : "+matrix[0].length+","+vector.length);
- }
-
- if (buffer == null) {
- buffer = new float[matrix.length];
- }
-
- final int nbRow = matrix.length;
- final int nbCol = matrix[0].length;
- final float[] res = new float[nbRow];
-
- for (int r = 0; r < nbRow; r++) {
- double s = 0;
- for (int c = 0; c < nbCol; c++) {
- s += matrix[r][c] * vector[c];
- }
- res[r] = (float) s;
- }
-
- System.arraycopy(res, 0, buffer, 0, res.length);
- return buffer;
- }
-
/**
* Multiply m1 by m2, result is stored in m1, returns m1.
* see {@link Matrices#multiply(un.science.math.Matrix,
un.science.math.Matrix, un.science.math.Matrix)}
@@ -697,58 +549,6 @@ public final class Matrices {
return buffer;
}
- /**
- * Calculate Euler angle of given matrix.
- * Source :
- * http://www.soi.city.ac.uk/~sbbh653/publications/euler.pdf
- * http://jeux.developpez.com/faq/math/?page=transformations#Q37
- *
- * @param mat input matrix
- * @param buffer euler buffer, can be null
- * @return euler angle in radians (heading/yaw , elevation/pitch ,
bank/roll)
- */
- public static double[] toEuler(double[][] mat, double[] buffer){
-
- if (buffer == null){
- buffer = new double[3];
- }
-
- double angle_x;
- double angle_y;
- double angle_z;
-
- if (mat[2][0] != -1 && mat[2][0] != +1){
- //first possible solution
- angle_y = -Math.asin(mat[2][0]);
- double cosy1 = Math.cos(angle_y);
- angle_x = Math.atan2(mat[2][1]/cosy1, mat[2][2]/cosy1);
- angle_z = Math.atan2(mat[1][0]/cosy1, mat[0][0]/cosy1);
-
- //second possible solution
- //angle_y = Angles.PI - y1;
- //double cosy2 = Math.cos(angle_y);
- //angle_x = Math.atan2(mat[2][1]/cosy2, mat[2][2]/cosy2);
- //angle_z = Math.atan2(mat[1][0]/cosy2, mat[0][0]/cosy2);
-
- } else {
- // Gimbal lock
- angle_z = 0;
- if (mat[2][0] == -1){
- angle_y = Math.PI / 2.0;
- angle_x = angle_z + Math.atan2(mat[0][1], mat[0][2]);
- } else {
- angle_y = -Math.PI / 2.0;
- angle_x = -angle_z + Math.atan2(-mat[0][1], -mat[0][2]);
- }
- }
-
-
- buffer[0] = angle_z;
- buffer[1] = angle_y;
- buffer[2] = angle_x;
- return buffer;
- }
-
/**
* Create and orbit matrix 4x4 focus on the root point (0,0,0).
*
@@ -785,51 +585,4 @@ public final class Matrices {
return result.getValues();
}
- /**
- * Decompose a matrix in rotation, scale and translation.
- * The matrix is expected to be orthogonal of size 3x3 or 4x4.
- */
- public static void decomposeMatrix(ReadOnly.Matrix<?> trs, Matrix<?>
rotation, Tuple<?> scale, Tuple<?> translation){
- final int dimension = trs.getNumCol()-1;
- if (dimension == 2){
- final double scaleX = Math.sqrt(trs.get(0,0)*trs.get(0,0)
- + trs.get(1,0)*trs.get(1,0));
- final double scaleY = Math.sqrt(trs.get(0,1)*trs.get(0,1)
- + trs.get(1,1)*trs.get(1,1));
-
- final double[] invertScale = new double[]{1d/scaleX,1d/scaleY};
- final Matrix<?> rot = trs.getRange(0, 1, 0, 1);
- rot.scale(invertScale);
-
- rotation.set(rot);
- scale.set(0,scaleX);
- scale.set(1,scaleY);
- translation.set(0, trs.get(0,2));
- translation.set(1, trs.get(1,2));
- } else if (dimension == 3){
- final double scaleX = Math.sqrt(trs.get(0,0)*trs.get(0,0)
- + trs.get(1,0)*trs.get(1,0)
- + trs.get(2,0)*trs.get(2,0));
- final double scaleY = Math.sqrt(trs.get(0,1)*trs.get(0,1)
- + trs.get(1,1)*trs.get(1,1)
- + trs.get(2,1)*trs.get(2,1));
- final double scaleZ = Math.sqrt(trs.get(0,2)*trs.get(0,2)
- + trs.get(1,2)*trs.get(1,2)
- + trs.get(2,2)*trs.get(2,2));
- final double[] invertScale = new
double[]{1d/scaleX,1d/scaleY,1d/scaleZ};
- final Matrix rot = trs.getRange(0, 2, 0, 2);
- rot.scale(invertScale);
-
- rotation.set(rot);
- scale.set(0, scaleX);
- scale.set(1, scaleY);
- scale.set(2, scaleZ);
- translation.set(0,trs.get(0,3));
- translation.set(1,trs.get(1,3));
- translation.set(2,trs.get(2,3));
-
- } else {
- throw new IllegalArgumentException("Only works for 2D and 3D for
now. TODO");
- }
- }
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix.java
index 89739a39e0..8026a1c7a7 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix.java
@@ -34,6 +34,11 @@ public interface Matrix<T extends Matrix<T>> extends
ReadOnly.Matrix<T>, org.ope
return org.opengis.referencing.operation.Matrix.super.isIdentity();
}
+ @Override
+ default boolean isSquare() {
+ return getNumRow() == getNumCol();
+ }
+
@Override
default double getElement(int row, int col) {
return get(row,col);
@@ -133,6 +138,14 @@ public interface Matrix<T extends Matrix<T>> extends
ReadOnly.Matrix<T>, org.ope
T transpose();
+ /**
+ * replace valeus close to 0 with zero, removing -0 if present
+ *
+ * @param epsilon tolerance
+ * @return this matrix
+ */
+ T roundZeros(double epsilon);
+
T copy();
@Override
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix3D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix3D.java
index 2c522a8f40..cc91e57736 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix3D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix3D.java
@@ -294,10 +294,44 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
/**
* Convert to euler angles.
+ * Source :
+ * http://www.soi.city.ac.uk/~sbbh653/publications/euler.pdf
+ * http://jeux.developpez.com/faq/math/?page=transformations#Q37
+ *
* @return euler angle in radians (heading/yaw , elevation/pitch ,
bank/roll)
*/
- public Vector<?> toEuler(){
- return new VectorND.Double(Matrices.toEuler(toArray2Double(ROW_ORDER),
null));
+ public Vector3D.Double toEuler(){
+
+ double angle_x;
+ double angle_y;
+ double angle_z;
+
+ if (m20 != -1 && m20 != +1){
+ //first possible solution
+ angle_y = -Math.asin(m20);
+ double cosy1 = Math.cos(angle_y);
+ angle_x = Math.atan2(m21/cosy1, m22/cosy1);
+ angle_z = Math.atan2(m10/cosy1, m00/cosy1);
+
+ //second possible solution
+ //angle_y = Angles.PI - y1;
+ //double cosy2 = Math.cos(angle_y);
+ //angle_x = Math.atan2(mat[2][1]/cosy2, mat[2][2]/cosy2);
+ //angle_z = Math.atan2(mat[1][0]/cosy2, mat[0][0]/cosy2);
+
+ } else {
+ // Gimbal lock
+ angle_z = 0;
+ if (m20 == -1){
+ angle_y = Math.PI / 2.0;
+ angle_x = angle_z + Math.atan2(m01, m02);
+ } else {
+ angle_y = -Math.PI / 2.0;
+ angle_x = -angle_z + Math.atan2(-m01, -m02);
+ }
+ }
+
+ return new Vector3D.Double(angle_z, angle_y, angle_x);
}
/**
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/MatrixND.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/MatrixND.java
index e7eff9f878..dcfcd0e99d 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/MatrixND.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/MatrixND.java
@@ -307,13 +307,20 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
return this;
}
- /**
- * Set Matrix value to identity matrix.
- * @return this matrix
- */
@Override
public MatrixND setToIdentity(){
- Matrices.setToIdentity(values);
+ if (values.length != values[0].length) {
+ throw new IllegalArgumentException("The matrix is not a square
matrix.");
+ }
+ for (int x = 0; x < values[0].length; x++) {
+ for (int y = 0; y < values.length; y++) {
+ if (x == y) {
+ values[y][x] = 1.;
+ } else {
+ values[y][x] = 0.;
+ }
+ }
+ }
return this;
}
@@ -330,8 +337,24 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
}
@Override
- public boolean isIdentity(){
- return Matrices.isIdentity(values);
+ public boolean isIdentity() {
+ if (values.length != values[0].length) {
+ return false; // m must be a square matrix
+ }
+ for (int x = 0; x < values[0].length; x++) {
+ for (int y = 0; y < values.length; y++) {
+ if (x == y) {
+ if (values[y][x] != 1) {
+ return false;
+ }
+ } else {
+ if (values[y][x] != 0) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
}
/**
@@ -419,7 +442,7 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
//TODO improve it, slow and memory greedy
final double[] v = Arrays.copyOfRange(source, sourceOffset,
sourceOffset + getInputDimensions());
final double[] d = new double[getOutputDimensions()];
- Matrices.transform(values, v, d);
+ internalTransform(v, d);
System.arraycopy(d,0,dest,destOffset,d.length);
}
@@ -431,8 +454,24 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
v[i] = source[sourceOffset+i];
}
final double[] d = new double[getOutputDimensions()];
- Matrices.transform(values, v, d);
+ internalTransform(v, d);
for (int i=0;i<d.length;i++) dest[destOffset+i] = (float) d[i];
}
+ /**
+ * Transform given vector.
+ *
+ * @param vector vector to transform
+ * @param buffer result vector buffer, not null
+ * @return the product of matrix and vector.
+ */
+ private void internalTransform(final double[] vector, double[] buffer) {
+ for (int r = 0; r < nbRow; r++) {
+ double s = 0;
+ for (int c = 0; c < nbCol; c++) {
+ s += values[r][c] * vector[c];
+ }
+ buffer[r] = s;
+ }
+ }
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/ReadOnly.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/ReadOnly.java
index ccbe79890d..94015988ca 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/ReadOnly.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/ReadOnly.java
@@ -509,6 +509,11 @@ public final class ReadOnly {
*/
boolean isFinite();
+ /**
+ * @return true if matrix has the same number of rows and columns.
+ */
+ boolean isSquare();
+
/**
* For compatibility with MatrixSIS.
*
@@ -568,15 +573,6 @@ public final class ReadOnly {
*/
org.apache.sis.geometries.math.Matrix<?> toMatrix();
- /**
- * Create a square matrix of size dimensions+1
- * The last matrix line will be [0,...,1]
- *
- * @param buffer to store matrix values in
- * @return matrix
- */
- org.apache.sis.geometries.math.Matrix<?>
toMatrix(org.apache.sis.geometries.math.Matrix<?> buffer);
-
/**
* Create and affine transform.
*
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity.java
index 4fb692b1c8..91c8a282ad 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity.java
@@ -37,33 +37,19 @@ import org.opengis.referencing.operation.MathTransform;
*/
public interface Similarity<T extends Similarity<T>> extends
ReadOnly.Similarity<T> {
- /**
- * Get transform rotation.
- * Call notifyChanged after if you modified the values.
- *
- * @return Matrix
- */
- @Override
- Matrix<?> getRotation();
+ public static final int ROTATION_UPDATED = 1;
+ public static final int SCALE_UPDATED = 1 << 1;
+ public static final int TRANSLATION_UPDATED = 1 << 2;
+ public static final int ALL_UPDATED = ROTATION_UPDATED | SCALE_UPDATED |
TRANSLATION_UPDATED;
/**
- * Get transform scale.
- * Call notifyChanged after if you modified the values.
+ * Update this similarity.
+ * This method will send a change event if values have changed.
*
- * @return Vector
- */
- @Override
- Vector<?> getScale();
-
- /**
- * Get transform translation.
- * Call notifyChanged after if you modified the values.
- *ç&é ,
- * +
- * @return Vector
+ * @param updater, gets rotation,scale,translation as input and returns
the modified elements.
+ * @return this similarity
*/
- @Override
- Vector<?> getTranslation();
+ T update(TriFunction<Matrix<?>,Vector<?>,Vector<?>,Integer> updater);
/**
* Get a general matrix view of size : dimension+1
@@ -85,11 +71,20 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
*/
ReadOnly.Matrix<?> viewMatrixInverse();
+ /**
+ * Get an affine view of size : dimension+1
+ * This affine combine rotation, scale and translation
+ *
+ * [R*S, R*S, R*S, T]
+ * [R*S, R*S, R*S, T]
+ * [R*S, R*S, R*S, T]
+ *
+ * @return Affine, never null
+ */
ReadOnly.Affine<?> viewAffine();
/**
* Inverse view of this transform.
- * The returned affine is no modifiable.
* The returned affine reflects any change made to this transform
*
* @return inverse transform view
@@ -98,6 +93,7 @@ public interface Similarity<T extends Similarity<T>> extends
ReadOnly.Similarity
/**
* Multiply this similarity by given similarity and store the result in
this similarity.
+ * This method will send a change event if values have changed.
*
* @param other multiplying similarity
* @return this similarity
@@ -106,6 +102,8 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
/**
* Copy values from given transform.
+ * This method will send a change event if values have changed.
+ *
* @param trs
* @return this instance
*/
@@ -114,6 +112,7 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
/**
* Set transform from given matrix.
* Matrix must be orthogonal of size dimension+1.
+ * This method will send a change event if values have changed.
*
* @param trs
* @throws IllegalArgumentException if matrix is not affine
@@ -123,6 +122,7 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
/**
* Set transform from given affine.
* Affine must be of same size.
+ * This method will send a change event if values have changed.
*
* @param trs
*/
@@ -137,14 +137,15 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
/**
* Set this transform to given translation.
* This will reset rotation and scale values.
- *
* This method will send a change event if values have changed.
+ *
* @param trs
*/
T setToTranslation(double[] trs);
/**
* Inverse this affine transform.
+ * This method will send a change event if values have changed.
*
* @return this affine instance
*/
@@ -158,16 +159,15 @@ public interface Similarity<T extends Similarity<T>>
extends ReadOnly.Similarity
@Override
T copy();
- /**
- * Flag to indicate the transform parameters has changed.
- * This is used to recalculate the general matrix when needed.
- */
- void notifyChanged();
-
/**
* Combine the different elements to obtain a linear transform of
dimension 3.
*/
default MathTransform toMathTransform() {
return MathTransforms.linear(toMatrix().toMatrixSIS());
}
+
+ @FunctionalInterface
+ public static interface TriFunction<T, U, V, R> {
+ R apply(T t, U u, V v);
+ }
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity3D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity3D.java
index c090fc8e1e..c6aaf4e124 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity3D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity3D.java
@@ -25,9 +25,9 @@ import java.util.Objects;
*/
public final class Similarity3D extends AbstractSimilarity<Similarity3D> {
- public final Vector3D.Double scale = new Vector3D.Double(1, 1, 1);
- public final Vector3D.Double translation = new Vector3D.Double(0, 0, 0);
- public final Matrix3D rotation = new Matrix3D(1,0,0, 0,1,0, 0,0,1);
+ private final Vector3D.Double scale = new Vector3D.Double(1, 1, 1);
+ private final Vector3D.Double translation = new Vector3D.Double(0, 0, 0);
+ private final Matrix3D rotation = new Matrix3D(1,0,0, 0,1,0, 0,0,1);
public Similarity3D(){
super(3);
@@ -49,20 +49,27 @@ public final class Similarity3D extends
AbstractSimilarity<Similarity3D> {
}
@Override
- public Matrix3D getRotation() {
+ public ReadOnly.Matrix<?> getRotation() {
return rotation;
}
@Override
- public Vector3D.Double getScale() {
+ public ReadOnly.Vector<?> getScale() {
return scale;
}
@Override
- public Vector3D.Double getTranslation() {
+ public ReadOnly.Vector<?> getTranslation() {
return translation;
}
+ @Override
+ public Similarity3D update(TriFunction<Matrix<?>, Vector<?>, Vector<?>,
Integer> updater) {
+ final Integer changed = updater.apply(rotation, scale, translation);
+ if (changed != 0) notifyChanged();
+ return this;
+ }
+
@Override
public Similarity3D multiply(ReadOnly.Similarity<?> other) {
final Vector<?> resTrans = other.getTranslation().copy()
@@ -136,13 +143,6 @@ public final class Similarity3D extends
AbstractSimilarity<Similarity3D> {
return affine;
}
- @Override
- public Matrix<?> toMatrix(Matrix<?> buffer) {
- if (buffer == null) return toMatrix();
- buffer.set(toMatrix());
- return buffer;
- }
-
@Override
public Similarity3D copy() {
return new Similarity3D().set(this);
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/SimilarityND.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/SimilarityND.java
index 9dcc6c2139..d4919e9c9a 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/SimilarityND.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/SimilarityND.java
@@ -38,9 +38,9 @@ package org.apache.sis.geometries.math;
public class SimilarityND extends AbstractSimilarity<SimilarityND> {
private final int dimension;
- public final Matrix<?> rotation;
- public final Vector<?> scale;
- public final Vector<?> translation;
+ private final Matrix<?> rotation;
+ private final Vector<?> scale;
+ private final Vector<?> translation;
public static Similarity<?> create(int dimension) {
return new SimilarityND(dimension);
@@ -115,20 +115,27 @@ public class SimilarityND extends
AbstractSimilarity<SimilarityND> {
}
@Override
- public Matrix<?> getRotation() {
+ public ReadOnly.Matrix<?> getRotation() {
return rotation;
}
@Override
- public Vector<?> getScale() {
+ public ReadOnly.Vector<?> getScale() {
return scale;
}
@Override
- public Vector<?> getTranslation() {
+ public ReadOnly.Vector<?> getTranslation() {
return translation;
}
+ @Override
+ public SimilarityND update(TriFunction<Matrix<?>, Vector<?>, Vector<?>,
Integer> updater) {
+ final Integer changed = updater.apply(rotation, scale, translation);
+ if (changed != 0) notifyChanged();
+ return this;
+ }
+
@Override
public SimilarityND multiply(ReadOnly.Similarity<?> other) {
/*
@@ -159,41 +166,6 @@ public class SimilarityND extends
AbstractSimilarity<SimilarityND> {
return this;
}
- @Override
- public Matrix<?> toMatrix() {
- final Matrix<?> matrix = MatrixND.create(dimension+1, dimension+1);
- final Vector<?> translation = getTranslation();
- final Matrix<?> rotation = getRotation();
- final Vector<?> scale = getScale();
- matrix.setToIdentity();
- matrix.set(rotation);
- matrix.scale(scale.extend(1).toArrayDouble());
- for (int i = 0, dimension = getDimension(); i < dimension; i++) {
- matrix.set(i, dimension, translation.get(i));
- }
- return matrix;
- }
-
- @Override
- public Matrix<?> toMatrix(Matrix<?> matrix) {
- if (matrix == null) matrix = MatrixND.create(dimension+1, dimension+1);
- final Vector<?> translation = getTranslation();
- final Matrix<?> rotation = getRotation();
- final Vector<?> scale = getScale();
- matrix.setToIdentity();
- matrix.set(rotation);
- matrix.scale(scale.extend(1).toArrayDouble());
- for (int i = 0, dimension = getDimension(); i < dimension; i++) {
- matrix.set(i, dimension, translation.get(i));
- }
- return matrix;
- }
-
- @Override
- public Affine<?> toAffine() {
- return AffineND.create(dimension).setFromMatrix(toMatrix());
- }
-
@Override
public SimilarityND copy() {
return new SimilarityND(dimension).set(this);