/// <summary> /// Creates a raster mapper from the transformation. /// </summary> /// <param name="mode">The raster mapping mode.</param> /// <param name="translation">The translation coordinate.</param> /// <param name="scale">The scale vector.</param> /// <returns>The raster mapper based on the specified transformation.</returns> /// <exception cref="System.ArgumentException"> /// The translation is invalid. /// or /// The scale is invalid. /// or /// The scale of the X dimension is equal to 0. /// or /// The scale of the Y dimension is equal to 0. /// </exception> public static RasterMapper FromTransformation(RasterMapMode mode, Coordinate translation, CoordinateVector scale) { if (!translation.IsValid) { throw new ArgumentException("The translation is invalid.", "translation"); } if (!scale.IsValid) { throw new ArgumentException("The scale is invalid.", "scale"); } if (scale.X == 0) { throw new ArgumentException("The scale of the X dimension is equal to 0.", "scale"); } if (scale.Y == 0) { throw new ArgumentException("The scale of the Y dimension is equal to 0.", "scale"); } Matrix transformation = new Matrix(4, 4); transformation[0, 0] = scale.X; transformation[1, 1] = scale.Y; transformation[2, 2] = scale.Z; transformation[0, 3] = translation.X; transformation[1, 3] = translation.Y; transformation[2, 3] = translation.Z; transformation[3, 3] = 1; return(new RasterMapper(mode, transformation)); }
/// <summary> /// Creates a raster mapper from raster coordinates. /// </summary> /// <param name="mode">The raster mapping mode.</param> /// <param name="coordinates">The array 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, params RasterCoordinate[] coordinates) { if (coordinates == null) { throw new ArgumentNullException("The array of coordinates is null.", "coordinates"); } return(FromCoordinates(mode, coordinates as IList <RasterCoordinate>)); }
/// <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)); }
/// <summary> /// Maps the coordinate at a specified row and column index. /// </summary> /// <param name="rowIndex">The zero-based row index of the coordinate.</param> /// <param name="columnIndex">The zero-based column index of the coordinate.</param> /// <param name="mode">The mapping mode.</param> /// <returns>The coordinate located at the specified index with respect to the specified mode.</returns> /// <exception cref="System.InvalidOperationException">The mapping of the raster is not defined.</exception> public Coordinate MapCoordinate(Double rowIndex, Double columnIndex, RasterMapMode mode) { if (mode == Mode) { return(MapCoordinate(rowIndex, columnIndex)); } else { switch (mode) { case RasterMapMode.ValueIsArea: return(MapCoordinate(rowIndex - 0.5, columnIndex - 0.5)); default: // ValueIsCoordinate return(MapCoordinate(rowIndex + 0.5, columnIndex + 0.5)); } } }
/// <summary> /// Initializes a new instance of the <see cref="RasterMapper" /> class. /// </summary> /// <param name="mode">The raster mapping mode.</param> /// <param name="transformation">The transformation from raster space to geometry space.</param> /// <exception cref="System.ArgumentNullException">The transformation is null.</exception> /// <exception cref="System.ArgumentException"> /// The number of columns in the transformation is not equal to 4. /// or /// The number of rows in the transformation is not equal to 4. /// or /// The transformation contains invalid values. /// </exception> /// <exception cref="System.NotSupportedException">The specified transformation is not supported.</exception> public RasterMapper(RasterMapMode mode, Matrix transformation) { if (transformation == null) { throw new ArgumentNullException("transformation", "The transformation is null."); } if (transformation.NumberOfColumns != 4) { throw new ArgumentException("The number of columns in the transformation is not equal to 4.", "transformation"); } if (transformation.NumberOfRows != 4) { throw new ArgumentException("The number of rows in the transformation is not equal to 4.", "transformation"); } // check for invalid values if (transformation.Any(value => Double.IsNaN(value) || Double.IsInfinity(value))) { throw new ArgumentException("The transformation contains invalid values.", "transformation"); } if (transformation[3, 0] != 0 || transformation[3, 1] != 0 || transformation[3, 2] != 0 || transformation[3, 3] != 1) { throw new ArgumentException("The transformation contains invalid values.", "transformation"); } // check for unsupported transformation if (transformation[0, 0] == 0 || transformation[1, 1] == 0 || transformation[2, 0] != 0 || transformation[2, 1] != 0 || transformation[0, 2] != 0 || transformation[1, 2] != 0) { throw new NotSupportedException("The specified transformation is not supported."); } _isLinearTransformation = (transformation[0, 1] == 0 && transformation[1, 0] == 0); // rotation is not specified Mode = mode; GeometryTransformation = transformation; if (!_isLinearTransformation) { _rasterTransformation = transformation.Invert(); } }
/// <summary> /// Creates a raster mapper from the transformation. /// </summary> /// <param name="mode">The raster mapping mode.</param> /// <param name="translationX">The translation in X dimension.</param> /// <param name="translationY">The translation in Y dimension.</param> /// <param name="translationZ">The translation in Z dimension.</param> /// <param name="scaleX">The scale in X dimension.</param> /// <param name="scaleY">The scale in Y dimension.</param> /// <param name="scaleZ">The scale in Z dimension.</param> /// <returns>The raster mapper based on the specified transformation.</returns> /// <exception cref="System.ArgumentException"> /// The translation of the X dimension is not a number. /// or /// The translation of the Y dimension is not a number. /// or /// The translation of the Z dimension is not a number. /// or /// The scale of the X dimension is not a number or is equal to 0. /// or /// The scale of the Y dimension is not a number or is equal to 0. /// or /// The scale of the Z dimension is not a number. /// </exception> public static RasterMapper FromTransformation(RasterMapMode mode, Double translationX, Double translationY, Double translationZ, Double scaleX, Double scaleY, Double scaleZ) { if (Double.IsNaN(translationX)) { throw new ArgumentException("The translation of the X dimension is not a number.", "translationX"); } if (Double.IsNaN(translationY)) { throw new ArgumentException("The translation of the Y dimension is not a number.", "translationY"); } if (Double.IsNaN(translationZ)) { throw new ArgumentException("The translation of the Z dimension is not a number.", "translationZ"); } if (Double.IsNaN(scaleX) || scaleX == 0) { throw new ArgumentException("The scale of the X dimension is not a number or is equal to 0.", "scaleX"); } if (Double.IsNaN(scaleY) || scaleY == 0) { throw new ArgumentException("The scale of the Y dimension is not a number or is equal to 0.", "scaleY"); } if (Double.IsNaN(scaleZ)) { throw new ArgumentException("The scale of the Z dimension is not a number.", "scaleZ"); } Matrix transformation = new Matrix(4, 4); transformation[0, 0] = scaleX; transformation[1, 1] = scaleY; transformation[2, 2] = scaleZ; transformation[0, 3] = translationX; transformation[1, 3] = translationY; transformation[2, 3] = translationZ; transformation[3, 3] = 1; return(new RasterMapper(mode, transformation)); }
/// <summary> /// Maps the raster row and column index at the specified coordinate. /// </summary> /// <param name="coordinate">The coordinate.</param> /// <param name="mode">The mapping mode.</param> /// <param name="rowIndex">The zero-based column index of the value.</param> /// <param name="columnIndex">The zero-based row index of the value.</param> public void MapRaster(Coordinate coordinate, RasterMapMode mode, out Double rowIndex, out Double columnIndex) { if (mode == Mode) { MapRaster(coordinate, out rowIndex, out columnIndex); } else { switch (mode) { case RasterMapMode.ValueIsArea: MapRaster(coordinate, out rowIndex, out columnIndex); rowIndex += 0.5; columnIndex += 0.5; break; default: // ValueIsCoordinate MapRaster(coordinate, out rowIndex, out columnIndex); rowIndex -= 0.5; columnIndex -= 0.5; break; } } }
/// <summary> /// Reads the mapping from model space to raster space. /// </summary> /// <returns>The mapping from model space to raster space.</returns> protected RasterMapper ComputeRasterToModelSpaceMapping() { if (!_currentGeoKeys.ContainsKey(GeoKey.RasterType)) { return(null); } RasterMapMode mode = Convert.ToInt16(_currentGeoKeys[GeoKey.RasterType]) == 1 ? RasterMapMode.ValueIsArea : RasterMapMode.ValueIsCoordinate; Double[] modelTiePointsArray = null; Double[] modelPixelScaleArray = null; Double[] modelTransformationArray = null; // gather information from tags if (_imageFileDirectories[_currentImageIndex].ContainsKey(TiffTag.ModelTiepointTag)) { modelTiePointsArray = _imageFileDirectories[_currentImageIndex][TiffTag.ModelTiepointTag].Select(value => Convert.ToDouble(value)).ToArray(); } if (_imageFileDirectories[_currentImageIndex].ContainsKey(TiffTag.ModelPixelScaleTag)) { modelPixelScaleArray = _imageFileDirectories[_currentImageIndex][TiffTag.ModelPixelScaleTag].Select(value => Convert.ToDouble(value)).ToArray(); } if (_imageFileDirectories[_currentImageIndex].ContainsKey(TiffTag.ModelTransformationTag)) { modelTransformationArray = _imageFileDirectories[_currentImageIndex][TiffTag.ModelTransformationTag].Select(value => Convert.ToDouble(value)).ToArray(); } // for GeoTIFF 0.2, IntergraphMatrixTag (33920) may contain the transformation values if (modelTransformationArray == null && _imageFileDirectories[_currentImageIndex].ContainsKey(TiffTag.IntergraphMatrixTag)) { modelTransformationArray = _imageFileDirectories[_currentImageIndex][TiffTag.IntergraphMatrixTag].Select(value => Convert.ToDouble(value)).ToArray(); } // compute with model tie points if (modelTiePointsArray != null && (modelTiePointsArray.Length > 6 || (modelTiePointsArray.Length == 6 && modelPixelScaleArray.Length == 3))) { if (modelTiePointsArray.Length > 6) // transformation is specified by tie points { RasterCoordinate[] coordinates = new RasterCoordinate[modelTiePointsArray.Length / 6]; for (Int32 i = 0; i < modelTiePointsArray.Length; i += 6) { coordinates[i / 6] = new RasterCoordinate(Convert.ToInt32(modelTiePointsArray[i]), Convert.ToInt32(modelTiePointsArray[i + 1]), new Coordinate(modelTiePointsArray[i + 3], modelTiePointsArray[i + 4], modelTiePointsArray[i + 5])); } return(RasterMapper.FromCoordinates(mode, coordinates)); } else // transformation is specified by single tie point and scale { Coordinate rasterSpaceCoordinate = new Coordinate(modelTiePointsArray[0], modelTiePointsArray[1], modelTiePointsArray[2]); Coordinate modelSpaceCoordinate = new Coordinate(modelTiePointsArray[3], modelTiePointsArray[4], modelTiePointsArray[5]); Double scaleX = modelPixelScaleArray[0]; Double scaleY = -modelPixelScaleArray[1]; Double scaleZ = modelPixelScaleArray[2]; return(RasterMapper.FromTransformation(mode, modelSpaceCoordinate.X - rasterSpaceCoordinate.X * scaleX, modelSpaceCoordinate.Y + rasterSpaceCoordinate.Y * scaleY, modelSpaceCoordinate.Z - rasterSpaceCoordinate.Z * scaleZ, scaleX, scaleY, scaleZ)); } } // compute with transformation values if (modelTransformationArray != null) { Matrix transformation = new Matrix(4, 4); for (Int32 i = 0; i < 4; i++) { for (Int32 j = 0; j < 4; j++) { transformation[i, j] = modelTransformationArray[i * 4 + j]; } } return(RasterMapper.FromTransformation(mode, transformation)); } // nothing is available return(null); }
/// <summary> /// Creates a raster mapper from the transformation. /// </summary> /// <param name="mode">The raster mapping mode.</param> /// <param name="transformation">The transformation from raster space to geometry space.</param> /// <returns>The raster mapper based on the specified transformation.</returns> /// <exception cref="System.ArgumentNullException">The transformation is null.</exception> /// <exception cref="System.ArgumentException"> /// The number of columns in the transformation is not equal to 4. /// or /// The number of rows in the transformation is not equal to 4. /// or /// The transformation contains invalid values. /// </exception> /// <exception cref="System.NotSupportedException">The specified transformation is not supported.</exception> public static RasterMapper FromTransformation(RasterMapMode mode, Matrix transformation) { return(new RasterMapper(mode, transformation)); }