Beispiel #1
0
        private bool ReadHeader(byte[] headerBuffer, GridTable table)
        {
            var ll = new PhiLambda
            {
                Phi    = GetBigEndianDouble(headerBuffer, 4 * 16 + 8),
                Lambda = -GetBigEndianDouble(headerBuffer, 7 * 16 + 8)
            };

            var ur = new PhiLambda
            {
                Phi    = GetBigEndianDouble(headerBuffer, 5 * 16 + 8),
                Lambda = -GetBigEndianDouble(headerBuffer, 6 * 16 + 8)
            };

            var cs = new PhiLambda
            {
                Phi    = GetBigEndianDouble(headerBuffer, 8 * 16 + 8),
                Lambda = -GetBigEndianDouble(headerBuffer, 9 * 16 + 8)
            };

            table.NumLambdas = (int)(Math.Abs(ur.Lambda - ll.Lambda) / cs.Lambda + .5) + 1;
            table.NumPhis    = (int)(Math.Abs(ur.Phi - ll.Phi) / cs.Phi + .5) + 1;

            table.LowerLeft      = PhiLambda.DegreesToRadians(ll);
            table.UpperRight     = PhiLambda.DegreesToRadians(ur);
            table.SizeOfGridCell = PhiLambda.DegreesToRadians(cs);

            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Parses the grid table data
        /// </summary>
        /// <param name="table">The table to fill</param>
        /// <returns>true if the data could be read.</returns>
        internal override bool ReadData(GridTable table)
        {
            using (var brLos = new BinaryReader(OpenGridTableStream()))
                using (var brLas = new BinaryReader(OpenLasStream()))
                {
                    var numPhis    = table.NumPhis;
                    var coeffs     = new PhiLambda[numPhis][];
                    var numLambdas = table.NumLambdas;

                    //position the stream
                    var offset = sizeof(float) * (numLambdas + 1);
                    brLas.BaseStream.Seek(offset, SeekOrigin.Current);
                    brLos.BaseStream.Seek(offset, SeekOrigin.Current);

                    for (var i = 0; i < numPhis; i++)
                    {
                        //Skip first 'zero' value
                        brLas.ReadBytes(sizeof(float));
                        brLos.ReadBytes(sizeof(float));

                        coeffs[i]    = new PhiLambda[numLambdas];
                        coeffs[i][0] = PhiLambda.ArcSecondsToRadians(brLas.ReadSingle(), brLos.ReadSingle());
                        for (var j = 1; j < numLambdas; j++)
                        {
                            coeffs[i][j] = coeffs[i][j - 1] +
                                           PhiLambda.ArcSecondsToRadians(brLas.ReadSingle(), brLos.ReadSingle());
                        }
                        table.Coefficients = coeffs;
                    }

                    return(true);
                }
        }
Beispiel #3
0
 /// <summary>
 /// Parses the grid table data
 /// </summary>
 /// <param name="table">The table to fill</param>
 /// <returns>true if the data could be read.</returns>
 internal override bool ReadData(GridTable table)
 {
     using (var s = OpenGridTableStream())
     {
         s.Seek(_dataOffset + 176, SeekOrigin.Current);
         using (var br = new BinaryReader(s))
         {
             var numPhis    = table.NumPhis;
             var coeffs     = new PhiLambda[numPhis][];
             var numLambdas = table.NumLambdas;
             for (var row = 0; row < numPhis; row++)
             {
                 coeffs[row] = new PhiLambda[numLambdas];
                 // NTV order is flipped compared with a normal CVS table
                 for (var col = numLambdas - 1; col >= 0; col--)
                 {
                     // shift values are given in "arc-seconds" and need to be converted to radians.
                     coeffs[row][col] =
                         PhiLambda.ArcSecondsToRadians(
                             ReadBigEndianDouble(br), ReadBigEndianDouble(br));
                 }
             }
         }
     }
     return(true);
 }
Beispiel #4
0
        internal bool Applies(PhiLambda location, out GridTable table)
        {
            //Set inital return value
            table = null;

            //Test finer sub grid tables
            foreach (var subGridTable in _subGridTables)
            {
                if (subGridTable.Applies(location, out table))
                {
                    return(true);
                }
            }

            if (location.Lambda < LowerLeft.Lambda ||
                location.Lambda > UpperRight.Lambda ||
                location.Phi < LowerLeft.Phi ||
                location.Phi > UpperRight.Phi)
            {
                return(false);
            }

            table = this;
            return(true);
        }
Beispiel #5
0
        internal Coordinate Apply(Coordinate geoCoord, bool inverse)
        {
            var input = new PhiLambda {
                Lambda = geoCoord.X, Phi = geoCoord.Y
            };

            if (input.Lambda == HugeValue)
            {
                return(geoCoord);
            }

            if (!_fullyLoaded)
            {
                lock (_lockReadData)
                {
                    if (!_fullyLoaded)
                    {
                        _loader.ReadData(this);
                    }
                    _fullyLoaded = true;
                }
            }

            var output = Convert(input, inverse);

            geoCoord.X = output.Lambda;
            geoCoord.Y = output.Phi;

            return(geoCoord);
        }
Beispiel #6
0
 public static PhiLambda ArcMicroSecondsToRadians(PhiLambda plInDegrees)
 {
     return(new PhiLambda
     {
         Lambda = ProjectionMath.ArcMicroSecondsToRadians(plInDegrees.Lambda),
         Phi = ProjectionMath.ArcMicroSecondsToRadians(plInDegrees.Phi)
     });
 }
        internal override bool ReadHeader(GridTable table)
        {
            using (var stream = OpenGridTableStream())
            {
                var header = new byte[176];
                if (stream.Read(header, 0, 176) != 176)
                {
                    return(false);
                }

                table.LowerLeft = new PhiLambda
                {
                    Phi    = GetBigEndianDouble(header, 24),
                    Lambda = -GetBigEndianDouble(header, 72)
                };

                table.UpperRight = new PhiLambda
                {
                    Phi    = GetBigEndianDouble(header, 40),
                    Lambda = -GetBigEndianDouble(header, 56)
                };

                table.SizeOfGridCell = new PhiLambda
                {
                    Phi    = GetBigEndianDouble(header, 88),
                    Lambda = -GetBigEndianDouble(header, 104)
                };

                var size = table.UpperRight - table.LowerLeft;
                table.NumLambdas = (int)(Math.Abs(size.Lambda) / table.SizeOfGridCell.Lambda + 0.5) + 1;
                table.NumPhis    = (int)(Math.Abs(size.Phi) / table.SizeOfGridCell.Phi + 0.5) + 1;

                table.LowerLeft      = PhiLambda.DegreesToRadians(table.LowerLeft);
                table.UpperRight     = PhiLambda.DegreesToRadians(table.UpperRight);
                table.SizeOfGridCell = PhiLambda.DegreesToRadians(table.SizeOfGridCell);

                return(true);
            }
        }
        internal override bool ReadData(GridTable table)
        {
            using (var br = new BinaryReader(OpenGridTableStream()))
            {
                br.BaseStream.Seek(176, SeekOrigin.Current);
                var coeffs = new PhiLambda[table.NumPhis][];
                for (var row = 0; row < table.NumPhis; row++)
                {
                    coeffs[row] = new PhiLambda[table.NumLambdas];

                    // NTV order is flipped compared with a normal CVS table
                    for (var col = table.NumLambdas - 1; col >= 0; col--)
                    {
                        const double degToArcSec = (Math.PI / 180) / 3600;
                        // shift values are given in "arc-seconds" and need to be converted to radians.
                        coeffs[row][col].Phi    = ReadBigEndianDouble(br) * degToArcSec;
                        coeffs[row][col].Lambda = ReadBigEndianDouble(br) * degToArcSec;
                    }
                }
                table.Coefficients = coeffs;
                return(true);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Parses the grid table header and returns an appropriate <see cref="GridTable"/>
        /// </summary>
        /// <param name="table">The grid tabel to initialize</param>
        /// <returns>true if the header could be read.</returns>
        internal override bool ReadHeader(GridTable table)
        {
            using (var br = new BinaryReader(OpenGridTableStream()))
            {
                br.BaseStream.Seek(64, SeekOrigin.Current);

                table.NumLambdas = br.ReadInt32();
                table.NumPhis    = br.ReadInt32();
                br.ReadBytes(4);

                PhiLambda ll, cs;
                ll.Lambda = br.ReadSingle();
                cs.Lambda = br.ReadSingle();
                ll.Phi    = br.ReadSingle();
                cs.Phi    = br.ReadSingle();

                table.LowerLeft      = PhiLambda.DegreesToRadians(ll);
                table.SizeOfGridCell = PhiLambda.DegreesToRadians(cs);
                table.UpperRight     = ll + cs.Times(table.NumPhis, table.NumLambdas);

                return(true);
            }
        }
Beispiel #10
0
        private PhiLambda InterpolateGrid(PhiLambda t)
        {
            PhiLambda result, remainder;

            result.Phi    = HugeValue;
            result.Lambda = HugeValue;

            // find indices and normalize by the cell size (so fractions range from 0 to 1)
            var iLam = (int)Math.Floor(t.Lambda /= SizeOfGridCell.Lambda);
            var iPhi = (int)Math.Floor(t.Phi /= SizeOfGridCell.Phi);

            // use the index to determine the remainder
            remainder.Lambda = t.Lambda - iLam;
            remainder.Phi    = t.Phi - iPhi;

            //int offLam = 0; // normally we look to the right and bottom neighbor cells
            //int offPhi = 0;
            //if (remainder.Lambda < .5) offLam = -1; // look to cell left of the current cell
            //if (remainder.Phi < .5) offPhi = -1; // look to cell above the of the current cell

            //// because the fractional weights are between cells, we need to adjust the
            //// "remainder" so that it is now relative to the center of the top left
            //// cell, taking into account that the definition of the top left cell
            //// depends on whether the original remainder was larger than .5
            //remainder.Phi = (remainder.Phi > .5) ? remainder.Phi - .5 : remainder.Phi + .5;
            //remainder.Lambda = (remainder.Lambda > .5) ? remainder.Lambda - .5 : remainder.Phi + .5;

            if (iLam < 0)
            {
                if (iLam == -1 && remainder.Lambda > 0.99999999999)
                {
                    iLam++;
                    remainder.Lambda = 0;
                }
                else
                {
                    return(result);
                }
            }
            else if (iLam + 1 >= NumLambdas)
            {
                if (iLam + 1 == NumLambdas && remainder.Lambda < 1e-11)
                {
                    iLam--;
                }
                else
                {
                    return(result);
                }
            }
            if (iPhi < 0)
            {
                if (iPhi == -1 && remainder.Phi > 0.99999999999)
                {
                    iPhi++;
                    remainder.Phi = 0;
                }
                else
                {
                    return(result);
                }
            }
            else if (iPhi + 1 >= NumPhis)
            {
                if (iPhi + 1 == NumPhis && remainder.Phi < 1e-11)
                {
                    iPhi--;
                    remainder.Phi = 1;
                }
                else
                {
                    return(result);
                }
            }

            var f00 = GetValue(iPhi, iLam);
            var f01 = GetValue(iPhi + 1, iLam);
            var f10 = GetValue(iPhi, iLam + 1);
            var f11 = GetValue(iPhi + 1, iLam + 1);

            // The cell weight is equivalent to the area of a cell sized square centered
            // on the actual point that overlaps with the cell.

            // Since the overlap must add up to 1, any portion that does not overlap
            // on the left must overlap on the right, hence (1-remainder.Lambda)
            var m00 = (1 - remainder.Lambda) * (1 - remainder.Phi);
            var m01 = (1 - remainder.Lambda) * remainder.Phi;
            var m10 = remainder.Lambda * (1 - remainder.Phi);
            var m11 = remainder.Lambda * remainder.Phi;

            result.Lambda = m00 * f00.Lambda + m01 * f01.Lambda + m10 * f10.Lambda + m11 * f11.Lambda;
            result.Phi    = m00 * f00.Phi + m01 * f01.Phi + m10 * f10.Phi + m11 * f11.Phi;

            return(result);
        }
Beispiel #11
0
        private PhiLambda Convert(PhiLambda input, bool inverse)
        {
            var tb = input;

            tb.Lambda -= LowerLeft.Lambda;
            tb.Phi    -= LowerLeft.Phi;
            tb.Lambda  = ProjectionMath.NormalizeLongitude(tb.Lambda - Math.PI) + Math.PI;

            var t = InterpolateGrid(tb);

            if (inverse)
            {
                PhiLambda dif;
                int       i = MaxIterations;
                if (t.Lambda == HugeValue)
                {
                    return(t);
                }
                t.Lambda = tb.Lambda + t.Lambda;
                t.Phi    = tb.Phi - t.Phi;
                do
                {
                    var del = InterpolateGrid(t);

                    /* This case used to return failure, but I have
                     * changed it to return the first order approximation
                     * of the inverse shift.  This avoids cases where the
                     * grid shift *into* this grid came from another grid.
                     * While we aren't returning optimally correct results
                     * I feel a close result in this case is better than
                     * no result.  NFW
                     * To demonstrate use -112.5839956 49.4914451 against
                     * the NTv2 grid shift file from Canada. */
                    if (del.Lambda == HugeValue)
                    {
                        Debug.WriteLine("InverseShiftFailed");
                        break;
                    }
                    t.Lambda -= dif.Lambda = t.Lambda - del.Lambda - tb.Lambda;
                    t.Phi    -= dif.Phi = t.Phi + del.Phi - tb.Phi;
                } while (i-- > 0 && Math.Abs(dif.Lambda) > Tolerance && Math.Abs(dif.Phi) > Tolerance);
                if (i < 0)
                {
                    Debug.WriteLine("InvShiftConvergeFailed");
                    t.Lambda = t.Phi = HugeValue;
                    return(t);
                }
                input.Lambda = ProjectionMath.NormalizeLongitude(t.Lambda + LowerLeft.Lambda);
                input.Phi    = t.Phi + LowerLeft.Phi;
            }
            else
            {
                if (t.Lambda == HugeValue)
                {
                    input = t;
                }
                else
                {
                    input.Lambda -= t.Lambda;
                    input.Phi    += t.Phi;
                }
            }
            return(input);
        }
Beispiel #12
0
        internal override bool ReadData(GridTable table)
        {
            using (var sr = new StreamReader(OpenGridTableStream()))
            {
                //Skip first 2 lines
                sr.ReadLine();
                sr.ReadLine();

                var phiIndex    = -1;
                var lambdaIndex = 0;

                double phi = 0, lambda = 0;
                var    coeff = new PhiLambda[table.NumPhis][];
                while (!sr.EndOfStream)
                {
                    var line = sr.ReadLine();
                    if (string.IsNullOrEmpty(line))
                    {
                        continue;
                    }
                    var      posColon = line.IndexOf(':');
                    string[] values;
                    int      valueIndex;
                    if (posColon > 0)
                    {
                        phiIndex                  = int.Parse(line.Substring(0, posColon), NumberStyles.Integer);
                        coeff[phiIndex]           = new PhiLambda[table.NumLambdas];
                        line                      = line.Substring(posColon + 1);
                        values                    = line.Split(new[] { ' ' });
                        lambda                    = ProjectionMath.ArcSecondsToRadians(long.Parse(values[0], NumberStyles.Integer));
                        phi                       = ProjectionMath.ArcSecondsToRadians(long.Parse(values[1], NumberStyles.Integer));
                        coeff[phiIndex][0].Phi    = phi;
                        coeff[phiIndex][0].Lambda = lambda;
                        lambdaIndex               = 1;
                        valueIndex                = 2;
                    }
                    else
                    {
                        values     = line.Split(new[] { ' ' });
                        valueIndex = 0;
                    }

                    if (phiIndex >= 0)
                    {
                        while (lambdaIndex < table.NumLambdas)
                        {
                            lambda += ProjectionMath.ArcMicroSecondsToRadians(
                                long.Parse(values[valueIndex++], NumberStyles.Integer));
                            phi += ProjectionMath.ArcMicroSecondsToRadians(
                                long.Parse(values[valueIndex++], NumberStyles.Integer));

                            coeff[phiIndex][lambdaIndex].Phi    = phi;
                            coeff[phiIndex][lambdaIndex].Lambda = lambda;
                            lambdaIndex++;
                        }
                    }
                }
                table.Coefficients = coeff;
            }
            return(true);
        }