Example #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="t"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        private static PhiLam NadInterpolate(PhiLam t, NadTable ct)
        {
            PhiLam result, remainder;

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

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

 
            int offLam = 0; // normally we look to the right and bottom neighbor cells
            int offPhi = 0;
            if(remainder.Phi < .5) offLam = -1; // look to cells above current cell
            if(remainder.Lambda < .5) offPhi = -1; // look to cells to the left of current cell
                         
            PhiLam topLeft = GetValue(iPhi + offPhi, iLam + offLam, ct);
            PhiLam topRight = GetValue(iPhi + offPhi, iLam + offLam + 1, ct);
            PhiLam bottomLeft = GetValue(iPhi + offPhi + 1, iLam + offLam, ct);
            PhiLam bottomRight = GetValue(iPhi + offPhi + 1, iLam + offLam + 1, ct);

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

            // 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 mTL = remainder.Lambda*remainder.Phi;
            double mTR = (1 - remainder.Lambda)*remainder.Phi;
            double mBL = remainder.Lambda*(1 - remainder.Phi);
            double mBR = (1 - remainder.Lambda) * (1 - remainder.Phi);

            result.Lambda = mTL*topLeft.Lambda + mTR*topRight.Lambda + mBL*bottomLeft.Lambda + mBR*bottomRight.Lambda;
            result.Phi = mTL*topLeft.Phi + mTR*topRight.Phi + mBL*bottomLeft.Phi + mBR*bottomRight.Phi;

            return result;


        }
Example #2
0
        /// <summary>
        /// So that we can read from an embedded stream, this reads a NadTable
        /// from any stream, not just a filename.
        /// </summary>
        /// <param name="str">The stream to read</param>
        public void ReadStream(Stream str)
        {
            StreamReader sr = new StreamReader(str);
            _name = sr.ReadLine();
            string numText = sr.ReadToEnd();
            char[] separators = new[] {' ', ',',':', (char)10};
            string[] values = numText.Split(separators, StringSplitOptions.RemoveEmptyEntries);
            _numLambdas = int.Parse(values[0]);
            _numPhis = int.Parse(values[1]);
            _lowerLeft.Lambda = double.Parse(values[3]) * DegToRad;
            _lowerLeft.Phi = double.Parse(values[4]) * DegToRad;
            _cellSize.Lambda = double.Parse(values[5]) * DegToRad;
            _cellSize.Phi = double.Parse(values[6]) * DegToRad;
            int p = 7;
            _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++;
                }
            }

        }
Example #3
0
        private static PhiLam Convert(PhiLam input, bool inverse, NadTable table )
        {
            if (input.Lambda == HUGE_VAL) return input;
            // Normalize input to ll origin
            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)
                    {
                        System.Diagnostics.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)
                {
                    System.Diagnostics.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;
        }