Help on DataSet Reprojection

Jan 18, 2011 at 5:41 AM

Hello. This is the doc for DataSet.Reproject method

 

        /// <summary>
        /// RasterBounds datasets offer a limited sort of reproject on the fly.
        /// This tries to update the bounds by reprojecting the top left and bottom
        /// left and top right coordinates and updating the "affine" transform.
        /// This should not be used if CanReproject is false.
        /// Greater accuracy can be accomplished using the Projective transform,
        /// which is planned to be implemented as a toolbox function.
        /// </summary>
        /// <param name="targetProjection">The projectionInfo to project to.</param>
        public override void Reproject(Projections.ProjectionInfo targetProjection)
        {
            if (CanReproject == false) return;
            double[] aff = Projections.Reproject.ReprojectAffine(Bounds.AffineCoefficients, Bounds.NumRows,
                                                                 Bounds.NumColumns,
                                                                 Projection, targetProjection);
            Bounds.AffineCoefficients = aff;
        }

 

and this is the one for the Reproject.ReprojectAffine one

 

        /// <summary>
        /// This method reprojects the affine transform coefficients.  This is used for projection on the fly,
        /// where image transforms can take advantage of an affine projection, but does not have the power of
        /// a full projective transform and gets less and less accurate as the image covers larger and larger
        /// areas.  Since most image layers represent small rectangular areas, this should not be a problem in
        /// most cases.  the affine array should be ordered as follows:
        /// X' = [0] + [1] * Column + [2] * Row
        /// Y' = [3] + [4] * Column + [5] * Row
        /// </summary>
        /// <param name="affine">The array of double affine coefficients.</param>
        /// <param name="numRows">The number of rows to use for the lower bounds.  Value of 0 or less will be set to 1.</param>
        /// <param name="numCols">The number of columns to use to get the right bounds.  Values of 0 or less will be set to 1.</param>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns>The transformed coefficients</returns>
        public static double[] ReprojectAffine(double[] affine, double numRows, double numCols, ProjectionInfo source, ProjectionInfo dest)
        {...}

 

Could you explain the difference between the affine transform and the projective transform in easy words?

My problem is the following. I have a grid (1290 rows * 2230 columns) in Lambert Conformal Conic-WGS84 projected system reference.My goal is to reproject the grid in WGS84 geographic system reference. My idea is: copy the grid, take the affine matrix from the original grid, reproject the affine matrix (ReprojectAffine method), set the reprojected affine matrix both with the new system reference in the copied grid and save it. Is that correct?

Developer
Jan 18, 2011 at 3:20 PM

In easy words, the affine transform describes movement based on a three point mapping, and it is easiest to discuss with the top left, top right and bottom left points.  The top left point is responsible for pinning the top left part of your image to a particular coordinate.  However, you could still stretch, skew, rotate etc around that one point, as long as the center of the top left cell fits into that location.  The top right point locks in how far you stretch your image horizontally.  It also locks in how much skew there is between the top two points, (how much vertical change there is between column cell centers).  The lower right point then locks in how much vertical stretch you have, and how much horizontal change there is between rows.  This then represents the full discriptive power of the affine transform, so while it can describe various parallelograms, what it can never describe is a trapezoid.

A projective transform adds a single coordinate to the mix.  It would be like giving you an extra pin for the lower right corner, so that you could stretch things out.  In fact, the projective transform ends up being far more complex.  An affine transform can be determined exactly from pinning ANY three reference points in your image.  They don't have to be the corners, that was just the easiest way to describe how the parameters are related to pinning points.  However the projective transform does not have one exact solution for any four reference points.  However, in the case of reprojecting the corners, it vastly simplifies the problem so that a solution can be found fairly easily.

Now the clincher is this.  GDI+ does not have the ability to apply a projective transform to an image.  I have experimented in the past with implementations using the projective transform, but nothing you write by hand at the high level programming language is going to be nearly as fast as the built in GDI+ transforms.  Images also can only store the affine coefficients in their world file.  Most images are also set up so that the skew terms are 0 anyway, and in fact you only need to know the upper left hand corner and the cell width and cell height.  However, the GDI+ drawing of DotSpatial should now be handling the skew terms as well.  So if you needed to do a very accurate reproject that implemented the projective transform, you would probably just create a rectangular transparent image large enough to contain the whole result, and then set the values within.

The general projection on the fly solution is to reproject the top left, top right and bottom left coordinates, and then use these to quickly define the affine coefficients.  That's what the ReprojectAffine function does.  Since GDI+ supports the affine reproject and most of the time the trapezoiding effect on images to correctly reproject would be minimal, this usually works quite well.

Ted