Пример #1
0
        /// <inheritdoc/>
        public override void FillData()
        {
            using (Stream str = GetStream())
            {
                if (str == null)
                {
                    return;
                }
                using (BinaryReader br = new BinaryReader(str))
                {
                    str.Seek(DataOffset, SeekOrigin.Begin);
                    str.Seek(176, SeekOrigin.Current);

                    int        numPhis    = NumPhis;
                    int        numLambdas = NumLambdas;
                    PhiLam[][] cvs        = new PhiLam[numPhis][];

                    // Skip past rest of header
                    for (int row = 0; row < numPhis; row++)
                    {
                        cvs[row] = new PhiLam[NumLambdas];
                        // NTV order is flipped compared with a normal CVS table
                        for (int col = numLambdas - 1; col >= 0; col--)
                        {
                            // shift values are given in "arc-seconds" and need to be converted to radians.
                            cvs[row][col].Phi    = ReadDouble(br) * (Math.PI / 180) / 3600;
                            cvs[row][col].Lambda = ReadDouble(br) * (Math.PI / 180) / 3600;
                        }
                    }
                    Cvs    = cvs;
                    Filled = true;
                }
            }
        }
Пример #2
0
        /// <inheritdoc></inheritdoc>
        public override void ReadHeader()
        {
            byte[] header = new byte[176];
            using (Stream str = GetStream())
            {
                if (str == null) return;
                // Read important header content
                using (BinaryReader br = new BinaryReader(str))
                {
                    br.Read(header, 0, 176);
                }
            }

            PhiLam ll;
            ll.Phi = GetDouble(header, 24);
            ll.Lambda = -GetDouble(header, 72);

            double urPhi = GetDouble(header, 40);
            double urLam = -GetDouble(header, 56);

            PhiLam cs = new PhiLam();
            cs.Phi = GetDouble(header, 88);
            cs.Lambda = GetDouble(header, 104);

            NumLambdas = (int)(Math.Abs(urLam - ll.Lambda) / cs.Lambda + .5) + 1;
            NumPhis = (int)(Math.Abs(urPhi - ll.Phi) / cs.Phi + .5) + 1;
            ll.Lambda *= DEG_TO_RAD;
            ll.Phi *= DEG_TO_RAD;
            cs.Lambda *= DEG_TO_RAD;
            cs.Phi *= DEG_TO_RAD;

            LowerLeft = ll;
            CellSize = cs;
        }
Пример #3
0
        /// <inheritdoc></inheritdoc>
        public override void FillData()
        {
            using Stream strLos = GetStream();
            using Stream strLas = GetLasStream();
            if (strLas == null || strLos == null)
            {
                return;
            }
            using BinaryReader brLas = new(strLas);
            using BinaryReader brLos = new(strLos);
            int numPhis    = NumPhis;
            int numLambdas = NumLambdas;
            // .las/.los header is padded out to 1 full line of lambdas
            int offsetToData = ((NumLambdas + 1) * sizeof(Single));

            brLas.BaseStream.Seek(offsetToData, SeekOrigin.Begin);
            brLos.BaseStream.Seek(offsetToData, SeekOrigin.Begin);
            PhiLam[][] cvs = new PhiLam[numPhis][];
            for (int i = 0; i < numPhis; i++)
            {
                cvs[i] = new PhiLam[numLambdas];
                brLas.ReadSingle(); // discard leading 'zero'
                brLos.ReadSingle(); // discard leading 'zero'
                cvs[i][0].Phi    = brLas.ReadSingle() * SecToRad;
                cvs[i][0].Lambda = brLos.ReadSingle() * SecToRad;
                for (int j = 1; j < NumLambdas; j++)
                {
                    cvs[i][j].Phi    += brLas.ReadSingle() * SecToRad;
                    cvs[i][j].Lambda += brLos.ReadSingle() * SecToRad;
                }
            }
            Cvs    = cvs;
            Filled = true;
        }
Пример #4
0
        /// <inheritdoc></inheritdoc>
        public override void FillData()
        {
            string numText;

            using (Stream str = GetStream())
            {
                if (str == null)
                {
                    return;
                }
                using (StreamReader sr = new StreamReader(str))
                {
                    sr.ReadLine();
                    numText = sr.ReadToEnd();
                }
            }
            char[]   separators = new[] { ' ', ',', ':', (char)10 };
            string[] values     = numText.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            int      p          = 7;

            int numPhis    = NumPhis;
            int numLambdas = NumLambdas;

            PhiLam[][] cvs = new PhiLam[numPhis][];
            for (int i = 0; i < numPhis; i++)
            {
                cvs[i] = new PhiLam[numLambdas];
                int iCheck = int.Parse(values[p]);
                if (iCheck != i)
                {
                    throw new ProjectionException(ProjectionMessages.IndexMismatch);
                }
                p++;
                double lam = long.Parse(values[p]) * USecToRad;
                cvs[i][0].Lambda = lam;
                p++;
                double phi = long.Parse(values[p]) * USecToRad;
                cvs[i][0].Phi = phi;
                p++;
                for (int j = 1; j < NumLambdas; j++)
                {
                    lam += long.Parse(values[p]) * USecToRad;
                    cvs[i][j].Lambda = lam;
                    p++;
                    phi          += long.Parse(values[p]) * USecToRad;
                    cvs[i][j].Phi = phi;
                    p++;
                }
            }
            Cvs    = cvs;
            Filled = true;
        }
Пример #5
0
        private static bool TryGrid(PhiLam input, NadTable table)
        {
            var wLam = table.LowerLeft.Lambda;
            var eLam = wLam + (table.NumLambdas - 1) * table.CellSize.Lambda;
            var sPhi = table.LowerLeft.Phi;
            var nPhi = sPhi + (table.NumPhis - 1) * table.CellSize.Lambda;

            if (input.Lambda < wLam || input.Lambda > eLam ||
                input.Phi < sPhi || input.Phi > nPhi)
            {
                return(false);
            }
            return(true);
        }
Пример #6
0
        /// <inheritdoc></inheritdoc>
        public override void ReadHeader()
        {
            byte[] header = new byte[176];
            using (Stream str = GetStream())
            {
                if (str == null)
                {
                    return;
                }
                // Read important header content
                using (BinaryReader br = new BinaryReader(str))
                {
                    br.Read(header, 0, 176);
                }
            }

            PhiLam ll;

            ll.Phi    = GetDouble(header, 24);
            ll.Lambda = -GetDouble(header, 72);

            double urPhi = GetDouble(header, 40);
            double urLam = -GetDouble(header, 56);

            PhiLam cs = new PhiLam();

            cs.Phi    = GetDouble(header, 88);
            cs.Lambda = GetDouble(header, 104);

            NumLambdas = (int)(Math.Abs(urLam - ll.Lambda) / cs.Lambda + .5) + 1;
            NumPhis    = (int)(Math.Abs(urPhi - ll.Phi) / cs.Phi + .5) + 1;
            ll.Lambda *= DEG_TO_RAD;
            ll.Phi    *= DEG_TO_RAD;
            cs.Lambda *= DEG_TO_RAD;
            cs.Phi    *= DEG_TO_RAD;

            LowerLeft = ll;
            CellSize  = cs;
        }
Пример #7
0
        private static PhiLam NadInterpolate(PhiLam t, NadTable ct)
        {
            PhiLam result, remainder;

            result.Phi    = HUGE_VAL;
            result.Lambda = HUGE_VAL;
            // find indices and normalize by the cell size (so fractions range from 0 to 1)

            int iLam = (int)Math.Floor(t.Lambda /= ct.CellSize.Lambda);
            int iPhi = (int)Math.Floor(t.Phi /= ct.CellSize.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 >= ct.NumLambdas)
            {
                if (iLam + 1 == ct.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 >= ct.NumPhis)
            {
                if (iPhi + 1 == ct.NumPhis && remainder.Phi < 1e-11)
                {
                    iPhi--;
                    remainder.Phi = 1;
                }
                else
                {
                    return(result);
                }
            }

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

            // 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)

            double m00 = (1 - remainder.Lambda) * (1 - remainder.Phi);
            double m01 = (1 - remainder.Lambda) * remainder.Phi;
            double m10 = remainder.Lambda * (1 - remainder.Phi);
            double 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);
        }
Пример #8
0
        private static PhiLam Convert(PhiLam input, bool inverse, NadTable table)
        {
            if (input.Lambda == HUGE_VAL)
            {
                return(input);
            }
            // Normalize input to ll origin
            if (!table.Filled)
            {
                table.FillData();
            }
            PhiLam tb = input;

            tb.Lambda -= table.LowerLeft.Lambda;
            tb.Phi    -= table.LowerLeft.Phi;
            tb.Lambda  = Proj.Adjlon(tb.Lambda - Math.PI) + Math.PI;
            PhiLam t = NadInterpolate(tb, table);

            if (inverse)
            {
                PhiLam del, dif;
                int    i = MAX_TRY;
                if (t.Lambda == HUGE_VAL)
                {
                    return(t);
                }
                t.Lambda = tb.Lambda + t.Lambda;
                t.Phi    = tb.Phi - t.Phi;
                do
                {
                    del = NadInterpolate(t, table);

                    /* 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 == HUGE_VAL)
                    {
                        Debug.WriteLine(ProjectionMessages.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) > TOL && Math.Abs(dif.Phi) > TOL);
                if (i < 0)
                {
                    Debug.WriteLine(ProjectionMessages.InvShiftConvergeFailed);
                    t.Lambda = t.Phi = HUGE_VAL;
                    return(t);
                }
                input.Lambda = Proj.Adjlon(t.Lambda + table.LowerLeft.Lambda);
                input.Phi    = t.Phi + table.LowerLeft.Phi;
            }
            else
            {
                if (t.Lambda == HUGE_VAL)
                {
                    input = t;
                }
                else
                {
                    input.Lambda -= t.Lambda;
                    input.Phi    += t.Phi;
                }
            }
            return(input);
        }
Пример #9
0
        /// <inheritdoc></inheritdoc>
        public override void FillData()
        {
            using (Stream str = GetStream())
            {
                if (str == null) return;
                using (var br = new BinaryReader(str))
                {
                    int numPhis = NumPhis;
                    int numLambdas = NumLambdas;

                    PhiLam[][] cvs = new PhiLam[numPhis][];

                    // Skip past rest of header
                    str.Seek(176, SeekOrigin.Begin);
                    for (int row = 0; row < numPhis; row++)
                    {
                        cvs[row] = new PhiLam[numLambdas];
                        // NTV order is flipped compared with a normal CVS table
                        for (int col = numLambdas - 1; col >= 0; col--)
                        {
                            // shift values are given in "arc-seconds" and need to be converted to radians.
                            cvs[row][col].Phi = ReadDouble(br) * (Math.PI / 180) / 3600;
                            cvs[row][col].Lambda = ReadDouble(br) * (Math.PI / 180) / 3600;
                        }
                    }
                    Cvs = cvs;
                }
            }
        }
Пример #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="t"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private static PhiLam NadInterpolate(PhiLam t, NadTable ct)
        {
            PhiLam result, remainder;
            result.Phi = HUGE_VAL;
            result.Lambda = HUGE_VAL;
            // find indices and normalize by the cell size (so fractions range from 0 to 1)

            int iLam = (int)Math.Floor(t.Lambda /= ct.CellSize.Lambda);
            int iPhi = (int)Math.Floor(t.Phi /= ct.CellSize.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 >= ct.NumLambdas)
            {
                if (iLam + 1 == ct.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 >= ct.NumPhis)
            {
                if (iPhi + 1 == ct.NumPhis && remainder.Phi < 1e-11)
                {
                    iPhi--;
                    remainder.Phi = 1;
                }
                else
                {
                    return result;
                }
            }

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

            // 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)

            double m00 = (1 - remainder.Lambda) * (1 - remainder.Phi);
            double m01 = (1 - remainder.Lambda) * remainder.Phi;
            double m10 = remainder.Lambda * (1 - remainder.Phi);
            double 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;
        }
Пример #11
0
 private static PhiLam Convert(PhiLam input, bool inverse, NadTable table)
 {
     if (input.Lambda == HUGE_VAL) return input;
     // Normalize input to ll origin
     if (!table.Filled) table.FillData();
     PhiLam tb = input;
     tb.Lambda -= table.LowerLeft.Lambda;
     tb.Phi -= table.LowerLeft.Phi;
     tb.Lambda = Proj.Adjlon(tb.Lambda - Math.PI) + Math.PI;
     PhiLam t = NadInterpolate(tb, table);
     if (inverse)
     {
         PhiLam del, dif;
         int i = MAX_TRY;
         if (t.Lambda == HUGE_VAL) return t;
         t.Lambda = tb.Lambda + t.Lambda;
         t.Phi = tb.Phi - t.Phi;
         do
         {
             del = NadInterpolate(t, table);
             /* 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 == HUGE_VAL)
             {
                 Debug.WriteLine(ProjectionMessages.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) > TOL && Math.Abs(dif.Phi) > TOL);
         if (i < 0)
         {
             Debug.WriteLine(ProjectionMessages.InvShiftConvergeFailed);
             t.Lambda = t.Phi = HUGE_VAL;
             return t;
         }
         input.Lambda = Proj.Adjlon(t.Lambda + table.LowerLeft.Lambda);
         input.Phi = t.Phi + table.LowerLeft.Phi;
     }
     else
     {
         if (t.Lambda == HUGE_VAL)
         {
             input = t;
         }
         else
         {
             input.Lambda -= t.Lambda;
             input.Phi += t.Phi;
         }
     }
     return input;
 }
Пример #12
0
        /// <inheritdoc></inheritdoc>
        public override void FillData()
        {
            string numText;
            using (Stream str = GetStream())
            {
                if (str == null) return;
                using (StreamReader sr = new StreamReader(str))
                {
                    sr.ReadLine();
                    numText = sr.ReadToEnd();
                }
            }
            char[] separators = new[] { ' ', ',', ':', (char)10 };
            string[] values = numText.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            int p = 7;

            int numPhis = NumPhis;
            int numLambdas = NumLambdas;
            PhiLam[][] cvs = new PhiLam[numPhis][];
            for (int i = 0; i < numPhis; i++)
            {
                cvs[i] = new PhiLam[numLambdas];
                int iCheck = int.Parse(values[p]);
                if (iCheck != i)
                {
                    throw new ProjectionException(ProjectionMessages.IndexMismatch);
                }
                p++;
                double lam = long.Parse(values[p]) * USecToRad;
                cvs[i][0].Lambda = lam;
                p++;
                double phi = long.Parse(values[p]) * USecToRad;
                cvs[i][0].Phi = phi;
                p++;
                for (int j = 1; j < NumLambdas; j++)
                {
                    lam += long.Parse(values[p]) * USecToRad;
                    cvs[i][j].Lambda = lam;
                    p++;
                    phi += long.Parse(values[p]) * USecToRad;
                    cvs[i][j].Phi = phi;
                    p++;
                }
            }
            Cvs = cvs;
            Filled = true;
        }
Пример #13
0
 /// <inheritdoc></inheritdoc>
 public override void FillData()
 {
     using (Stream strLos = GetStream())
     using (Stream strLas = GetLasStream())
     {
         if (strLas == null || strLos == null) return;
         using (BinaryReader brLas = new BinaryReader(strLas))
         using (BinaryReader brLos = new BinaryReader(strLos))
         {
             int numPhis = NumPhis;
             int numLambdas = NumLambdas;
             // .las/.los header is padded out to 1 full line of lambdas
             int offsetToData = ((NumLambdas + 1) * sizeof(Single));
             brLas.BaseStream.Seek(offsetToData, SeekOrigin.Begin);
             brLos.BaseStream.Seek(offsetToData, SeekOrigin.Begin);
             PhiLam[][] cvs = new PhiLam[numPhis][];
             for (int i = 0; i < numPhis; i++)
             {
                 cvs[i] = new PhiLam[numLambdas];
                 brLas.ReadSingle(); // discard leading 'zero'
                 brLos.ReadSingle(); // discard leading 'zero'
                 cvs[i][0].Phi = brLas.ReadSingle() * SecToRad;
                 cvs[i][0].Lambda = brLos.ReadSingle() * SecToRad;
                 for (int j = 1; j < NumLambdas; j++)
                 {
                     cvs[i][j].Phi += brLas.ReadSingle() * SecToRad;
                     cvs[i][j].Lambda += brLos.ReadSingle() * SecToRad;
                 }
             }
             Cvs = cvs;
             Filled = true;
         }
     }
 }