Example #1
0
        /// <summary>
        /// Determines if the shape is partially inside grid extents.
        /// </summary>
        /// <param name="raster">Raster that should be checked.</param>
        /// <param name="shape">Shape that should be checked.</param>
        /// <returns>false, if the shape is completely outside grid extents
        /// true, if it's at least partially inside </returns>
        public static bool ContainsFeature(this IRaster raster, IFeature shape)
        {
            IRasterBounds bounds      = raster.Bounds;
            Extent        shapeExtent = shape.Geometry.EnvelopeInternal.ToExtent();

            return(!(shapeExtent.MinX > bounds.Extent.MaxX) && !(shapeExtent.MinY > bounds.Extent.MaxY) && !(shapeExtent.MaxX < bounds.Extent.MinX) && !(shapeExtent.MaxY < bounds.Extent.MinY));
        }
Example #2
0
 /// <summary>
 /// Extends the normal bounds changing behavior to also update the world file.
 /// </summary>
 /// <param name="bounds">Updates the world file.</param>
 protected override void OnBoundsChanged(IRasterBounds bounds)
 {
     if (WorldFile != null && bounds != null)
     {
         WorldFile.Affine = bounds.AffineCoefficients;
     }
 }
Example #3
0
        /// <summary>
        /// Returns the row col index
        /// </summary>
        /// <param name="bounds">The raster bounds to perform the calculation on</param>
        /// <param name="location">Gets or sets the ICoordinate</param>
        /// <returns>An RcIndex that shows the best row or column index for the specified coordinate.</returns>
        public static RcIndex ProjToCell(this IRasterBounds bounds, Coordinate location)
        {
            double[] c = bounds.AffineCoefficients;
            double   rw, cl;

            if (c[2] == 0 && c[4] == 0)
            {
                // If we don't have skew terms, then the x and y terms are independent.
                // also both of the other tests will have divide by zero errors and fail.
                cl = (location.X - c[0]) / c[1];
                rw = (location.Y - c[3]) / c[5];
            }
            else if (c[2] != 0)
            {
                // this equation will have divide by zero if c[2] is zero, but works if c[4] is zero
                double div = (c[5] * c[1]) / c[2] - c[4];
                cl = (c[3] + (c[5] * location.X) / c[2] - (c[5] * c[0]) / c[2] - location.Y) / div;
                rw = (location.X - c[0] - c[1] * cl) / c[2];
            }
            else
            {
                double div = (c[4] * c[2] / c[1] - c[5]);
                rw = (c[3] + c[4] * location.X / c[1] - c[4] * c[0] / c[1] - location.Y) / div;
                cl = (location.X - c[2] * rw - c[0]) / c[1];
            }
            int iRow = (int)Math.Floor(rw);
            int iCol = (int)Math.Floor(cl);

            if (iRow < 0 || iCol < 0 || iRow >= bounds.NumRows || iCol >= bounds.NumColumns)
            {
                return(RcIndex.Empty);
            }

            return(new RcIndex(iRow, iCol));
        }
Example #4
0
        /// <summary>
        /// The affine transform can make figuring out what rows and columns are needed from the original image
        /// in order to correctly fill a geographic extent challenging. This attempts to handle that back projection
        /// problem. It returns a System.Drawing.Rectangle in pixel (cell) coordinates that is completely contains
        /// the geographic extents, but is not larger than the bounds of the underlying image.
        /// If geographic extent fully contains extent of IRasterBounds, than returns rectangle which contains full raster image.
        /// If geographic extent partially contains extent of IRasterBounds, than returns rectangle which contains needed edges of full raster image.
        /// It back projects all four corners of the extent and returns the bounding rectangle clipped by the image rectangle.
        /// </summary>
        /// <param name="self">Instance of <see cref="IRasterBounds"/></param>
        /// <param name="extent">Extent to test.</param>
        /// <returns>Rectangle in pixel (cell) coordinates.</returns>
        public static Rectangle CellsContainingExtent(this IRasterBounds self, Extent extent)
        {
            var se     = self.Extent;
            var exMinX = Math.Max(extent.MinX, se.MinX);
            var exMaxY = Math.Min(extent.MaxY, se.MaxY);
            var exMaxX = Math.Min(extent.MaxX, se.MaxX);
            var exMinY = Math.Max(extent.MinY, se.MinY);

            var coords = new List <Coordinate>
            {
                new Coordinate(exMinX, exMaxY),
                new Coordinate(exMaxX, exMaxY),
                new Coordinate(exMinX, exMinY),
                new Coordinate(exMaxX, exMinY)
            };
            int minX = self.NumColumns;
            int minY = self.NumRows;
            int maxX = 0;
            int maxY = 0;

            foreach (var c in coords)
            {
                var rowCol = self.ProjToCell(c);
                if (rowCol.Row < minY)
                {
                    minY = rowCol.Row;
                }
                if (rowCol.Column < minX)
                {
                    minX = rowCol.Column;
                }
                if (rowCol.Row > maxY)
                {
                    maxY = rowCol.Row;
                }
                if (rowCol.Column > maxX)
                {
                    maxX = rowCol.Column;
                }
            }

            if (minX < 0)
            {
                minX = 0;
            }
            if (minY < 0)
            {
                minY = 0;
            }
            if (maxX > self.NumColumns)
            {
                maxX = self.NumColumns;
            }
            if (maxY > self.NumRows)
            {
                maxY = self.NumRows;
            }
            return(new Rectangle(minX, minY, maxX - minX, maxY - minY));
        }
Example #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PyramidImage"/> class and uses the raster bounds to specify the number or rows and columns.
 /// No data is written at this time.
 /// </summary>
 /// <param name="fileName">Name of the file.</param>
 /// <param name="bounds">The raster bounds.</param>
 public PyramidImage(string fileName, IRasterBounds bounds)
 {
     Filename = fileName;
     Bounds   = bounds;
     CreateHeaders(bounds.NumRows, bounds.NumColumns, bounds.AffineCoefficients);
     Width  = Header.ImageHeaders[0].NumColumns;
     Height = Header.ImageHeaders[0].NumRows;
 }
Example #6
0
 /// <summary>
 /// Calculates the area of this envelope.  Because the word Area,
 /// like Volume, is dimension specific, this method only looks
 /// at the X and Y ordinates, and requires at least 2 ordinates.
 /// </summary>
 /// <param name="self">The IEnvelope to use with this method</param>
 /// <returns>The 2D area as a double value.</returns>
 public static double Area(this IRasterBounds self)
 {
     if (self == null)
     {
         return(-1);
     }
     return(self.Width * self.Height);
 }
Example #7
0
        /// <summary>
        /// Given any input row or column, this returns the appropriate geographic location for the
        /// position of the center of the cell.
        /// </summary>
        /// <param name="bounds">The raster bounds to perform the calculation on</param>
        /// <param name="row">The integer row index from 0 to numRows - 1</param>
        /// <param name="column">The integer column index from 0 to numColumns - 1</param>
        /// <returns>The geographic position of the center of the specified cell</returns>
        public static Coordinate CellCenter_ToProj(this IRasterBounds bounds, int row, int column)
        {
            double[] affine = bounds.AffineCoefficients;
            double   x      = affine[0] + affine[1] * column + affine[2] * row;
            double   y      = affine[3] + affine[4] * column + affine[5] * row;

            return(new Coordinate(x, y));
        }
Example #8
0
 /// <summary>
 /// Creates a new Pyramid image, and uses the raster bounds to specify the number or rows and columns.
 /// No data is written at this time.
 /// </summary>
 /// <param name="fileName"></param>
 /// <param name="bounds"></param>
 public PyramidImage(string fileName, IRasterBounds bounds)
 {
     Filename = fileName;
     Bounds = bounds;
     CreateHeaders(bounds.NumRows, bounds.NumColumns, bounds.AffineCoefficients);
     Width = _header.ImageHeaders[0].NumColumns;
     Height = _header.ImageHeaders[0].NumRows;
 }
Example #9
0
        /// <summary>
        /// Given the row and column, this returns the geographic position of the bottom right corner of the cell
        /// </summary>
        /// <param name="bounds">The raster bounds to perform the calculation on</param>
        /// <param name="row">The integer row index from 0 to numRows - 1</param>
        /// <param name="column">The integer column index from 0 to numColumns - 1</param>
        /// <returns>The geographic position of the bottom right corner of the specified cell</returns>
        public static Coordinate CellBottomRight_ToProj(this IRasterBounds bounds, int row, int column)
        {
            double[] affine = bounds.AffineCoefficients;
            double   x      = affine[0] + affine[1] * (column + 0.5) + affine[2] * (row + 0.5);
            double   y      = affine[3] + affine[4] * (column + 0.5) + affine[5] * (row + 0.5);

            return(new Coordinate(x, y));
        }
Example #10
0
 /// <summary>
 /// Uses the specified distance to expand the envelope by that amount in all dimensions.
 /// </summary>
 /// <param name="self">The <c>IRasterBounds</c> that this calculation is for.</param>
 /// <param name="distance">The double distance to expand in all directions.</param>
 public static void ExpandBy(this IRasterBounds self, double distance)
 {
     self.X      -= distance;
     self.Y      += distance;
     self.Width  += distance * 2;
     self.Height += distance * 2;
     // the maximum is now the minimum etc.
 }
Example #11
0
 /// <summary>
 /// Occurs when the bounds have been set.
 /// </summary>
 /// <param name="bounds">The new bounds.</param>
 protected override void OnBoundsChanged(IRasterBounds bounds)
 {
     // Bounds may be null when the image layer is being disposed.
     // We could probably skip calling this event in that case, but at any rate, we don't want to crash.
     if (WorldFile != null && bounds != null)
     {
         WorldFile.Affine = bounds.AffineCoefficients;
     }
 }
Example #12
0
 /// <summary>
 /// Re-defines the double precision affine transform values based on the specified
 /// system.Drawing.Matrix.
 /// </summary>
 /// <param name="bounds">The bounds to adjust based on the matrix</param>
 /// <param name="matrix">The matrix to use as a guide for adjustments.</param>
 public static void Set_AffineMatrix(this IRasterBounds bounds, Matrix matrix)
 {
     double[] affine = new double[6];
     affine[0] = Double.Parse(matrix.Elements[0].ToString()); // XShift
     affine[2] = Double.Parse(matrix.Elements[1].ToString()); // RotationX
     affine[4] = Double.Parse(matrix.Elements[2].ToString()); // RotationY
     affine[3] = Double.Parse(matrix.Elements[3].ToString()); // YShift
     affine[1] = Double.Parse(matrix.Elements[4].ToString()); // CellWidth
     affine[5] = Double.Parse(matrix.Elements[5].ToString()); // CellHeight
 }
Example #13
0
        /// <summary>
        /// Images can be skewed, so this gets the point that actually defines the top left
        /// corner of the data in geographic coordinates
        /// </summary>
        /// <param name="bounds">The IRasterBounds to obtain the top left of</param>
        public static Coordinate TopLeft(this IRasterBounds bounds)
        {
            double[] affine = bounds.AffineCoefficients;
            // X' = [0] + [1] * Column + [2] * Row
            // Y' = [3] + [4] * Column + [5] * Row
            double x = affine[0];
            double y = affine[3];

            return(new Coordinate(x, y));
        }
Example #14
0
 /// <summary>
 /// Use the Save method instead of this extension. This only provides a default behavior that can
 /// optionally be used by implementers of the IRasterBounds interface.
 /// </summary>
 /// <param name="bounds">The bounds that get saved to file.</param>
 public static void SaveWorldFile(this IRasterBounds bounds)
 {
     using var sw = new StreamWriter(bounds.WorldFile);
     double[] affine = bounds.AffineCoefficients;
     sw.WriteLine(affine[1]); // Dx
     sw.WriteLine(affine[2]); // rotation X
     sw.WriteLine(affine[4]); // rotation Y
     sw.WriteLine(affine[5]); // Dy
     sw.WriteLine(affine[0]); // Top Left X
     sw.WriteLine(affine[3]); // Top Left Y
 }
Example #15
0
        /// <summary>
        /// Images can be skewed, so this gets the point that actually defines the bottom left
        /// corner of the data in geographic coordinates
        /// </summary>
        public static Coordinate BottomLeft(this IRasterBounds bounds)
        {
            double[] affine  = bounds.AffineCoefficients;
            int      numRows = bounds.NumRows;
            // X' = [0] + [1] * Column + [2] * Row
            // Y' = [3] + [4] * Column + [5] * Row
            double x = affine[0] + numRows * affine[2];
            double y = affine[3] + numRows * affine[5];

            return(new Coordinate(x, y));
        }
Example #16
0
 /// <summary>
 /// Re-defines the double precision affine transform values based on the specified System.Drawing2D.Matrix.
 /// </summary>
 /// <param name="bounds">The bounds to adjust based on the matrix</param>
 /// <param name="matrix">The matrix to use as a guide for adjustments.</param>
 public static void SetAffineMatrix(this IRasterBounds bounds, Matrix matrix)
 {
     double[] affine = new double[6];
     affine[0] = Convert.ToDouble(matrix.Elements[0]); // XShift
     affine[2] = Convert.ToDouble(matrix.Elements[1]); // RotationX
     affine[4] = Convert.ToDouble(matrix.Elements[2]); // RotationY
     affine[3] = Convert.ToDouble(matrix.Elements[3]); // YShift
     affine[1] = Convert.ToDouble(matrix.Elements[4]); // CellWidth
     affine[5] = Convert.ToDouble(matrix.Elements[5]); // CellHeight
     bounds.AffineCoefficients = affine;
 }
Example #17
0
 /// <summary>
 /// Converts creates a float precisions drawing matrix from the double precision affine
 /// coordinates.  The Matrix can be manipulated and then set back.  Some precision will
 /// be lost, however, as only floats are supported.
 /// </summary>
 public static Matrix Get_AffineMatrix(this IRasterBounds bounds)
 {
     double[] affine = bounds.AffineCoefficients;
     return(new Matrix(
                Convert.ToSingle(affine[0]),   // XShift
                Convert.ToSingle(affine[2]),   // RotationX
                Convert.ToSingle(affine[4]),   // RotationY
                Convert.ToSingle(affine[3]),   // YShift
                Convert.ToSingle(affine[1]),   // CellWidth
                Convert.ToSingle(affine[5]))); // CellHeight
 }
Example #18
0
        /// <summary>
        /// Returns the row col index.
        /// </summary>
        /// <param name="bounds">The raster bounds to perform the calculation on</param>
        /// <param name="location">Gets or sets the ICoordinate</param>
        /// <returns>An RcIndex that shows the best row or column index for the specified coordinate.</returns>
        public static RcIndex ProjToCell(this IRasterBounds bounds, Coordinate location)
        {
            var pc = new AffineTransform(bounds.AffineCoefficients).ProjToCell(location);

            if (pc.Row < 0 || pc.Column < 0 || pc.Row >= bounds.NumRows || pc.Column >= bounds.NumColumns)
            {
                return(RcIndex.Empty);
            }

            return(pc);
        }
Example #19
0
        /// <summary>
        /// Images can be skewed, so this gets the point that actually defines the top right
        /// corner of the data in geographic coordinates.
        /// </summary>
        /// <param name="bounds">The IRasterBounds to obtain the top right of.</param>
        /// <returns>The top right corner.</returns>
        public static Coordinate TopRight(this IRasterBounds bounds)
        {
            double[] affine     = bounds.AffineCoefficients;
            double   numColumns = bounds.NumColumns;

            // X' = [0] + [1] * Column + [2] * Row
            // Y' = [3] + [4] * Column + [5] * Row
            double x = affine[0] + (numColumns * affine[1]);
            double y = affine[3] + (numColumns * affine[4]);

            return(new Coordinate(x, y));
        }
Example #20
0
        /// <summary>
        /// determine if the shape is partially inside grid extents
        /// </summary>
        /// <returns>false, if the shape is completely outside grid extents
        /// true, if it's at least partially inside </returns>
        public static bool ContainsFeature(this IRaster raster, IFeature shape)
        {
            IRasterBounds bounds      = raster.Bounds;
            Extent        shapeExtent = shape.Envelope.ToExtent();

            if (shapeExtent.MinX > bounds.Extent.MaxX || shapeExtent.MinY > bounds.Extent.MaxY ||
                shapeExtent.MaxX < bounds.Extent.MinX || shapeExtent.MaxY < bounds.Extent.MinY)
            {
                return(false);
            }

            return(true);
        }
Example #21
0
        /// <summary>
        /// Use the Save method instead of this extension.  This only provides
        /// a default behavior that can optionally be used by implementers
        /// of the IRasterBounds interface.
        /// </summary>
        public static void SaveWorldFile(this IRasterBounds bounds)
        {
            StreamWriter sw = new StreamWriter(bounds.WorldFile);

            double[] affine = bounds.AffineCoefficients;
            sw.WriteLine(affine[1].ToString()); // Dx
            sw.WriteLine(affine[2].ToString()); // rotation X
            sw.WriteLine(affine[4].ToString()); // rotation Y
            sw.WriteLine(affine[5].ToString()); // Dy
            sw.WriteLine(affine[0].ToString()); // Top Left X
            sw.WriteLine(affine[3].ToString()); // Top Left Y
            sw.Close();
        }
Example #22
0
        /// <summary>
        /// Generates a new version of the affine transform that will
        /// cover the same region, but using the specified number of
        /// rows and columns instead.
        /// </summary>
        /// <param name="bounds">The raster bounds to resample</param>
        /// <param name="numRows">The new number of rows </param>
        /// <param name="numColumns">The new number of columns</param>
        /// <returns>
        /// X = [0] + [1] * Column + [2] * Row
        /// Y = [3] + [4] * Column + [5] * Row
        /// </returns>
        public static IRasterBounds ResampleTransform(this IRasterBounds bounds, int numRows, int numColumns)
        {
            double[] affine        = bounds.AffineCoefficients;
            double[] result        = new double[6];
            double   oldNumRows    = bounds.NumRows;
            double   oldNumColumns = bounds.NumColumns;

            result[0] = affine[0];                              // Top Left X
            result[3] = affine[3];                              // Top Left Y
            result[1] = affine[1] * oldNumColumns / numColumns; // dx
            result[5] = affine[5] * oldNumRows / numRows;       // dy
            result[2] = affine[2] * oldNumRows / numRows;       // skew x
            result[4] = affine[4] * oldNumColumns / numColumns; // skew y
            return(new RasterBounds(numRows, numColumns, result));
        }
Example #23
0
        /// <summary>
        /// Use the Open method instead of this extension. This only provides a default behavior that can
        /// optionally be used by implementers of the IRasterBounds interface.
        /// </summary>
        /// <param name="bounds">The bounds to open.</param>
        /// <param name="fileName">The *.wld or *.**w world file to open.</param>
        public static void OpenWorldFile(this IRasterBounds bounds, string fileName)
        {
            bounds.WorldFile = fileName;
            double[] affine = new double[6];

            StreamReader sr   = new StreamReader(fileName);
            string       line = sr.ReadLine();

            if (line != null)
            {
                affine[1] = double.Parse(line); // Dx
            }

            line = sr.ReadLine();
            if (line != null)
            {
                affine[2] = double.Parse(line); // Skew X
            }

            line = sr.ReadLine();
            if (line != null)
            {
                affine[4] = double.Parse(line); // Skew Y
            }

            line = sr.ReadLine();
            if (line != null)
            {
                affine[5] = double.Parse(line); // Dy
            }

            line = sr.ReadLine();
            if (line != null)
            {
                affine[0] = double.Parse(line); // Top Left X
            }

            line = sr.ReadLine();
            if (line != null)
            {
                affine[3] = double.Parse(line); // Top Left Y
            }

            bounds.AffineCoefficients = affine;
            sr.Close();
        }
Example #24
0
 /// <summary>
 /// Extends the normal bounds changing behavior to also update the world file.
 /// </summary>
 /// <param name="bounds">Updates the world file.</param>
 protected override void OnBoundsChanged(IRasterBounds bounds)
 {
     if (WorldFile != null && bounds != null)
         WorldFile.Affine = bounds.AffineCoefficients;
 }
Example #25
0
 /// <summary>
 /// Extends the normal bounds changing behavior to also update the world file.
 /// </summary>
 /// <param name="bounds">Updates the world file.</param>
 protected override void OnBoundsChanged(IRasterBounds bounds)
 {
     WorldFile.Affine = bounds.AffineCoefficients;
 }
Example #26
0
 /// <summary>
 /// Given the row and column, this returns the geographic position of the bottom right corner of the cell.
 /// </summary>
 /// <param name="bounds">The raster bounds to perform the calculation on</param>
 /// <param name="row">The integer row index from 0 to numRows - 1</param>
 /// <param name="column">The integer column index from 0 to numColumns - 1</param>
 /// <returns>The geographic position of the bottom right corner of the specified cell</returns>
 public static Coordinate CellBottomRightToProj(this IRasterBounds bounds, int row, int column)
 {
     return(new AffineTransform(bounds.AffineCoefficients).CellBottomRightToProj(row, column));
 }
Example #27
0
 /// <summary>
 /// Gets the right value, which is X + Width.
 /// </summary>
 /// <param name="self">The <c>IRasterBounds</c> that this calculation is for.</param>
 /// <returns></returns>
 public static double Right(this IRasterBounds self)
 {
     return(self.X + self.Width);
 }
Example #28
0
 /// <summary>
 /// Gets the left value for this rectangle.  This should be the
 /// X coordinate, but is added for clarity.
 /// </summary>
 /// <param name="self">The <c>IRasterBounds</c> that this calculation is for.</param>
 /// <returns></returns>
 public static double Left(this IRasterBounds self)
 {
     return(self.X);
 }
Example #29
0
 /// <summary>
 /// Gets the minY, which is Y - Height.
 /// </summary>
 /// <param name="self">The <c>IRasterBounds</c> that this calculation is for.</param>
 /// <returns></returns>
 public static double Bottom(this IRasterBounds self)
 {
     return(self.Y - self.Height);
 }
Example #30
0
 /// <summary>
 /// Occurs when the raster bounds of this data class have changed.
 /// </summary>
 /// <param name="bounds">The bounds that changed.</param>
 protected virtual void OnBoundsChanged(IRasterBounds bounds)
 {
 }
Example #31
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RasterBoundDataSet"/> class.
 /// </summary>
 protected RasterBoundDataSet()
 {
     _bounds = new RasterBounds(0, 0, new double[] { 0, 1, 0, 0, 0, -1 });
 }
Example #32
0
 /// <summary>
 /// Occurs when the bounds have been set.
 /// </summary>
 /// <param name="bounds">The new bounds.</param>
 protected override void OnBoundsChanged(IRasterBounds bounds)
 {
     // Bounds may be null when the image layer is being disposed.
     // We could probably skip calling this event in that case, but at any rate, we don't want to crash.
     if (WorldFile != null && Bounds != null)
         WorldFile.Affine = Bounds.AffineCoefficients;
 }
Example #33
0
 /// <summary>
 /// Creates a new instance of the RasterBoundData object, setting up a default RasterBounds.
 /// </summary>
 protected RasterBoundDataSet()
 {
     _bounds = new RasterBounds(0, 0, new double[] { 0, 1, 0, 0, 0, -1 });
 }
Example #34
0
 /// <summary>
 /// Occurs when the raster bounds of this data class have changed.
 /// </summary>
 protected virtual void OnBoundsChanged(IRasterBounds bounds)
 {
 }
Example #35
0
 /// <summary>
 /// Gets the maxY value, which should be Y.
 /// </summary>
 /// <param name="self">The <c>IRasterBounds</c> that this calculation is for.</param>
 /// <returns>The double value representing the Max Y value of this rectangle</returns>
 public static double Top(this IRasterBounds self)
 {
     return(self.Y);
 }
Example #36
0
 /// <summary>
 /// Attempts to save the affine coefficients to the specified worldfile file name
 /// </summary>
 /// <param name="bounds">The bounds to save</param>
 /// <param name="fileName">The fileName to save this bounds to</param>
 public static void SaveAs(this IRasterBounds bounds, string fileName)
 {
     bounds.WorldFile = fileName;
     bounds.Save();
 }