コード例 #1
0
        /// <summary>
        /// Creates a raster mapper from raster coordinates.
        /// </summary>
        /// <param name="mode">The raster mapping mode.</param>
        /// <param name="coordinates">The list of coordinates.</param>
        /// <returns>The raster mapper created by linear interpolation of the coordinates.</returns>
        /// <exception cref="System.ArgumentNullException">The array of coordinates is null.</exception>
        /// <exception cref="System.ArgumentException">
        /// The number of coordinates with distinct column index is less than 2.
        /// or
        /// The number of coordinates with distinct row index is less than 2.
        /// </exception>
        public static RasterMapper FromCoordinates(RasterMapMode mode, IList <RasterCoordinate> coordinates)
        {
            if (coordinates == null)
            {
                throw new ArgumentNullException("The list of coordinates is null.", "coordinates");
            }
            if (coordinates.Select(coordinate => coordinate.ColumnIndex).Distinct().Count() < 2)
            {
                throw new ArgumentException("The number of coordinates with distinct column index is less than 2.", "coordinates");
            }
            if (coordinates.Select(coordinate => coordinate.RowIndex).Distinct().Count() < 2)
            {
                throw new ArgumentException("The number of coordinates with distinct row index is less than 2.", "coordinates");
            }

            // compute linear equation system in both dimensions

            Int32[] columnIndices = coordinates.Select(coordinate => coordinate.ColumnIndex).Distinct().ToArray();
            Int32[] rowIndices    = coordinates.Select(coordinate => coordinate.ColumnIndex).Distinct().ToArray();

            Matrix matrix  = new Matrix(coordinates.Count, 3);
            Vector vectorX = new Vector(coordinates.Count);
            Vector vectorY = new Vector(coordinates.Count);

            for (Int32 coordinateIndex = 0; coordinateIndex < coordinates.Count; coordinateIndex++)
            {
                matrix[coordinateIndex, 0] = coordinates[coordinateIndex].ColumnIndex;
                matrix[coordinateIndex, 1] = coordinates[coordinateIndex].RowIndex;
                matrix[coordinateIndex, 2] = 1;

                vectorX[coordinateIndex] = coordinates[coordinateIndex].Coordinate.X;
                vectorY[coordinateIndex] = coordinates[coordinateIndex].Coordinate.Y;
            }

            // solve equation using least squares method
            Vector resultX = LUDecomposition.SolveEquation(matrix.Transpone() * matrix, matrix.Transpone() * vectorX);
            Vector resultY = LUDecomposition.SolveEquation(matrix.Transpone() * matrix, matrix.Transpone() * vectorY);

            // merge the results into a matrix
            Matrix transformation = new Matrix(4, 4);

            transformation[0, 0] = resultX[0];
            transformation[0, 1] = resultX[1];
            transformation[0, 3] = resultX[2];
            transformation[1, 0] = resultY[0];
            transformation[1, 1] = resultY[1];
            transformation[1, 3] = resultY[2];
            transformation[3, 3] = 1;

            return(new RasterMapper(mode, transformation));
        }
コード例 #2
0
        /// <summary>
        /// Creates a general (not invertible) polynomial transformation.
        /// </summary>
        /// <param name="degree">The degree of the polynomial.</param>
        /// <param name="sourceEvaluationCoordinate">The source evaluation coordinate.</param>
        /// <param name="sourceCoordinates">The source coordinates.</param>
        /// <param name="targetEvaluationCoordinate">The target evaluation coordinate.</param>
        /// <param name="targetCoordinates">The target coordinates.</param>
        /// <returns>The general polynomial transformation created from the specified coordinates.</returns>
        /// <exception cref="System.ArgumentException">
        /// The degree is not valid.
        /// or
        /// The amount of source coordinates is insufficient for the specified degree.
        /// or
        /// The amount of target coordinates is insufficient for the specified degree.
        /// or
        /// The amount of source and target coordinates does not match.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// The list of source coordinates is null.
        /// or
        /// The list of target coordinates is null.
        /// </exception>
        public static GeneralPolynomialTransformation CreateGeneralTransformation(Int32 degree,
                                                                                  Coordinate sourceEvaluationCoordinate, IList <Coordinate> sourceCoordinates,
                                                                                  Coordinate targetEvaluationCoordinate, IList <Coordinate> targetCoordinates)
        {
            if (degree < 1)
            {
                throw new ArgumentException("The degree is not valid.", "degree");
            }

            Int32 size = Convert.ToInt32(Calculator.Sum(1, degree + 1));

            if (sourceCoordinates == null)
            {
                throw new ArgumentNullException("The list of source coordinates is null.", "sourceCoordinates");
            }
            if (sourceCoordinates.Count < size)
            {
                throw new ArgumentException("The amount of source coordinates is insufficient for the specified degree.", "sourceCoordinates");
            }
            if (targetCoordinates == null)
            {
                throw new ArgumentNullException("The list of target coordinates is null.", "targetCoordinates");
            }
            if (targetCoordinates.Count < size)
            {
                throw new ArgumentException("The amount of target coordinates is insufficient for the specified degree.", "targetCoordinates");
            }
            if (sourceCoordinates.Count != targetCoordinates.Count)
            {
                throw new ArgumentException("The amount of source and target coordinates does not match.", "targetCoordinates");
            }

            // compute scaling factors
            Double sourceScalingFactor = 2 / (sourceCoordinates.Select(coordinate => coordinate.X).Average() + sourceCoordinates.Select(coordinate => coordinate.Y).Average());
            Double targetScalingFactor = 2 / (targetCoordinates.Select(coordinate => coordinate.X).Average() + targetCoordinates.Select(coordinate => coordinate.Y).Average());

            Matrix sourceMatrixA = new Matrix(size, size);
            Matrix sourceMatrixB = new Matrix(size, size);
            Vector targetVectorX = new Vector(size);
            Vector targetVectorY = new Vector(size);

            // compute coordinates
            Int32 l = 0;

            for (Int32 i = 0; i < sourceCoordinates.Count; i++)
            {
                sourceMatrixA[i, 0] = 1;
                sourceMatrixB[i, 0] = 1;
                l = 1;

                for (Int32 j = 1; j <= degree; j++)
                {
                    Int32 m = Convert.ToInt32(Calculator.Sum(1, j + 1)) - Convert.ToInt32(Calculator.Sum(1, j));
                    for (Int32 k = 0; k < m; k++)
                    {
                        Double u = (sourceCoordinates[i].X - sourceEvaluationCoordinate.X) * sourceScalingFactor;
                        Double v = (sourceCoordinates[i].Y - sourceEvaluationCoordinate.Y) * sourceScalingFactor;

                        sourceMatrixA[i, l] = Calculator.Pow(u, j - k) * Calculator.Pow(v, k);
                        sourceMatrixB[i, l] = Calculator.Pow(u, j - k) * Calculator.Pow(v, k);

                        l++;
                    }
                }
                targetVectorX[i] = (targetCoordinates[i].X - targetEvaluationCoordinate.X) * targetScalingFactor;
                targetVectorY[i] = (targetCoordinates[i].Y - targetEvaluationCoordinate.Y) * targetScalingFactor;
            }

            // compute coefficients
            Vector resultA = LUDecomposition.SolveEquation(sourceMatrixA, targetVectorX);
            Vector resultB = LUDecomposition.SolveEquation(sourceMatrixB, targetVectorY);

            // compute parameters
            Dictionary <CoordinateOperationParameter, Object> parameters = GenerateParameters(degree, sourceEvaluationCoordinate, targetEvaluationCoordinate, sourceScalingFactor, targetScalingFactor, resultA, resultB);

            return(new GeneralPolynomialTransformation(degree, parameters));
        }