org.geotoolkit.referencing.operation.matrix.GeneralMatrix Maven / Gradle / Ivy
/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2001-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.referencing.operation.matrix;
import java.awt.geom.AffineTransform;
import java.text.ParseException;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Arrays;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import javax.vecmath.GMatrix;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.operation.Matrix;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.MismatchedDimensionException;
import org.geotoolkit.util.XArrays;
import org.geotoolkit.util.Strings;
import org.geotoolkit.util.ComparisonMode;
import org.geotoolkit.math.XMath;
import org.geotoolkit.math.Statistics;
import org.geotoolkit.resources.Errors;
import org.geotoolkit.io.ContentFormatException;
import org.geotoolkit.io.LineFormat;
import org.geotoolkit.internal.referencing.AxisDirections;
/**
* A two dimensional array of numbers. Row and column numbering begins with zero.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @author Simone Giannecchini (Geosolutions)
* @version 3.20
*
* @see javax.vecmath.GMatrix
* @see java.awt.geom.AffineTransform
* @see javax.media.jai.PerspectiveTransform
* @see javax.media.j3d.Transform3D
* @see Jama matrix
* @see JSR-83 Multiarray package
*
* @since 1.2
* @module
*/
public class GeneralMatrix extends GMatrix implements XMatrix {
/**
* Serial number for inter-operability with different versions.
*/
private static final long serialVersionUID = 8447482612423035360L;
/**
* Constructs a square identity matrix of size {@code size} × {@code size}.
*
* @param size The number of rows and columns.
*/
public GeneralMatrix(final int size) {
super(size, size);
}
/**
* Creates a matrix of size {@code numRow} × {@code numCol}.
* Elements on the diagonal (j == i) are set to 1.
*
* @param numRow Number of rows.
* @param numCol Number of columns.
*/
public GeneralMatrix(final int numRow, final int numCol) {
super(numRow, numCol);
}
/**
* Constructs a {@code numRow} × {@code numCol} matrix
* initialized to the values in the {@code matrix} array. The array values
* are copied in one row at a time in row major fashion. The array should be
* exactly {@code numRow*numCol} in length. Note that because row and column
* numbering begins with zero, {@code numRow} and {@code numCol} will be
* one larger than the maximum possible matrix index values.
*
* @param numRow Number of rows.
* @param numCol Number of columns.
* @param matrix Initial values.
*/
public GeneralMatrix(final int numRow, final int numCol, final double[] matrix) {
super(numRow, numCol, matrix);
if (numRow*numCol != matrix.length) {
throw new IllegalArgumentException(String.valueOf(matrix.length));
}
}
/**
* Constructs a new matrix from a two-dimensional array of doubles.
*
* @param matrix Array of rows. Each row must have the same length.
* @throws IllegalArgumentException if the specified matrix is not regular
* (i.e. if all rows doesn't have the same length).
*/
public GeneralMatrix(final double[]... matrix) throws IllegalArgumentException {
super(matrix.length, (matrix.length!=0) ? matrix[0].length : 0);
final int numRow = getNumRow();
final int numCol = getNumCol();
for (int j=0; j
* If the source dimension is equal to the destination dimension,
* then the transform is affine. However, the following special cases
* are also handled:
*
*
* - If the target dimension is smaller than the source dimension,
* then extra dimensions are dropped.
* - If the target dimension is greater than the source dimension,
* then the coordinates in the new dimensions are set to 0.
*
*
* @param srcRegion The source region.
* @param dstRegion The destination region.
*/
public GeneralMatrix(final Envelope srcRegion,
final Envelope dstRegion)
{
super(dstRegion.getDimension()+1, srcRegion.getDimension()+1);
// Next lines should be first if only Sun could fix RFE #4093999 (sigh...)
final int srcDim = srcRegion.getDimension();
final int dstDim = dstRegion.getDimension();
for (int i=Math.min(srcDim, dstDim); --i>=0;) {
double scale = dstRegion.getSpan(i) / srcRegion.getSpan(i);
double translate = dstRegion.getMinimum(i) - srcRegion.getMinimum(i)*scale;
setElement(i, i, scale);
setElement(i, srcDim, translate);
}
setElement(dstDim, srcDim, 1);
assert (srcDim != dstDim) || isAffine() : this;
}
/**
* Constructs a transform changing axis order and/or direction.
* For example, the transform may converts (NORTH,WEST) coordinates
* into (EAST,NORTH). Axis direction can be inverted only. For example,
* it is illegal to transform (NORTH,WEST) coordinates into (NORTH,DOWN).
*
* If the source dimension is equal to the destination dimension,
* then the transform is affine. However, the following special cases
* are also handled:
*
*
* - If the target dimension is smaller than the source dimension,
* extra axis are dropped. An exception is thrown if the target
* contains some axis not found in the source.
*
*
* @param srcAxis The set of axis direction for source coordinate system.
* @param dstAxis The set of axis direction for destination coordinate system.
* @throws IllegalArgumentException If {@code dstAxis} contains some axis
* not found in {@code srcAxis}, or if some colinear axis were found.
*/
public GeneralMatrix(final AxisDirection[] srcAxis,
final AxisDirection[] dstAxis)
{
this(null, srcAxis, null, dstAxis, false);
}
/**
* Constructs a transform mapping a source region to a destination region.
* Axis order and/or direction can be changed during the process.
* For example, the transform may convert (NORTH,WEST) coordinates
* into (EAST,NORTH). Axis direction can be inverted only. For example,
* it is illegal to transform (NORTH,WEST) coordinates into (NORTH,DOWN).
*
* If the source dimension is equal to the destination dimension,
* then the transform is affine. However, the following special cases
* are also handled:
*
*
* - If the target dimension is smaller than the source dimension,
* extra axis are dropped. An exception is thrown if the target
* contains some axis not found in the source.
*
*
* @param srcRegion The source region.
* @param srcAxis Axis direction for each dimension of the source region.
* @param dstRegion The destination region.
* @param dstAxis Axis direction for each dimension of the destination region.
* @throws MismatchedDimensionException if the envelope dimension doesn't
* matches the axis direction array length.
* @throws IllegalArgumentException If {@code dstAxis} contains some axis
* not found in {@code srcAxis}, or if some colinear axis were found.
*/
public GeneralMatrix(final Envelope srcRegion, final AxisDirection[] srcAxis,
final Envelope dstRegion, final AxisDirection[] dstAxis)
{
this(srcRegion, srcAxis, dstRegion, dstAxis, true);
}
/**
* Implementation of constructors expecting envelope and/or axis directions.
*
* @param validRegions {@code true} if source and destination regions must
* be taken in account. If {@code false}, then source and destination
* regions will be ignored and may be null.
*/
private GeneralMatrix(final Envelope srcRegion, final AxisDirection[] srcAxis,
final Envelope dstRegion, final AxisDirection[] dstAxis,
final boolean validRegions)
{
super(dstAxis.length+1, srcAxis.length+1);
if (validRegions) {
ensureDimensionMatch("srcRegion", srcRegion, srcAxis.length);
ensureDimensionMatch("dstRegion", dstRegion, dstAxis.length);
}
/*
* Maps source axis to destination axis. If no axis is moved (for example if the user
* want to transform (NORTH,EAST) to (SOUTH,EAST)), then source and destination index
* will be equal. If some axis are moved (for example if the user want to transform
* (NORTH,EAST) to (EAST,NORTH)), then ordinates at index {@code srcIndex} will have
* to be moved at index {@code dstIndex}.
*/
setZero();
for (int dstIndex=0; dstIndex=0;) {
getColumn(i, column);
final double m = XMath.magnitude(column);
for (int j=0; j data.length) {
data = Arrays.copyOf(data, upper*2);
}
System.arraycopy(row, 0, data, numData, row.length);
numData = upper;
numRow++;
assert numData % numRow == 0 : numData;
}
data = (data != null) ? XArrays.resize(data, numData) : XArrays.EMPTY_DOUBLE;
return new GeneralMatrix(numRow, numData/numRow, data);
}
/**
* Returns a string representation of this matrix. The returned string is implementation
* dependent. It is usually provided for debugging purposes only.
*/
@Override
public String toString() {
return toString(this);
}
/**
* Returns a string representation of the specified matrix. The returned string is
* implementation dependent. It is usually provided for debugging purposes only.
*/
static String toString(final Matrix matrix) {
/*
* Chooses a NumberFormat (more specifically the number of fraction digits)
* based on the element values (their range, mean and standard deviation).
*/
final int numRow = matrix.getNumRow();
final int numCol = matrix.getNumCol();
final Statistics statistics = new Statistics();
for (int j=0; j
© 2015 - 2025 Weber Informatics LLC | Privacy Policy