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 ad1fce0356 feat(Geometry): math Matrix extends geoapi Matrix, cleaning
Similarity classes
ad1fce0356 is described below
commit ad1fce03567e9af399e4dcb3093c8f2f322d315c
Author: jsorel <[email protected]>
AuthorDate: Thu Mar 5 14:41:27 2026 +0100
feat(Geometry): math Matrix extends geoapi Matrix, cleaning Similarity
classes
---
.../main/org/apache/sis/geometries/Geometries.java | 17 +-
.../apache/sis/geometries/math/AbstractMatrix.java | 142 +++---
.../sis/geometries/math/AbstractSimilarity.java | 294 +++++++++++
.../org/apache/sis/geometries/math/Affine.java | 2 +-
.../org/apache/sis/geometries/math/Affine1D.java | 4 +-
.../org/apache/sis/geometries/math/Affine2D.java | 12 +-
.../org/apache/sis/geometries/math/Affine3D.java | 28 +-
.../org/apache/sis/geometries/math/Affine4D.java | 46 +-
.../org/apache/sis/geometries/math/Matrices.java | 44 +-
.../org/apache/sis/geometries/math/Matrix.java | 58 ++-
.../org/apache/sis/geometries/math/Matrix2D.java | 28 +-
.../org/apache/sis/geometries/math/Matrix3D.java | 149 +++---
.../org/apache/sis/geometries/math/Matrix4D.java | 97 ++--
.../org/apache/sis/geometries/math/MatrixND.java | 42 +-
.../org/apache/sis/geometries/math/Quaternion.java | 15 +-
.../org/apache/sis/geometries/math/Similarity.java | 92 +++-
.../apache/sis/geometries/math/Similarity3D.java | 176 +++++++
.../apache/sis/geometries/math/SimilarityND.java | 551 ++-------------------
.../org/apache/sis/geometries/scene/SceneNode.java | 6 +-
.../apache/sis/geometries/math/QuaternionTest.java | 2 +-
20 files changed, 918 insertions(+), 887 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 42d95d729a..227d69454e 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
@@ -55,6 +55,7 @@ import org.apache.sis.geometries.math.Array;
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.geometries.math.Matrix3D;
import org.apache.sis.geometry.wrapper.jts.JTS;
import org.apache.sis.measure.Units;
import org.apache.sis.referencing.CRS;
@@ -63,7 +64,6 @@ import org.apache.sis.referencing.cs.DefaultCartesianCS;
import org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
import org.apache.sis.referencing.cs.DefaultLinearCS;
import org.apache.sis.referencing.datum.DefaultEngineeringDatum;
-import org.apache.sis.referencing.operation.matrix.Matrix3;
import org.apache.sis.referencing.operation.transform.LinearTransform;
import org.apache.sis.referencing.internal.shared.AxisDirections;
import org.apache.sis.util.ArgumentChecks;
@@ -228,21 +228,10 @@ public final class Geometries {
/**
* Get rotation matrix from Geometry crs to another.
*/
- public static Matrix3 createRotation(CoordinateReferenceSystem crs1,
CoordinateReferenceSystem crs2) throws FactoryException {
+ public static Matrix3D createRotation(CoordinateReferenceSystem crs1,
CoordinateReferenceSystem crs2) throws FactoryException {
final MathTransform trs = CRS.findOperation(crs1, crs2,
null).getMathTransform();
final LinearTransform lt = (LinearTransform) trs;
- final Matrix m = lt.getMatrix();
- final Matrix3 rotation = new Matrix3();
- rotation.m00 = m.getElement(0, 0);
- rotation.m01 = m.getElement(0, 1);
- rotation.m02 = m.getElement(0, 2);
- rotation.m10 = m.getElement(1, 0);
- rotation.m11 = m.getElement(1, 1);
- rotation.m12 = m.getElement(1, 2);
- rotation.m20 = m.getElement(2, 0);
- rotation.m21 = m.getElement(2, 1);
- rotation.m22 = m.getElement(2, 2);
- return rotation;
+ return new Matrix3D().set(lt.getMatrix());
}
/**
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 22c38515e4..55110a2b5c 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
@@ -24,7 +24,7 @@ import java.util.Arrays;
* @author Johann Sorel
* @aurhor Bertrand COTE
*/
-abstract class AbstractMatrix<T extends AbstractMatrix<T>> extends
SimplifiedTransform implements Matrix<T>{
+abstract class AbstractMatrix<T extends AbstractMatrix<T>> extends
SimplifiedTransform implements Matrix<T> {
protected final int nbRow;
protected final int nbCol;
@@ -42,12 +42,12 @@ abstract class AbstractMatrix<T extends AbstractMatrix<T>>
extends SimplifiedTra
}
@Override
- public int getNbRow() {
+ public int getNumRow() {
return nbRow;
}
@Override
- public int getNbCol() {
+ public int getNumCol() {
return nbCol;
}
@@ -61,19 +61,25 @@ abstract class AbstractMatrix<T extends AbstractMatrix<T>>
extends SimplifiedTra
return nbRow;
}
-
////////////////////////////////////////////////////////////////////////////
- // get/set matrix values
///////////////////////////////////////////////////
-
////////////////////////////////////////////////////////////////////////////
-
@Override
- public double[][] toArray2DoubleRowOrder() {
- final double[][] C = new double[nbRow][nbCol];
- for (int r = 0; r < nbRow; r++) {
- for (int c = 0; c < nbCol; c++) {
- C[r][c] = get(r,c);
+ public double[][] toArray2Double(boolean rowOrder) {
+ if (rowOrder) {
+ final double[][] C = new double[nbRow][nbCol];
+ for (int r = 0; r < nbRow; r++) {
+ for (int c = 0; c < nbCol; c++) {
+ C[r][c] = get(r,c);
+ }
+ }
+ return C;
+ } else {
+ final double[][] C = new double[nbCol][nbRow];
+ for (int r = 0; r < nbRow; r++) {
+ for (int c = 0; c < nbCol; c++) {
+ C[c][r] = get(r,c);
+ }
}
+ return C;
}
- return C;
}
@Override
@@ -207,8 +213,8 @@ abstract class AbstractMatrix<T extends AbstractMatrix<T>>
extends SimplifiedTra
@Override
public T set(final Matrix<?> toCopy){
- final int rm = Math.min(this.nbRow, toCopy.getNbRow());
- final int cm = Math.min(this.nbCol, toCopy.getNbCol());
+ final int rm = Math.min(this.nbRow, toCopy.getNumRow());
+ final int cm = Math.min(this.nbCol, toCopy.getNumCol());
for (int r=0;r<rm;r++){
for (int c=0;c<cm;c++){
set(r, c, toCopy.get(r, c));
@@ -218,20 +224,36 @@ abstract class AbstractMatrix<T extends
AbstractMatrix<T>> extends SimplifiedTra
}
@Override
- public T set(final double[] values){
- for (int i=0,r=0;r<nbRow;r++){
- for (int c=0;c<nbCol;c++,i++){
- set(r, c, values[i]);
+ public T set(final double[] values, boolean rowOrder){
+ if (rowOrder) {
+ for (int i=0,r=0;r<nbRow;r++){
+ for (int c=0;c<nbCol;c++,i++){
+ set(r, c, values[i]);
+ }
+ }
+ } else {
+ for (int i=0,c=0;c<nbCol;c++){
+ for (int r=0;r<nbRow;r++,i++){
+ set(r, c, values[i]);
+ }
}
}
return (T) this;
}
@Override
- public T set(final double[][] values){
- for (int r=0;r<nbRow;r++){
- for (int c=0;c<nbCol;c++){
- set(r, c, values[r][c]);
+ public T set(final double[][] values, boolean rowOrder){
+ if (rowOrder) {
+ for (int r=0;r<nbRow;r++){
+ for (int c=0;c<nbCol;c++){
+ set(r, c, values[r][c]);
+ }
+ }
+ } else {
+ for (int r=0;r<nbRow;r++){
+ for (int c=0;c<nbCol;c++){
+ set(r, c, values[c][r]);
+ }
}
}
return (T) this;
@@ -345,6 +367,18 @@ abstract class AbstractMatrix<T extends AbstractMatrix<T>>
extends SimplifiedTra
return (T) this;
}
+ @Override
+ public T set(org.opengis.referencing.operation.Matrix toCopy) {
+ final int rm = Math.min(this.nbRow, toCopy.getNumRow());
+ final int cm = Math.min(this.nbCol, toCopy.getNumCol());
+ for (int r=0;r<rm;r++){
+ for (int c=0;c<cm;c++){
+ set(r, c, toCopy.getElement(r, c));
+ }
+ }
+ return (T) this;
+
+ }
/**
* Set Matrix value to identity matrix.
* @return this matrix
@@ -415,41 +449,41 @@ abstract class AbstractMatrix<T extends
AbstractMatrix<T>> extends SimplifiedTra
*/
@Override
public T invert(){
- final double[][] inverse =
Matrices.localInvert(toArray2DoubleRowOrder());
+ final double[][] inverse =
Matrices.localInvert(toArray2Double(ROW_ORDER));
if (inverse == null){
throw new IllegalArgumentException("Can not inverse");
}
- set(inverse);
+ set(inverse, ROW_ORDER);
return (T) this;
}
@Override
public T add(Matrix<?> other){
- set(Matrices.localAdd(dArray(this), dArray(other)));
+ set(Matrices.localAdd(dArray(this), dArray(other)), ROW_ORDER);
return (T) this;
}
@Override
public T subtract(Matrix<?> other){
- set(Matrices.localSubtract(dArray(this), dArray(other)));
+ set(Matrices.localSubtract(dArray(this), dArray(other)), ROW_ORDER);
return (T) this;
}
@Override
public T scale(double[] tuple){
- set(Matrices.localScale(dArray(this), tuple));
+ set(Matrices.localScale(dArray(this), tuple), ROW_ORDER);
return (T) this;
}
@Override
public T scale(double scale){
- set(Matrices.localScale(dArray(this), scale));
+ set(Matrices.localScale(dArray(this), scale), ROW_ORDER);
return (T) this;
}
@Override
public T multiply(Matrix<?> other){
- set(Matrices.localMultiply(dArray(this), dArray(other)));
+ set(Matrices.localMultiply(dArray(this), dArray(other)), ROW_ORDER);
return (T) this;
}
@@ -470,33 +504,20 @@ abstract class AbstractMatrix<T extends
AbstractMatrix<T>> extends SimplifiedTra
}
}
- /**
- * Matrix as 1D double array, in column order.
- *
- * @return 1D double array, in column order.
- */
@Override
- public double[] toArrayDoubleColOrder(){
+ public double[] toArrayDouble(boolean rowOrder){
final double[] array = new double[nbRow*nbCol];
- for (int p=0,c=0;c<nbCol;c++){
- for (int r=0;r<nbRow;r++,p++){
- array[p] = get(r, c);
+ if (rowOrder) {
+ for (int p=0,r=0;r<nbRow;r++){
+ for (int c=0;c<nbCol;c++,p++){
+ array[p] = get(r, c);
+ }
}
- }
- return array;
- }
-
- /**
- * Matrix as 1D double array, in row order.
- *
- * @return 1D double array, in row order.
- */
- @Override
- public double[] toArrayDoubleRowOrder(){
- final double[] array = new double[nbRow*nbCol];
- for (int p=0,r=0;r<nbRow;r++){
- for (int c=0;c<nbCol;c++,p++){
- array[p] = get(r, c);
+ } else {
+ for (int p=0,c=0;c<nbCol;c++){
+ for (int r=0;r<nbRow;r++,p++){
+ array[p] = get(r, c);
+ }
}
}
return array;
@@ -537,21 +558,26 @@ abstract class AbstractMatrix<T extends
AbstractMatrix<T>> extends SimplifiedTra
return false;
}
final Matrix other = (Matrix) obj;
- if (this.nbRow != other.getNbRow()) {
+ if (this.nbRow != other.getNumRow()) {
return false;
}
- if (this.nbCol != other.getNbCol()) {
+ if (this.nbCol != other.getNumCol()) {
return false;
}
//check values
- if (!Arrays.equals(toArrayDoubleRowOrder(),
other.toArrayDoubleRowOrder())){
+ if (!Arrays.equals(toArrayDouble(ROW_ORDER),
other.toArrayDouble(ROW_ORDER))){
return false;
}
return true;
}
+ @Override
+ public org.opengis.referencing.operation.Matrix clone() {
+ return copy();
+ }
+
protected static double[][] dArray(Matrix matrix){
- return matrix instanceof MatrixND ? ((MatrixND) matrix).values :
matrix.toArray2DoubleRowOrder();
+ return matrix instanceof MatrixND ? ((MatrixND) matrix).values :
matrix.toArray2Double(ROW_ORDER);
}
}
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
new file mode 100644
index 0000000000..70df85eec4
--- /dev/null
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/AbstractSimilarity.java
@@ -0,0 +1,294 @@
+/*
+ * 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.math;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.Arrays;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+public abstract class AbstractSimilarity<T extends AbstractSimilarity<T>>
extends SimplifiedTransform implements Similarity<T>{
+
+ protected static final String PROPERTY_MATRIX = "matrix";
+
+ //keep track of the matrix state
+ protected final Object lock = new Object();
+ protected PropertyChangeSupport eventManager;
+ protected final Matrix<?> oldMatrix;
+
+ protected boolean dirty = true;
+ protected boolean inverseDirty = true;
+ protected boolean affineDirty = true;
+
+ //store a view of the global matrix of size dimension+1
+ //which group rotation,scale and translation
+ private final Matrix<?> matrix;
+ private final Matrix<?> inverseMatrix;
+ private final Matrix<?> inverseRotation;
+ private final Affine<?> affine;
+ private final Affine<?> inverseAffine;
+
+ public AbstractSimilarity(int dimension) {
+ super(dimension);
+
+ this.inverseRotation = MatrixND.create(dimension,
dimension).setToIdentity();
+ this.dirty = false;
+ final int msize = dimension + 1;
+ this.matrix = MatrixND.create(msize, msize).setToIdentity();
+ this.oldMatrix = this.matrix.copy();
+ this.inverseMatrix = this.matrix.copy();
+ this.affine = AffineND.create(dimension);
+ this.inverseAffine = AffineND.create(dimension);
+ }
+
+ /**
+ * Get a general matrix view of size : dimension+1
+ * This matrix 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]
+ * [ 0, 0, 0, 1]
+ *
+ * @return Matrix, never null
+ */
+ @Override
+ public Matrix<?> viewMatrix(){
+ if (dirty){
+ dirty = false;
+ //update matrix
+ 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));
+ }
+ oldMatrix.set(matrix);
+ if (!matrix.isFinite()){
+ throw new RuntimeException("Matrix is not finite
:\nRotation\n"+rotation+"Scale "+scale+"\nTranslate "+translation);
+ }
+ }
+ return matrix;
+ }
+
+ /**
+ * Get a general inverse matrix view of size : dimension+1
+ * DO NOT MODIFY THIS MATRIX.
+ *
+ * @return Matrix, never null
+ */
+ @Override
+ public Matrix<?> viewMatrixInverse(){
+ if (dirty){
+ viewMatrix();
+ }
+ if (inverseDirty){
+ inverseDirty = false;
+ inverseRotation.set(getRotation()).invert();
+ inverseMatrix.set(matrix).invert();
+ }
+ return inverseMatrix;
+ }
+
+ @Override
+ public Affine<?> viewAffine() {
+ if (dirty || affineDirty) {
+ affine.setFromMatrix(viewMatrix());
+ inverseAffine.setFromMatrix(viewMatrixInverse());
+ affineDirty = false;
+ }
+ return affine;
+ }
+
+ @Override
+ public Affine<?> viewAffineInverse() {
+ if (dirty || affineDirty) {
+ affine.setFromMatrix(viewMatrix());
+ inverseAffine.setFromMatrix(viewMatrixInverse());
+ affineDirty = false;
+ }
+ return inverseAffine;
+ }
+
+ @Override
+ public T setFromAffine(Affine<?> trs){
+ setFromMatrix(trs.toMatrix());
+ return (T) this;
+ }
+
+ @Override
+ public T setFromMatrix(Matrix<?> matrix) {
+ Matrices.decomposeMatrix(matrix, getRotation(), getScale(),
getTranslation());
+ notifyChanged();
+ return (T) this;
+ }
+
+ @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;
+ }
+
+ @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;
+ }
+
+ @Override
+ public T invert() {
+ return setFromAffine(toAffine().invert());
+ }
+
+ /**
+ * Test if this transform is identity.
+ * <ul>
+ * <li>Scale must be all at 1</li>
+ * <li>Translation must be all at 0</li>
+ * <li>Rotation must be an identity matrix</li>
+ * </ul>
+ *
+ * @return true if transform is identity.
+ */
+ @Override
+ public boolean isIdentity() {
+ return getScale().isAll(1) && getTranslation().isAll(0) &&
getRotation().isIdentity();
+ }
+
+ @Override
+ public Transform createInverse() {
+ return toAffine().invert().copy();
+ }
+
+ @Override
+ public Tuple<?> transform(Tuple<?> source, Tuple<?> out) {
+ return toAffine().transform(source, out);
+ }
+
+ @Override
+ public void transform(double[] in, int sourceOffset, double[] out, int
destOffset, int nbTuple) {
+ toAffine().transform(in, sourceOffset, out, destOffset, nbTuple);
+ }
+
+ @Override
+ public void transform(float[] in, int sourceOffset, float[] out, int
destOffset, int nbTuple) {
+ toAffine().transform(in, sourceOffset, out, destOffset, nbTuple);
+ }
+
+ @Override
+ protected void transform1(double[] source, int sourceOffset, double[]
dest, int destOffset) {
+ toAffine().transform(source, sourceOffset, dest, destOffset, 1);
+ }
+
+ @Override
+ protected void transform1(float[] source, int sourceOffset, float[] dest,
int destOffset) {
+ toAffine().transform(source, sourceOffset, dest, destOffset, 1);
+ }
+
+ @Override
+ public Tuple<?> inverseTransform(Tuple<?> source, Tuple<?> dest) {
+ return toAffine().invert().transform(source, dest);
+ }
+
+ @Override
+ public Matrix<?> toMatrix() {
+ return viewMatrix().copy();
+ }
+
+ @Override
+ public Matrix<?> toMatrix(Matrix<?> buffer) {
+ if (buffer == null) return toMatrix();
+ buffer.set(viewMatrix());
+ return buffer;
+ }
+
+ protected PropertyChangeSupport getEventManager() {
+ return getEventManager(true);
+ }
+
+ protected PropertyChangeSupport getEventManager(boolean create) {
+ synchronized (lock){
+ if (eventManager==null && create) eventManager = new
PropertyChangeSupport(this);
+ }
+ return eventManager;
+ }
+
+ public void addEventListener(PropertyChangeListener listener) {
+ getEventManager().addPropertyChangeListener(listener);
+ }
+
+ public void removeEventListener(PropertyChangeListener listener) {
+ getEventManager().removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Flag to indicate the transform parameters has changed.
+ * This is used to recalculate the general matrix when needed.
+ */
+ @Override
+ public void notifyChanged(){
+ dirty = true;
+ inverseDirty = true;
+ affineDirty = true;
+
+ if (eventManager != null &&
eventManager.hasListeners(PROPERTY_MATRIX)) {
+ //we have listeners, we need to recalculate the transform now
+ eventManager.firePropertyChange(PROPERTY_MATRIX, oldMatrix.copy(),
viewMatrix().copy());
+ }
+ }
+}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine.java
index 31816bd4a8..5bd4f1f333 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine.java
@@ -155,7 +155,7 @@ public interface Affine<T extends Affine<T>> extends
Transform {
* @param buffer to store matrix values in
* @return matrix
*/
- Matrix<?> toMatrix(Matrix buffer);
+ Matrix<?> toMatrix(Matrix<?> buffer);
/**
* Create a copy of this Affine.
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine1D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine1D.java
index 0a35eba6c6..a9bf2d4c69 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine1D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine1D.java
@@ -22,8 +22,8 @@ package org.apache.sis.geometries.math;
*/
public final class Affine1D extends AbstractAffine<Affine1D> implements
Transform1D {
- private double m00;
- private double m01;
+ double m00;
+ double m01;
public Affine1D() {
super(1);
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine2D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine2D.java
index 9bc0a90fae..e34573ea90 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine2D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine2D.java
@@ -23,12 +23,12 @@ package org.apache.sis.geometries.math;
*/
public final class Affine2D extends AbstractAffine<Affine2D> {
- private double m00;
- private double m01;
- private double m02;
- private double m10;
- private double m11;
- private double m12;
+ double m00;
+ double m01;
+ double m02;
+ double m10;
+ double m11;
+ double m12;
public Affine2D() {
super(2);
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine3D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine3D.java
index 1dbf531125..0a9137e6bc 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine3D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine3D.java
@@ -22,18 +22,18 @@ package org.apache.sis.geometries.math;
*/
public final class Affine3D extends AbstractAffine<Affine3D> {
- private double m00;
- private double m01;
- private double m02;
- private double m03;
- private double m10;
- private double m11;
- private double m12;
- private double m13;
- private double m20;
- private double m21;
- private double m22;
- private double m23;
+ double m00;
+ double m01;
+ double m02;
+ double m03;
+ double m10;
+ double m11;
+ double m12;
+ double m13;
+ double m20;
+ double m21;
+ double m22;
+ double m23;
public Affine3D() {
super(3);
@@ -263,7 +263,7 @@ public final class Affine3D extends
AbstractAffine<Affine3D> {
}
@Override
- public Affine3D setFromMatrix(Matrix m) {
+ public Affine3D setFromMatrix(Matrix<?> m) {
m00 = m.get(0, 0);
m01 = m.get(0, 1);
m02 = m.get(0, 2);
@@ -331,7 +331,7 @@ public final class Affine3D extends
AbstractAffine<Affine3D> {
}
@Override
- public Matrix toMatrix(Matrix buffer) {
+ public Matrix<?> toMatrix(Matrix<?> buffer) {
if (buffer == null) return toMatrix();
buffer.set(0, 0, m00);
buffer.set(0, 1, m01);
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine4D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine4D.java
index cac4150225..f22c3ee952 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine4D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Affine4D.java
@@ -22,29 +22,29 @@ package org.apache.sis.geometries.math;
*/
public final class Affine4D extends AbstractAffine<Affine4D> {
- private double m00;
- private double m01;
- private double m02;
- private double m03;
- private double m04;
-
- private double m10;
- private double m11;
- private double m12;
- private double m13;
- private double m14;
-
- private double m20;
- private double m21;
- private double m22;
- private double m23;
- private double m24;
-
- private double m30;
- private double m31;
- private double m32;
- private double m33;
- private double m34;
+ double m00;
+ double m01;
+ double m02;
+ double m03;
+ double m04;
+
+ double m10;
+ double m11;
+ double m12;
+ double m13;
+ double m14;
+
+ double m20;
+ double m21;
+ double m22;
+ double m23;
+ double m24;
+
+ double m30;
+ double m31;
+ double m32;
+ double m33;
+ double m34;
public Affine4D() {
super(4);
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 e1a3c737f4..650788c8d0 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
@@ -626,27 +626,6 @@ public final class Matrices {
return buffer;
}
- /**
- * Create rotation matrix to move v1 on v2.
- *
- * @param v1
- * @param v2
- * @return
- */
- public static Matrix4D createRotation(Vector<?> v1, Vector<?> v2){
- v1 = v1.normalize();
- v2 = v2.normalize();
- final double angle = Math.acos(v1.dot(v2));
- if (angle==0){
- //vectors are colinear
- Matrix4D identity = new Matrix4D();
- return identity;
- }
- final Vector axis = v1.copy().cross(v2).normalize();
- double[][] m = Matrices.createRotation4(angle, axis, null);
- return new Matrix4D(m);
- }
-
/**
* Build rotation matrix from Euler angle.
* Sources :
@@ -770,27 +749,6 @@ public final class Matrices {
return buffer;
}
- public static Matrix3D createFromUpAndRight(Vector<?> v, Vector<?> u) {
- v = v.copy();
- u = u.copy();
- v.normalize();
- u.normalize();
-
- //W = Normalized(Cross(V,U))
- Vector w = v.cross(u);
- w.normalize();
-
- //to ensure it is correctly perpendicular
- //U = Normalized(Cross(W,V))
- u = w.cross(v);
- u.normalize();
-
- return new Matrix3D(
- u.get(0), w.get(0), v.get(0),
- u.get(1), w.get(1), v.get(1),
- u.get(2), w.get(2), v.get(2));
- }
-
/**
* Create and orbit matrix 4x4 focus on the root point (0,0,0).
*
@@ -832,7 +790,7 @@ public final class Matrices {
* The matrix is expected to be orthogonal of size 3x3 or 4x4.
*/
public static void decomposeMatrix(Matrix<?> trs, Matrix<?> rotation,
Tuple<?> scale, Tuple<?> translation){
- final int dimension = trs.getNbCol()-1;
+ 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));
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 07a673cff3..2b32973823 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
@@ -23,11 +23,26 @@ import
org.apache.sis.referencing.operation.matrix.MatrixSIS;
* @author Johann Sorel (Geomatys)
* @todo Remove this class when all elements are merged in MatrixSIS
*/
-public interface Matrix<T extends Matrix<T>> extends Transform {
+public interface Matrix<T extends Matrix<T>> extends Transform,
org.opengis.referencing.operation.Matrix {
- int getNbRow();
+ public static final boolean ROW_ORDER = true;
+ public static final boolean COL_ORDER = false;
- int getNbCol();
+ @Override
+ int getNumRow();
+
+ @Override
+ int getNumCol();
+
+ @Override
+ default boolean isIdentity() {
+ return org.opengis.referencing.operation.Matrix.super.isIdentity();
+ }
+
+ @Override
+ default double getElement(int row, int col) {
+ return get(row,col);
+ }
double get(int row, int col);
@@ -85,13 +100,18 @@ public interface Matrix<T extends Matrix<T>> extends
Transform {
*/
Matrix<?> getRange(int[] r, int j0, int j1);
+ @Override
+ default void setElement(int row, int col, double value) {
+ set(row, col, value);
+ }
+
T set(int row, int col, double value);
T set(final Matrix<?> toCopy);
- T set(final double[] values);
+ T set(final double[] values, boolean rowOrder);
- T set(final double[][] values);
+ T set(final double[][] values, boolean rowOrder);
T setRow(int row, double[] values);
@@ -142,25 +162,20 @@ public interface Matrix<T extends Matrix<T>> extends
Transform {
T setRange(int i0, int i1, int[] c, Matrix<?> X);
/**
- * Matrix as 2D double array, in row order.
- *
- * @return 2D double array, in row order.
- */
- double[][] toArray2DoubleRowOrder();
-
- /**
- * Matrix as 1D double array, in column order.
+ * Matrix as 2D double array.
*
- * @return 1D double array, in column order.
+ * @param rowOrder true for row order, col order otherwise
+ * @return 2D double array
*/
- double[] toArrayDoubleColOrder();
+ double[][] toArray2Double(boolean rowOrder);
/**
- * Matrix as 1D double array, in row order.
+ * Matrix as 1D double array.
*
- * @return 1D double array, in row order.
+ * @param rowOrder true for row order, col order otherwise
+ * @return 1D double array
*/
- double[] toArrayDoubleRowOrder();
+ double[] toArrayDouble(boolean rowOrder);
/**
* Set Matrix value to identity matrix.
@@ -187,6 +202,11 @@ public interface Matrix<T extends Matrix<T>> extends
Transform {
T copy();
+ @Override
+ default org.opengis.referencing.operation.Matrix clone() {
+ return copy();
+ }
+
/**
* Test if all cells in the matrix equals given value.
* @param scalar scalar
@@ -210,4 +230,6 @@ public interface Matrix<T extends Matrix<T>> extends
Transform {
* @return sis matrix equivalent
*/
MatrixSIS toMatrixSIS();
+
+ T set(org.opengis.referencing.operation.Matrix matrix);
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix2D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix2D.java
index ce498fe702..e1a5c2cdfc 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix2D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix2D.java
@@ -30,11 +30,16 @@ public class Matrix2D extends AbstractMatrix<Matrix2D> {
double m00,m01;
double m10,m11;
+ /**
+ * New identity matrix2D
+ */
public Matrix2D() {
super(2, 2);
+ m00 = 1;
+ m11 = 1;
}
- public Matrix2D(Matrix m) {
+ public Matrix2D(Matrix<?> m) {
super(2, 2);
m00 = m.get(0, 0);
m01 = m.get(0, 1);
@@ -81,7 +86,7 @@ public class Matrix2D extends AbstractMatrix<Matrix2D> {
}
@Override
- public Matrix2D set(final Matrix toCopy){
+ public Matrix2D set(final Matrix<?> toCopy){
if (toCopy instanceof Matrix2D){
Matrix2D o = (Matrix2D) toCopy;
m00 = o.m00;m01 = o.m01;
@@ -158,7 +163,7 @@ public class Matrix2D extends AbstractMatrix<Matrix2D> {
}
@Override
- public Matrix2D multiply(Matrix other) {
+ public Matrix2D multiply(Matrix<?> other) {
if (other instanceof Matrix2D){
//usual case
Matrix2D o = (Matrix2D) other;
@@ -191,7 +196,7 @@ public class Matrix2D extends AbstractMatrix<Matrix2D> {
}
@Override
- public Tuple transform(Tuple vector, Tuple buffer) {
+ public Tuple<?> transform(Tuple<?> vector, Tuple<?> buffer) {
if (buffer == null) buffer = new Vector2D.Double();
if (vector instanceof Vector2D.Double && buffer instanceof
Vector2D.Double) {
@@ -217,19 +222,4 @@ public class Matrix2D extends AbstractMatrix<Matrix2D> {
return new Matrix2(m00, m01, m10, m11);
}
- /**
- * Create rotation matrix from angle.
- *
- * @param angle in radians
- * @return Matrix2
- */
- public static Matrix2D fromAngle(double angle) {
- final Matrix2D m = new Matrix2D();
- m.set(0, 0, Math.cos(angle));
- m.set(0, 1, -Math.sin(angle));
- m.set(1, 0, Math.sin(angle));
- m.set(1, 1, Math.cos(angle));
- return m;
- }
-
}
\ No newline at end of file
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 b6c6f7ade6..72d1d02b12 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
@@ -31,8 +31,14 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
double m10,m11,m12;
double m20,m21,m22;
+ /**
+ * New identity matrix3D
+ */
public Matrix3D() {
super(3, 3);
+ m00 = 1;
+ m11 = 1;
+ m22 = 1;
}
public Matrix3D(Matrix<?> m) {
@@ -219,7 +225,7 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
}
@Override
- public Matrix3D multiply(Matrix other) {
+ public Matrix3D multiply(Matrix<?> other) {
if (other instanceof Matrix3D o){
//usual case
double b00 = this.m00 * o.m00 + this.m01 * o.m10 + this.m02 *
o.m20;
@@ -260,7 +266,7 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
}
@Override
- public Tuple transform(Tuple vector, Tuple buffer) {
+ public Tuple<?> transform(Tuple<?> vector, Tuple<?> buffer) {
if (buffer == null) buffer = new Vector3D.Double();
if (vector instanceof Vector3D.Double v && buffer instanceof
Vector3D.Double b) {
@@ -291,20 +297,26 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
* @return euler angle in radians (heading/yaw , elevation/pitch ,
bank/roll)
*/
public Vector<?> toEuler(){
- return new VectorND.Double(Matrices.toEuler(toArray2DoubleRowOrder(),
null));
+ return new VectorND.Double(Matrices.toEuler(toArray2Double(ROW_ORDER),
null));
}
/**
+ * Build rotation matrix from euler angle.
*
* @param euler in radians (heading/yaw , elevation/pitch , bank/roll)
- * @return
+ * @return this matrix
*/
- public Matrix3D fromEuler(Tuple<?> euler){
- set(Matrices.fromEuler(euler.toArrayDouble(), new double[3][3]));
+ public Matrix3D setFromEuler(Tuple<?> euler){
+ set(Matrices.fromEuler(euler.toArrayDouble(), new double[3][3]),
ROW_ORDER);
return this;
}
- public Matrix3D fromAngle(final double angle, final Tuple<?> rotationAxis){
+ /**
+ * @param angle in radians
+ * @param rotationAxis rotation axis
+ * @return this matrix
+ */
+ public Matrix3D setFromAngle(final double angle, final Tuple<?>
rotationAxis){
final double fCos = Math.cos(angle);
final double fSin = Math.sin(angle);
final double fOneMinusCos = (1.0) - fCos;
@@ -330,97 +342,92 @@ public class Matrix3D extends AbstractMatrix<Matrix3D> {
return this;
}
- @Override
- public Matrix3D copy() {
- return new Matrix3D(this);
- }
-
- @Override
- public MatrixSIS toMatrixSIS() {
- return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
+ /**
+ * Create a rotation matrix as the concatenation of rotation on x,y,z axis.
+ *
+ * @param x in radians
+ * @param y in radians
+ * @param z in radians
+ * @return
+ */
+ public Matrix3D setFromAngles(double x, double y, double z){
+ setFromAngle(x, new Vector3D.Double(1, 0, 0));
+ Matrix3D r2 = new Matrix3D().setFromAngle(y, new Vector3D.Double(0, 1,
0));
+ Matrix3D r3 = new Matrix3D().setFromAngle(z, new Vector3D.Double(0, 0,
1));
+ this.multiply(r2);
+ this.multiply(r3);
+ return this;
}
/**
- * @return determinant
+ * Create rotation matrix from 3 axis.
+ * Each Tuple must be unit length(normalized)
+ *
+ * @param xAxis values are copied in 1th row
+ * @param yAxis values are copied in 2nd row
+ * @param zAxis values are copied in 3rd row
+ * @return rotation matrix
*/
- public double getDeterminant(){
- return m00 * (m11 * m22 - m12 * m21) -
- m01 * (m10 * m22 - m12 * m20) +
- m02 * (m10 * m21 - m11 * m20);
+ public Matrix3D setFromAxis(final Tuple<?> xAxis, final Tuple<?> yAxis,
final Tuple<?> zAxis){
+ setToIdentity();
+ this.setRow(0, xAxis.toArrayDouble());
+ this.setRow(1, yAxis.toArrayDouble());
+ this.setRow(2, zAxis.toArrayDouble());
+ return this;
}
/**
* Create rotation matrix to move v1 on v2.
*
- * @param v1
- * @param v2
- * @return
+ * @param v1 moving vector
+ * @param v2 target vector
+ * @return this matrix
*/
- public static Matrix3D createRotation(Vector<?> v1, Vector<?> v2){
+ public Matrix3D setFromVectors(Vector<?> v1, Vector<?> v2) {
v1 = v1.normalize();
v2 = v2.normalize();
final double angle = Math.acos(v1.dot(v2));
if (angle == 0){
//vectors are colinear
- Matrix3D identity = new Matrix3D().setToIdentity();
- return identity;
+ return setToIdentity();
}
final Vector<?> axis = v1.cross(v2).normalize();
- return createRotation3(angle, axis);
+ return setFromAngle(angle, axis);
}
- /**
- *
- * @param angle in radians
- * @param rotateAxis, rotation axis
- * @return
- */
- public static Matrix3D createRotation3(final double angle, final Tuple
rotateAxis){
- return new Matrix3D().fromAngle(angle, rotateAxis);
+ public Matrix3D setFromUpAndRight(Vector<?> v, Vector<?> u) {
+ v = v.copy().normalize();
+ u = u.copy().normalize();
+
+ //W = Normalized(Cross(V,U))
+ Vector<?> w = v.cross(u).normalize();
+
+ //to ensure it is correctly perpendicular
+ //U = Normalized(Cross(W,V))
+ u = w.cross(v).normalize();
+ setCol(0, u.toArrayDouble());
+ setCol(1, w.toArrayDouble());
+ setCol(2, v.toArrayDouble());
+ return this;
}
- /**
- * Build rotation matrix from euler angle.
- *
- * @param euler angles in radians (heading/yaw , elevation/pitch ,
bank/roll)
- * @return Matrix3
- */
- public static Matrix3D createRotationEuler(final Tuple euler){
- return new Matrix3D().fromEuler(euler);
+ @Override
+ public Matrix3D copy() {
+ return new Matrix3D(this);
}
- /**
- * Create rotation matrix from 3 axis.
- * Each Tuple must be unit length(normalized)
- *
- * @param xAxis values are copied in 1th row
- * @param yAxis values are copied in 2nd row
- * @param zAxis values are copied in 3rd row
- * @return rotation matrix
- */
- public static Matrix3D createFromAxis(final Tuple xAxis, final Tuple
yAxis, final Tuple zAxis){
- final Matrix3D m = new Matrix3D().setToIdentity();
- m.setRow(0, xAxis.toArrayDouble());
- m.setRow(1, yAxis.toArrayDouble());
- m.setRow(2, zAxis.toArrayDouble());
- return m;
+ @Override
+ public MatrixSIS toMatrixSIS() {
+ return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
}
/**
- * Create a rotation matrix as the concatenation of rotation on x,y,z axis.
- *
- * @param x in radians
- * @param y in radians
- * @param z in radians
- * @return
+ * @return determinant
*/
- public static Matrix3D createFromAngles(double x, double y, double z){
- Matrix3D r1 = Matrix3D.createRotation3(x, new Vector3D.Double(1, 0,
0));
- Matrix3D r2 = Matrix3D.createRotation3(y, new Vector3D.Double(0, 1,
0));
- Matrix3D r3 = Matrix3D.createRotation3(z, new Vector3D.Double(0, 0,
1));
- r1.multiply(r2);
- r1.multiply(r3);
- return r1;
+ public double getDeterminant(){
+ return m00 * (m11 * m22 - m12 * m21) -
+ m01 * (m10 * m22 - m12 * m20) +
+ m02 * (m10 * m21 - m11 * m20);
}
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix4D.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix4D.java
index 74f6902313..9c64cccce8 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix4D.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Matrix4D.java
@@ -16,6 +16,7 @@
*/
package org.apache.sis.geometries.math;
+import static org.apache.sis.geometries.math.Matrix.ROW_ORDER;
import org.apache.sis.referencing.operation.matrix.Matrix4;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
@@ -26,16 +27,23 @@ import
org.apache.sis.referencing.operation.matrix.MatrixSIS;
*/
public class Matrix4D extends AbstractMatrix<Matrix4D> {
- private double m00,m01,m02,m03;
- private double m10,m11,m12,m13;
- private double m20,m21,m22,m23;
- private double m30,m31,m32,m33;
+ double m00,m01,m02,m03;
+ double m10,m11,m12,m13;
+ double m20,m21,m22,m23;
+ double m30,m31,m32,m33;
+ /**
+ * New identity matrix4D
+ */
public Matrix4D() {
super(4, 4);
+ m00 = 1;
+ m11 = 1;
+ m22 = 1;
+ m33 = 1;
}
- public Matrix4D(Matrix m) {
+ public Matrix4D(Matrix<?> m) {
super(4, 4);
m00 = m.get(0, 0);m01 = m.get(0, 1);m02 = m.get(0, 2);m03 = m.get(0,
3);
m10 = m.get(1, 0);m11 = m.get(1, 1);m12 = m.get(1, 2);m13 = m.get(1,
3);
@@ -228,9 +236,8 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
* @param euler angles in radians (heading/yaw , elevation/pitch ,
bank/roll)
* @return Matrix4
*/
- public Matrix4D fromEuler(Tuple<?> euler){
- set(Matrices.fromEuler(euler.toArrayDouble(), null));
- return this;
+ public Matrix4D setFromEuler(Tuple<?> euler){
+ return set(Matrices.fromEuler(euler.toArrayDouble(), null), ROW_ORDER);
}
@Override
@@ -279,7 +286,7 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
@Override
public Matrix4D transpose(){
- return set(new Matrix4D(Matrices.transpose(toArray2DoubleRowOrder())));
+ return set(new
Matrix4D(Matrices.transpose(toArray2Double(ROW_ORDER))));
}
/**
@@ -321,26 +328,16 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
* @param rotation Matrix[3x3]
* @param scale Tuple[3]
* @param translation Tuple[3]
- * @return Matrix4
+ * @return this matrix
*/
- public static Matrix4D createFromComponents(final MatrixND rotation,
Tuple<?> scale, Tuple<?> translation){
- final Matrix4D matrix = new Matrix4D()
- .set(rotation)
- .scale(new VectorND.Double(scale).extend(1).toArrayDouble());
+ public Matrix4D setFromComponents(final MatrixND rotation, Tuple<?> scale,
Tuple<?> translation){
+ setToIdentity();
+ set(rotation);
+ scale(new VectorND.Double(scale).extend(1).toArrayDouble());
for (int i=0;i<translation.getDimension();i++){
- matrix.set(i, 3, translation.get(i));
+ set(i, 3, translation.get(i));
}
- return matrix;
- }
-
- /**
- * Build rotation matrix from euler angle.
- *
- * @param euler angles in radians (heading/yaw , elevation/pitch ,
bank/roll)
- * @return Matrix4
- */
- public static Matrix4D createRotationEuler(final Tuple<?> euler){
- return new Matrix4D(Matrices.fromEuler(euler.toArrayDouble(), new
double[4][4]));
+ return this;
}
/**
@@ -350,17 +347,16 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
* @param xAxis values are copied in 1th row
* @param yAxis values are copied in 2nd row
* @param zAxis values are copied in 3rd row
- * @return rotation matrix
+ * @return this matrix
*/
- public static Matrix4D createFromAxis(final Tuple<?> xAxis, final Tuple<?>
yAxis, final Tuple<?> zAxis){
- final Matrix4D m = new Matrix4D().setToIdentity();
- m.setRow(0, xAxis.toArrayDouble());
- m.setRow(1, yAxis.toArrayDouble());
- m.setRow(2, zAxis.toArrayDouble());
- return m;
+ public Matrix4D setFromAxis(final Tuple<?> xAxis, final Tuple<?> yAxis,
final Tuple<?> zAxis){
+ setToIdentity();
+ setRow(0, xAxis.toArrayDouble());
+ setRow(1, yAxis.toArrayDouble());
+ setRow(2, zAxis.toArrayDouble());
+ return this;
}
-
/**
* Create and orbit matrix 4x4 focus on the root point (0,0,0).
*
@@ -368,18 +364,39 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
* @param yAngle vertical angle
* @param rollAngle roll angle
* @param distance distance from base
- * @return orbit matrix 4x4
+ * @return this matrix, orbit matrix 4x4
*/
- public static Matrix4D focusedOrbit(final double xAngle,
+ public Matrix4D setFocusedOrbit(final double xAngle,
final double yAngle, double rollAngle, double distance){
- return new Matrix4D(Matrices.focusedOrbit(xAngle, yAngle, rollAngle,
distance));
+ return set(Matrices.focusedOrbit(xAngle, yAngle, rollAngle, distance),
ROW_ORDER);
+ }
+
+ /**
+ * Create rotation matrix to move v1 on v2.
+ *
+ * @param v1
+ * @param v2
+ * @return
+ */
+ public Matrix4D setFromVectors(Vector<?> v1, Vector<?> v2){
+ v1 = v1.normalize();
+ v2 = v2.normalize();
+ final double angle = Math.acos(v1.dot(v2));
+ if (angle==0){
+ //vectors are colinear
+ Matrix4D identity = new Matrix4D();
+ return identity;
+ }
+ final Vector<?> axis = v1.copy().cross(v2).normalize();
+ double[][] m = Matrices.createRotation4(angle, axis, null);
+ return set(m, ROW_ORDER);
}
-
///////////////////////////////////////////////////////////////////////////////
+ //
/////////////////////////////////////////////////////////////////////////////
// compute cofactor of 3x3 minor matrix without sign
// input params are 9 elements of the minor matrix
// NOTE: The caller must know its sign.
-
///////////////////////////////////////////////////////////////////////////////
+ //
/////////////////////////////////////////////////////////////////////////////
private static double getCofactor(
double m0, double m1, double m2,
double m3, double m4, double m5,
@@ -414,7 +431,7 @@ public class Matrix4D extends AbstractMatrix<Matrix4D> {
}
@Override
- public Tuple transform(Tuple vector, Tuple buffer) {
+ public Tuple<?> transform(Tuple<?> vector, Tuple<?> buffer) {
if (buffer == null) buffer = new Vector4D.Double();
if (vector instanceof Vector4D.Double && buffer instanceof
Vector4D.Double) {
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 867ed1220c..b33ad90030 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
@@ -36,7 +36,7 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
* @param nbcol
* @return
*/
- public static Matrix create(int nbrow, int nbcol){
+ public static Matrix<?> create(int nbrow, int nbcol){
if (nbrow==nbcol) {
switch(nbrow){
case 2 : return new Matrix2D();
@@ -49,8 +49,8 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
/**
* Create a new matrix of given size.
- * It is recommended to use statice create method to benefit from
specialized
- * matrices implementations such as Matric2,Matric4,Matrix4.
+ * It is recommended to use static create method to benefit from
specialized
+ * matrices implementations such as Matrix2D,Matrix3D,Matrix4D.
*
* @param nbrow
* @param nbcol
@@ -60,44 +60,14 @@ public class MatrixND extends AbstractMatrix<MatrixND>{
values = new double[nbrow][nbcol];
}
- protected MatrixND(final double m00, final double m01,
- final double m10, final double m11){
- this(new double[][]{
- {m00,m01},
- {m10,m11}
- });
- }
-
- protected MatrixND(final double m00, final double m01, final double m02,
- final double m10, final double m11, final double m12,
- final double m20, final double m21, final double m22){
- this(new double[][]{
- {m00,m01,m02},
- {m10,m11,m12},
- {m20,m21,m22}
- });
- }
-
- protected MatrixND(final double m00, final double m01, final double m02,
final double m03,
- final double m10, final double m11, final double m12, final
double m13,
- final double m20, final double m21, final double m22, final
double m23,
- final double m30, final double m31, final double m32, final
double m33){
- this(new double[][]{
- {m00,m01,m02,m03},
- {m10,m11,m12,m13},
- {m20,m21,m22,m23},
- {m30,m31,m32,m33}
- });
- }
-
public MatrixND(final double[][] values) {
super(values.length,values[0].length);
this.values = values;
}
- public MatrixND(Matrix m) {
- super(m.getNbRow(),m.getNbCol());
- values = m.toArray2DoubleRowOrder();
+ public MatrixND(Matrix<?> m) {
+ super(m.getNumRow(),m.getNumCol());
+ values = m.toArray2Double(ROW_ORDER);
}
public double[][] getValues() {
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Quaternion.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Quaternion.java
index 1703e7c266..275260b327 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Quaternion.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Quaternion.java
@@ -16,6 +16,8 @@
*/
package org.apache.sis.geometries.math;
+import static org.apache.sis.geometries.math.Matrix.ROW_ORDER;
+
/**
* Quaternion object.
*
@@ -350,7 +352,7 @@ public class Quaternion extends VectorND.Double {
* @return this Quaternion
*/
public Quaternion setFromMatrix(final Matrix matrix){
- final double[][] m = matrix.toArray2DoubleRowOrder();
+ final double[][] m = matrix.toArray2Double(ROW_ORDER);
final double trace = m[0][0] + m[1][1] + m[2][2] + 1;
final double s,x,y,z,w;
@@ -389,7 +391,7 @@ public class Quaternion extends VectorND.Double {
* @param angle rotation angle, in radians
* @return this quaternion
*/
- public Quaternion setFromAngle(Tuple axis, double angle) {
+ public Quaternion setFromAngle(Tuple<?> axis, double angle) {
Quaternions.fromAngle(axis, angle, values);
return this;
}
@@ -400,9 +402,8 @@ public class Quaternion extends VectorND.Double {
* @param euler angles in radians (heading/yaw , elevation/pitch ,
bank/roll)
* @return this quaternion
*/
- public Quaternion setFromEuler(Vector euler) {
- final Matrix3D matrix = Matrix3D.createRotationEuler(euler);
- return setFromMatrix(matrix);
+ public Quaternion setFromEuler(Vector<?> euler) {
+ return setFromMatrix(new Matrix3D().setFromEuler(euler));
}
/**
@@ -416,7 +417,7 @@ public class Quaternion extends VectorND.Double {
final double dot = base.dot(target);
if (dot < -0.999999) {
//try to find a better value on other axis
- Vector tmpvec3 = UNIT_X.cross(base);
+ Vector<?> tmpvec3 = UNIT_X.cross(base);
if (tmpvec3.length() < 0.000001) {
tmpvec3 = UNIT_Y.cross(base);
}
@@ -429,7 +430,7 @@ public class Quaternion extends VectorND.Double {
values[2] = 0;
values[3] = 1;
} else {
- final Vector cross = base.cross(target);
+ final Vector<?> cross = base.cross(target);
values[0] = cross.get(0);
values[1] = cross.get(1);
values[2] = cross.get(2);
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 2a22b7369d..60b371fb7b 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
@@ -16,6 +16,9 @@
*/
package org.apache.sis.geometries.math;
+import org.apache.sis.referencing.operation.transform.MathTransforms;
+import org.opengis.referencing.operation.MathTransform;
+
/**
* A similarity is the equivalent of a affine transform but preserving angles
by avoiding
* shearing value not rotations.
@@ -32,7 +35,7 @@ package org.apache.sis.geometries.math;
*
* @author Johann Sorel (Geomatys)
*/
-public interface Similarity<T extends Similarity<T>> extends Affine<T> {
+public interface Similarity<T extends Similarity<T>> extends Transform {
/**
* Dimension of the transform.
@@ -46,7 +49,7 @@ public interface Similarity<T extends Similarity<T>> extends
Affine<T> {
*
* @return Matrix
*/
- Matrix getRotation();
+ Matrix<?> getRotation();
/**
* Get transform scale.
@@ -59,7 +62,8 @@ public interface Similarity<T extends Similarity<T>> extends
Affine<T> {
/**
* Get transform translation.
* Call notifyChanged after if you modified the values.
- *
+ *ç&é ,
+ * +
* @return Vector
*/
Vector<?> getTranslation();
@@ -75,26 +79,25 @@ public interface Similarity<T extends Similarity<T>>
extends Affine<T> {
*
* @return Matrix, never null
*/
- Matrix viewMatrix();
+ Matrix<?> viewMatrix();
/**
* Get a general inverse matrix view of size : dimension+1
*
* @return Matrix, never null
*/
- Matrix viewMatrixInverse();
+ Matrix<?> viewMatrixInverse();
- /**
- * {@inheritDoc }
- */
- @Override
- void transform(double[] in, int sourceOffset, double[] out, int
destOffset, int nbTuple);
+ Affine<?> viewAffine();
/**
- * {@inheritDoc }
+ * 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
*/
- @Override
- void transform(float[] in, int sourceOffset, float[] out, int destOffset,
int nbTuple);
+ Affine<?> viewAffineInverse();
/**
* Inverse transform a single tuple.
@@ -106,14 +109,11 @@ public interface Similarity<T extends Similarity<T>>
extends Affine<T> {
Tuple<?> inverseTransform(Tuple<?> source, Tuple<?> dest);
/**
- * Inverse view of this transform.
- * The returned affine is no modifiable.
- * The returned affine reflects any change made to this transform
+ * Multiply this similarity by given similarity and store the result in
this similarity.
*
- * @return inverse transform view
+ * @param other multiplying similarity
+ * @return this similarity
*/
- Affine<?> inverse();
-
T multiply(Similarity<?> other);
/**
@@ -128,24 +128,22 @@ public interface Similarity<T extends Similarity<T>>
extends Affine<T> {
* Matrix must be orthogonal of size dimension+1.
*
* @param trs
+ * @throws IllegalArgumentException if matrix is not affine
*/
- @Override
- T setFromMatrix(Matrix trs);
+ T setFromMatrix(Matrix<?> trs) throws IllegalArgumentException;
/**
- * Set transform from given matrix.
+ * Set transform from given affine.
* Affine must be of same size.
*
* @param trs
*/
- @Override
- T set(Affine<?> trs);
+ T setFromAffine(Affine<?> trs);
/**
* Set to identity.
* This method will send a change event if values have changed.
*/
- @Override
T setToIdentity();
/**
@@ -157,10 +155,54 @@ public interface Similarity<T extends Similarity<T>>
extends Affine<T> {
*/
T setToTranslation(double[] trs);
+ /**
+ * Inverse this affine transform.
+ *
+ * @return this affine instance
+ */
+ T invert();
+
+ /**
+ * Create a square matrix of size dimensions+1
+ * The last matrix line will be [0,...,1]
+ *
+ * @return matrix
+ */
+ 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
+ */
+ Matrix<?> toMatrix(Matrix<?> buffer);
+
+ /**
+ * Create and affine transform.
+ *
+ * @return
+ */
+ Affine<?> toAffine();
+
+ /**
+ * Create a copy of this Affine.
+ *
+ * @return copy
+ */
+ 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());
+ }
}
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
new file mode 100644
index 0000000000..bf247b577b
--- /dev/null
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/math/Similarity3D.java
@@ -0,0 +1,176 @@
+/*
+ * 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.math;
+
+import java.util.Objects;
+
+/**
+ * 3D similarity.
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+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);
+
+ public Similarity3D(){
+ super(3);
+ }
+
+ @Override
+ public int getInputDimensions() {
+ return 3;
+ }
+
+ @Override
+ public int getOutputDimensions() {
+ return 3;
+ }
+
+ @Override
+ public int getDimension() {
+ return 3;
+ }
+
+ @Override
+ public Matrix3D getRotation() {
+ return rotation;
+ }
+
+ @Override
+ public Vector3D.Double getScale() {
+ return scale;
+ }
+
+ @Override
+ public Vector3D.Double getTranslation() {
+ return translation;
+ }
+
+ @Override
+ public Similarity3D multiply(Similarity<?> other) {
+ final Vector<?> resTrans = other.getTranslation().copy()
+ .transform(rotation)
+ .multiply(scale)
+ .add(translation);
+
+ rotation.multiply(other.getRotation());
+ scale.multiply(other.getScale());
+ translation.set(resTrans);
+ notifyChanged();
+ return this;
+ }
+
+ @Override
+ public Similarity3D set(Similarity<?> trs) {
+ if (rotation.equals(trs.getRotation()) && scale.equals(trs.getScale())
&& translation.equals(trs.getTranslation())){
+ //nothing changes
+ return this;
+ }
+ rotation.set(trs.getRotation());
+ scale.set(trs.getScale());
+ translation.set(trs.getTranslation());
+ notifyChanged();
+ return this;
+ }
+
+ /**
+ * Combine the different elements to obtain a 4x4 matrix.
+ * [R*S, R*S, R*S, T]
+ * [R*S, R*S, R*S, T]
+ * [R*S, R*S, R*S, T]
+ * [ 0, 0, 0, 1]
+ */
+ @Override
+ public Matrix4D toMatrix() {
+
+ final Matrix4D matrix = new Matrix4D();
+ //set rotation
+ matrix.m00 = rotation.m00; matrix.m10 = rotation.m10; matrix.m20 =
rotation.m20;
+ matrix.m01 = rotation.m01; matrix.m11 = rotation.m11; matrix.m21 =
rotation.m21;
+ matrix.m02 = rotation.m02; matrix.m12 = rotation.m12; matrix.m22 =
rotation.m22;
+ //scale matrix
+ matrix.m00 *= scale.x; matrix.m01 *= scale.y; matrix.m02 *= scale.z;
+ matrix.m10 *= scale.x; matrix.m11 *= scale.y; matrix.m12 *= scale.z;
+ matrix.m20 *= scale.x; matrix.m21 *= scale.y; matrix.m22 *= scale.z;
+ //add translation
+ matrix.m03 = translation.x;
+ matrix.m13 = translation.y;
+ matrix.m23 = translation.z;
+
+ return matrix;
+ }
+
+ @Override
+ public Affine3D toAffine() {
+ final Affine3D affine = new Affine3D();
+ //set rotation
+ affine.m00 = rotation.m00; affine.m10 = rotation.m10; affine.m20 =
rotation.m20;
+ affine.m01 = rotation.m01; affine.m11 = rotation.m11; affine.m21 =
rotation.m21;
+ affine.m02 = rotation.m02; affine.m12 = rotation.m12; affine.m22 =
rotation.m22;
+ //scale matrix
+ affine.m00 *= scale.x; affine.m01 *= scale.y; affine.m02 *= scale.z;
+ affine.m10 *= scale.x; affine.m11 *= scale.y; affine.m12 *= scale.z;
+ affine.m20 *= scale.x; affine.m21 *= scale.y; affine.m22 *= scale.z;
+ //add translation
+ affine.m03 = translation.x;
+ affine.m13 = translation.y;
+ affine.m23 = translation.z;
+
+ 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);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.scale,
+ this.translation,
+ this.rotation);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Similarity3D other = (Similarity3D) obj;
+ return Objects.equals(this.scale, other.scale)
+ && Objects.equals(this.translation, other.translation)
+ && Objects.equals(this.rotation, other.rotation);
+ }
+
+}
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 f63127c667..7fa8ea4da8 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
@@ -16,10 +16,6 @@
*/
package org.apache.sis.geometries.math;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.Arrays;
-
/**
* A similarity is the equivalent of a affine transform but preserving angles
by avoiding
* shearing value not rotations.
@@ -39,36 +35,18 @@ import java.util.Arrays;
*
* @author Johann Sorel
*/
-public class SimilarityND extends AbstractAffine<SimilarityND> implements
Similarity<SimilarityND> {
-
- private static final String PROPERTY_MATRIX = "matrix";
-
- //keep track of the matrix state
- private final Object lock = new Object();
- private PropertyChangeSupport eventManager;
- private final Matrix<?> oldMatrix;
+public class SimilarityND extends AbstractSimilarity<SimilarityND> {
private final int dimension;
- private final Matrix<?> rotation;
- private final Vector<?> scale;
- private final Vector<?> translation;
-
- //store a view of the global matrix of size dimension+1
- //which group rotation,scale and translation
- private final Inverse inverseAff = new Inverse();
- private boolean dirty = true;
- private boolean inverseDirty = true;
- private boolean affineDirty = true;
- private final Matrix<?> matrix;
- private final Matrix<?> inverseMatrix;
- private final Matrix<?> inverseRotation;
- private final Affine<?> affine;
+ public final Matrix<?> rotation;
+ public final Vector<?> scale;
+ public final Vector<?> translation;
public static Similarity<?> create(int dimension) {
return new SimilarityND(dimension);
}
- public static Similarity<?> create(Matrix rotation, Vector<?> scale,
Vector<?> translation) {
+ public static Similarity<?> create(Matrix<?> rotation, Vector<?> scale,
Vector<?> translation) {
return new SimilarityND(rotation, scale, translation);
}
@@ -80,45 +58,28 @@ public class SimilarityND extends
AbstractAffine<SimilarityND> implements Simila
super(dimension);
this.dimension = dimension;
this.rotation = MatrixND.create(dimension, dimension).setToIdentity();
- this.inverseRotation = rotation.copy();
this.scale = Vectors.create(dimension, DataType.DOUBLE);
//set scale to 1 by default
this.scale.setAll(1d);
this.translation = Vectors.create(dimension, DataType.DOUBLE);
- this.dirty = false;
- final int msize = dimension+1;
- this.matrix = MatrixND.create(msize, msize).setToIdentity();
- this.oldMatrix = this.matrix.copy();
- this.inverseMatrix = MatrixND.create(msize, msize);
- this.affine = AffineND.create(dimension);
}
- protected SimilarityND(Matrix rotation, Vector<?> scale, Vector<?>
translation) {
+ protected SimilarityND(Matrix<?> rotation, Vector<?> scale, Vector<?>
translation) {
super(scale.getDimension());
this.dimension = scale.getDimension();
this.rotation = rotation;
- this.inverseRotation = this.rotation.copy();
this.scale = scale;
this.translation = translation;
- final int msize = dimension+1;
- this.matrix = MatrixND.create(msize, msize).setToIdentity();
- this.oldMatrix = this.matrix.copy();
- this.inverseMatrix = MatrixND.create(msize, msize);
- this.affine = AffineND.create(dimension);
+ dirty = true;
}
protected SimilarityND(Quaternion rotation, Vector<?> scale, Vector<?>
translation) {
super(scale.getDimension());
this.dimension = scale.getDimension();
this.rotation = rotation.toMatrix3();
- this.inverseRotation = this.rotation.copy();
this.scale = scale;
this.translation = translation;
- final int msize = dimension+1;
- this.matrix = MatrixND.create(msize, msize).setToIdentity();
- this.oldMatrix = this.matrix.copy();
- this.inverseMatrix = MatrixND.create(msize, msize);
- this.affine = AffineND.create(dimension);
+ dirty = true;
}
/**
@@ -126,7 +87,7 @@ public class SimilarityND extends
AbstractAffine<SimilarityND> implements Simila
* @param trs
*/
@Override
- public SimilarityND set(Similarity trs){
+ public SimilarityND set(Similarity<?> trs){
if (rotation.equals(trs.getRotation()) && scale.equals(trs.getScale())
&& translation.equals(trs.getTranslation())){
//nothing changes
return this;
@@ -138,361 +99,34 @@ public class SimilarityND extends
AbstractAffine<SimilarityND> implements Simila
return this;
}
- /**
- * Set transform from given matrix.
- * Matrix must be orthogonal of size dimension+1.
- * @param trs
- */
- @Override
- public SimilarityND setFromMatrix(Matrix trs){
- Matrices.decomposeMatrix(trs, rotation, scale, translation);
- notifyChanged();
- return this;
- }
-
- /**
- * Set transform from given matrix.
- * Matrix must be orthogonal of size dimension+1.
- * @param trs
- */
- @Override
- public SimilarityND set(Affine trs){
- setFromMatrix(trs.toMatrix());
- return this;
- }
-
- @Override
- public SimilarityND set(int row, int col, double value) throws
IllegalArgumentException {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- /**
- * Set to identity.
- * This method will send a change event if values have changed.
- */
- @Override
- public SimilarityND setToIdentity(){
- 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);
- }
-
- if (change) notifyChanged();
- return this;
- }
-
- /**
- * Set this transform to given translation.
- * This will reset rotation and scale values.
- *
- * This method will send a change event if values have changed.
- */
- @Override
- public SimilarityND setToTranslation(double[] trs){
- 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);
- }
-
- if (change) notifyChanged();
-
- return this;
- }
-
- @Override
- public double get(int row, int col) {
- return viewMatrix().get(row, col);
- }
-
- /**
- * Dimension of the transform.
- * @return int
- */
@Override
public int getDimension() {
return dimension;
}
- /**
- * Get transform rotation.
- * Call notifyChanged after if you modified the values.
- *
- * @return Matrix
- */
- @Override
- public Matrix getRotation() {
- return rotation;
- }
-
- /**
- * Get transform scale.
- * Call notifyChanged after if you modified the values.
- *
- * @return Vector<?>
- */
- @Override
- public Vector<?> getScale() {
- return scale;
- }
-
- /**
- * Get transform translation.
- * Call notifyChanged after if you modified the values.
- *
- * @return Vector<?>
- */
- @Override
- public Vector<?> getTranslation() {
- return translation;
- }
-
- /**
- * Flag to indicate the transform parameters has changed.
- * This is used to recalculate the general matrix when needed.
- */
- @Override
- public void notifyChanged(){
- dirty=true;
- inverseDirty=true;
- affineDirty=true;
-
- if (eventManager!=null && eventManager.hasListeners(PROPERTY_MATRIX)){
- //we have listeners, we need to recalculate the transform now
- eventManager.firePropertyChange(PROPERTY_MATRIX, oldMatrix.copy(),
viewMatrix().copy());
- }
- }
-
- /**
- * Get a general matrix view of size : dimension+1
- * This matrix 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]
- * [ 0, 0, 0, 1]
- *
- * @return Matrix, never null
- */
- @Override
- public Matrix<?> viewMatrix(){
- if (dirty){
- dirty = false;
- //update matrix
- matrix.setToIdentity();
- matrix.set(rotation);
- matrix.scale(scale.extend(1).toArrayDouble());
- for (int i=0;i<dimension;i++){
- matrix.set(i, dimension, translation.get(i));
- }
- oldMatrix.set(matrix);
- if (!matrix.isFinite()){
- throw new RuntimeException("Matrix is not finite
:\nRotation\n"+rotation+"Scale "+scale+"\nTranslate "+translation);
- }
- }
- return matrix;
- }
-
- /**
- * Get a general inverse matrix view of size : dimension+1
- * DO NOT MODIFY THIS MATRIX.
- *
- * @return Matrix, never null
- */
- @Override
- public Matrix<?> viewMatrixInverse(){
- if (dirty){
- viewMatrix();
- }
- if (inverseDirty){
- inverseDirty = false;
- inverseRotation.set(rotation).invert();
- inverseMatrix.set(matrix).invert();
- }
- return inverseMatrix;
- }
-
- private Affine<?> asAffine() {
- if (dirty || affineDirty) {
- affine.setFromMatrix(viewMatrix());
- affineDirty = false;
- }
- return affine;
- }
-
- /**
- * {@inheritDoc }
- */
@Override
public int getInputDimensions() {
return dimension;
}
- /**
- * {@inheritDoc }
- */
@Override
public int getOutputDimensions() {
return dimension;
}
@Override
- public Tuple<?> transform(Tuple<?> source, Tuple<?> out) {
- return asAffine().transform(source, out);
-
- //under code uses less memory but is much slower
-// if (out == null) out = DefaultVector<?>.create(dimension);
-//
-// if (out instanceof Vector<?>) {
-// //scale
-// out.set(source);
-// ((Vector<?>) out).localMultiply(scale);
-// //rotate
-// rotation.transform(out, out);
-// //translate
-// ((Vector<?>) out).localAdd(translation);
-// } else {
-// final Vector<?> array = DefaultVector<?>.create(out);
-// //scale
-// array.set(source);
-// array.localMultiply(scale);
-// //rotate
-// rotation.transform(array, array);
-// //translate
-// array.localAdd(translation);
-// out.set(array);
-// }
-//
-// return out;
- }
-
- /**
- * {@inheritDoc }
- */
- @Override
- public void transform(double[] in, int sourceOffset, double[] out, int
destOffset, int nbTuple) {
- asAffine().transform(in, sourceOffset, out, destOffset, nbTuple);
-
- //we could use this, but it is slower.
- //asMatrix().transform(in, sourceOffset, out, destOffset, nbTuple);
-
- //this is also slower
-// //scale
-// Vector<?>s.multiplyRegular(in, out, sourceOffset, destOffset,
scale.toDouble(), nbTuple);
-// //rotate
-// rotation.transform(out, destOffset, out, destOffset, nbTuple);
-// //translate
-// Vector<?>s.addRegular(out, out, destOffset, destOffset,
translation.toDouble(), nbTuple);
-//
-// return out;
- }
-
- /**
- * {@inheritDoc }
- */
- @Override
- public void transform(float[] in, int sourceOffset, float[] out, int
destOffset, int nbTuple) {
- asAffine().transform(in, sourceOffset, out, destOffset, nbTuple);
-
- //we could use this, but it is slower.
- //asMatrix().transform(source, sourceOffset, dest, destOffset,
nbTuple);
-
- //this is also slower
-// //scale
-// Vector<?>s.multiplyRegular(in, out, sourceOffset, destOffset,
scale.toFloat(), nbTuple);
-// //rotate
-// rotation.transform(out, destOffset, out, destOffset, nbTuple);
-// //translate
-// Vector<?>s.addRegular(out, out, destOffset, destOffset,
translation.toFloat(), nbTuple);
-//
-// return out;
- }
-
- @Override
- protected void transform1(double[] source, int sourceOffset, double[]
dest, int destOffset) {
- asAffine().transform(source, sourceOffset, dest, destOffset, 1);
- }
-
- @Override
- protected void transform1(float[] source, int sourceOffset, float[] dest,
int destOffset) {
- asAffine().transform(source, sourceOffset, dest, destOffset, 1);
- }
-
- /**
- * Inverse transform a single tuple.
- *
- * @param source tuple, can not be null.
- * @param dest tuple, can be null.
- * @return destination tuple.
- */
- public Tuple<?> inverseTransform(Tuple<?> source, Tuple<?> dest){
- return inverseAff.transform(source, dest);
- }
-
- protected PropertyChangeSupport getEventManager() {
- return getEventManager(true);
- }
-
- protected PropertyChangeSupport getEventManager(boolean create) {
- synchronized (lock){
- if (eventManager==null && create) eventManager = new
PropertyChangeSupport(this);
- }
- return eventManager;
- }
-
- public void addEventListener(PropertyChangeListener listener) {
- getEventManager().addPropertyChangeListener(listener);
- }
-
- public void removeEventListener(PropertyChangeListener listener) {
- getEventManager().removePropertyChangeListener(listener);
- }
-
- /**
- * Inverse view of this transform.
- * The returned affine is no modifiable.
- * The returned affine reflects any change made to this NodeTransform
- *
- * @return inverse transform view
- */
- @Override
- public Affine inverse() {
- return inverseAff;
+ public Matrix<?> getRotation() {
+ return rotation;
}
@Override
- public SimilarityND invert() {
- final Affine<?> affine = AffineND.create(this);
- affine.invert();
- set(affine);
- return this;
+ public Vector<?> getScale() {
+ return scale;
}
-
@Override
- public SimilarityND multiply(Affine<?> other) {
- if (other instanceof Similarity<?> s) {
- return multiply(s);
- } else {
- return multiply(new SimilarityND(dimension).set(other));
- }
+ public Vector<?> getTranslation() {
+ return translation;
}
@Override
@@ -526,138 +160,43 @@ public class SimilarityND extends
AbstractAffine<SimilarityND> implements Simila
}
@Override
- public Matrix toMatrix() {
- return viewMatrix().copy();
+ 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 buffer) {
- if (buffer==null) return toMatrix();
- buffer.set(viewMatrix());
- return buffer;
+ 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 SimilarityND copy() {
- final SimilarityND aff = new SimilarityND(dimension);
- aff.set(this);
- return aff;
+ public Affine<?> toAffine() {
+ return AffineND.create(dimension).setFromMatrix(toMatrix());
}
- private class Inverse extends AbstractAffine<SimilarityND> {
-
- public Inverse() {
- super(dimension);
- }
-
- @Override
- public int getInputDimensions() {
- return dimension;
- }
-
- @Override
- public int getOutputDimensions() {
- return dimension;
- }
-
- @Override
- public Tuple<?> transform(Tuple<?> source, Tuple<?> dest) {
- if (dest == null) dest = Vectors.create(dimension,
DataType.DOUBLE);
- viewMatrixInverse();
- Vector<?> vd = Vectors.castOrWrap(dest);
- //inverse translate
- vd.set(source).subtract(translation);
- //inverse rotate
- inverseRotation.transform(vd, vd);
- //invert scale
- vd.divide(scale);
- return vd;
- }
-
- @Override
- public void transform(double[] source, int sourceOffset, double[]
dest, int destOffset, int nbTuple) {
- viewMatrixInverse();
- //inverse translate
- Vectors.subtractRegular(source, dest, sourceOffset, destOffset,
translation.toArrayDouble(), nbTuple);
- //inverse rotate
- inverseRotation.transform(dest, destOffset, dest, destOffset,
nbTuple);
- //invert scale
- Vectors.divideRegular(dest, dest, destOffset, destOffset,
scale.toArrayDouble(), nbTuple);
- }
-
- @Override
- public void transform(float[] source, int sourceOffset, float[] dest,
int destOffset, int nbTuple) {
- viewMatrixInverse();
- //inverse translate
- Vectors.subtractRegular(source, dest, sourceOffset, destOffset,
translation.toArrayFloat(), nbTuple);
- //inverse rotate
- inverseRotation.transform(dest, destOffset, dest, destOffset,
nbTuple);
- //invert scale
- Vectors.divideRegular(dest, dest, destOffset, destOffset,
scale.toArrayFloat(), nbTuple);
- }
-
- @Override
- protected void transform1(double[] source, int sourceOffset, double[]
dest, int destOffset) {
- viewMatrixInverse();
- //inverse translate
- Vectors.subtractRegular(source, dest, sourceOffset, destOffset,
translation.toArrayDouble(), 1);
- //inverse rotate
- inverseRotation.transform(dest, destOffset, dest, destOffset, 1);
- //invert scale
- Vectors.divideRegular(dest, dest, destOffset, destOffset,
scale.toArrayDouble(), 1);
- }
-
- @Override
- protected void transform1(float[] source, int sourceOffset, float[]
dest, int destOffset) {
- viewMatrixInverse();
- //inverse translate
- Vectors.subtractRegular(source, dest, sourceOffset, destOffset,
translation.toArrayFloat(), 1);
- //inverse rotate
- inverseRotation.transform(dest, destOffset, dest, destOffset, 1);
- //invert scale
- Vectors.divideRegular(dest, dest, destOffset, destOffset,
scale.toArrayFloat(), 1);
- }
-
- @Override
- public double get(int row, int col) {
- return viewMatrixInverse().get(row, col);
- }
-
- @Override
- public Matrix toMatrix() {
- return viewMatrixInverse().copy();
- }
-
- @Override
- public Matrix toMatrix(Matrix buffer) {
- if (buffer==null) {
- return viewMatrixInverse().copy();
- } else {
- buffer.set(viewMatrixInverse());
- return buffer;
- }
- }
-
- @Override
- public SimilarityND set(int row, int col, double value) throws
IllegalArgumentException {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- @Override
- public SimilarityND setFromMatrix(Matrix m) throws
IllegalArgumentException {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- @Override
- public SimilarityND createInverse() {
- throw new UnsupportedOperationException("Not supported.");
- }
-
- @Override
- public SimilarityND copy() {
- final SimilarityND aff = new SimilarityND(dimension);
- aff.set(Inverse.this);
- return aff;
- }
+ @Override
+ public SimilarityND copy() {
+ return new SimilarityND(dimension).set(this);
}
+
}
diff --git
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/scene/SceneNode.java
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/scene/SceneNode.java
index a106dd98f2..16f8cfb104 100644
---
a/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/scene/SceneNode.java
+++
b/incubator/src/org.apache.sis.geometry/main/org/apache/sis/geometries/scene/SceneNode.java
@@ -25,7 +25,7 @@ import java.util.Objects;
import java.util.Optional;
import org.apache.sis.geometries.Geometries;
import org.apache.sis.geometries.math.Similarity;
-import org.apache.sis.geometries.math.SimilarityND;
+import org.apache.sis.geometries.math.Similarity3D;
import org.apache.sis.geometry.Envelopes;
import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.measure.NumberRange;
@@ -48,7 +48,7 @@ import org.opengis.referencing.operation.TransformException;
*/
public class SceneNode {
- private final SimilarityND parentToNode = (SimilarityND)
SimilarityND.create(3);
+ private final Similarity3D parentToNode = new Similarity3D();
private SceneNode parent = null;
private final List<SceneNode> children = new
NotifiedCheckedList<SceneNode>(){
@Override
@@ -181,7 +181,7 @@ public class SceneNode {
*
* @return Transform, never null.
*/
- public SimilarityND getTransform() {
+ public Similarity3D getTransform() {
return parentToNode;
}
diff --git
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/QuaternionTest.java
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/QuaternionTest.java
index 20bdd548bb..1634d74662 100644
---
a/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/QuaternionTest.java
+++
b/incubator/src/org.apache.sis.geometry/test/org/apache/sis/geometries/math/QuaternionTest.java
@@ -79,7 +79,7 @@ public class QuaternionTest {
Quaternion q = new Quaternion();
q.setFromMatrix(m);
-
assertArrayEquals(m.toArrayDoubleColOrder(),q.toMatrix4().toArrayDoubleColOrder(),
DELTA);
+
assertArrayEquals(m.toArrayDouble(Matrix.COL_ORDER),q.toMatrix4().toArrayDouble(Matrix.COL_ORDER),
DELTA);
}
@Test