Example #1
0
        //**********************************************************************
        //							pj_gridinfo_free()
        //**********************************************************************
        public static void pj_gridinfo_free(projCtx ctx, PJ_GRIDINFO gi)
        {
            if (gi == null)
            {
                return;
            }

            if (gi.child != null)
            {
                PJ_GRIDINFO child, next;

                for (child = gi.child; child != null; child = next)
                {
                    next = child.next;
                    pj_gridinfo_free(ctx, child);
                    child = null;
                }
            }

            if (gi.ct != null)
            {
                nad_free(gi.ct);
            }
            gi.ct = null;
        }
Example #2
0
 //**********************************************************************
 //						pj_deallocate_grids()
 //
 //		Deallocate all loaded grids.
 //**********************************************************************
 public static void pj_deallocate_grids()
 {
     while (grid_list != null)
     {
         PJ_GRIDINFO item = grid_list;
         grid_list = grid_list.next;
         item.next = null;
         pj_gridinfo_free(Proj.pj_get_default_ctx(), item);
         item = null;
     }
 }
Example #3
0
 //**********************************************************************
 //                        pj_deallocate_grids()
 //
 //        Deallocate all loaded grids.
 //**********************************************************************
 public static void pj_deallocate_grids()
 {
     while(grid_list!=null)
     {
         PJ_GRIDINFO item=grid_list;
         grid_list=grid_list.next;
         item.next=null;
         pj_gridinfo_free(Proj.pj_get_default_ctx(), item);
         item=null;
     }
 }
Example #4
0
        static bool IS_LSB = true; //    (1 == ((unsigned char *) (&byte_order_test))[0])

        #endregion Fields

        #region Methods

        //**********************************************************************
        //                            pj_gridinfo_free()
        //**********************************************************************
        public static void pj_gridinfo_free(projCtx ctx, PJ_GRIDINFO gi)
        {
            if(gi==null) return;

            if(gi.child!=null)
            {
                PJ_GRIDINFO child, next;

                for(child=gi.child; child!=null; child=next)
                {
                    next=child.next;
                    pj_gridinfo_free(ctx, child);
                    child=null;
                }
            }

            if(gi.ct!=null) nad_free(gi.ct);
            gi.ct=null;
        }
Example #5
0
        //**********************************************************************
        //						pj_gridinfo_parent()
        //
        //		Seek a parent grid file by name from a grid list.
        //**********************************************************************
        static PJ_GRIDINFO pj_gridinfo_parent(PJ_GRIDINFO gilist, string name)
        {
            while (gilist != null)
            {
                if (gilist.ct.id == name)
                {
                    return(gilist);
                }

                if (gilist.child != null)
                {
                    PJ_GRIDINFO parent = pj_gridinfo_parent(gilist.child, name);
                    if (parent != null)
                    {
                        return(parent);
                    }
                }

                gilist = gilist.next;
            }

            return(gilist);
        }
Example #6
0
        //**********************************************************************
        //							pj_gridinfo_init()
        //
        //		Open and parse header details from a datum gridshift file
        //		returning a list of PJ_GRIDINFOs for the grids in that
        //		file. This superceeds use of nad_init() for modern
        //		applications.
        //**********************************************************************
        public static PJ_GRIDINFO pj_gridinfo_init(projCtx ctx, string gridname)
        {
            Libc.errno     = Proj.pj_errno = 0;
            ctx.last_errno = 0;

            // --------------------------------------------------------------------
            //		Initialize a GRIDINFO with stub info we would use if it
            //		cannot be loaded.
            // --------------------------------------------------------------------
            PJ_GRIDINFO gilist = new PJ_GRIDINFO();

            gilist.gridname    = gridname;
            gilist.filename    = null;
            gilist.format      = "missing";
            gilist.grid_offset = 0;
            gilist.ct          = null;
            gilist.next        = null;

            // --------------------------------------------------------------------
            //		Open the file using the usual search rules.
            // --------------------------------------------------------------------
            FileStream fp = Proj.pj_open_lib(ctx, gridname, FileAccess.Read);

            if (fp == null)
            {
                Proj.pj_errno  = Libc.errno;
                ctx.last_errno = 0;               // don't treat as a persistent error
                return(gilist);
            }

            gilist.filename = gridname;

            // --------------------------------------------------------------------
            //		Load a header, to determine the file type.
            // --------------------------------------------------------------------
            byte[] header = new byte[160];

            try
            {
                if (fp.Read(header, 0, header.Length) != header.Length)
                {
                    fp.Close();
                    header = null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(gilist);
                }
            }
            catch
            {
                fp.Close();
                header = null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return(gilist);
            }

            fp.Seek(0, SeekOrigin.Begin);

            // --------------------------------------------------------------------
            //		Determine file type.
            // --------------------------------------------------------------------
            if (Encoding.ASCII.GetString(header, 0, 6) == "HEADER" &&
                Encoding.ASCII.GetString(header, 96, 6) == "W GRID" &&
                Encoding.ASCII.GetString(header, 144, 16) == "TO      NAD83   ")
            {
                pj_gridinfo_init_ntv1(ctx, fp, gilist);
            }
            else if (Encoding.ASCII.GetString(header, 0, 8) == "NUM_OREC" &&
                     Encoding.ASCII.GetString(header, 48, 7) == "GS_TYPE")
            {
                pj_gridinfo_init_ntv2(ctx, fp, gilist);
            }
            else if (gridname.Length > 4 && gridname.EndsWith("gtx", StringComparison.CurrentCultureIgnoreCase))
            {
                pj_gridinfo_init_gtx(ctx, fp, gilist);
            }
            else if (Encoding.ASCII.GetString(header, 0, 9) == "CTABLE V2")
            {
                CTABLE ct = nad_ctable2_init(ctx, fp);

                gilist.format = "ctable2";
                gilist.ct     = ct;

                Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "Ctable2 {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})",
                            ct.id, ct.lim.lam, ct.lim.phi, ct.ll.lam * Proj.RAD_TO_DEG, ct.ll.phi * Proj.RAD_TO_DEG,
                            (ct.ll.lam + (ct.lim.lam - 1) * ct.del.lam) * Proj.RAD_TO_DEG, (ct.ll.phi + (ct.lim.phi - 1) * ct.del.phi) * Proj.RAD_TO_DEG);
            }
            else
            {
                CTABLE ct = nad_ctable_init(ctx, fp);

                if (ct == null)
                {
                    Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "CTABLE ct is NULL.");
                }
                else
                {
                    gilist.format = "ctable";
                    gilist.ct     = ct;

                    Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "Ctable {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})",
                                ct.id, ct.lim.lam, ct.lim.phi, ct.ll.lam * Proj.RAD_TO_DEG, ct.ll.phi * Proj.RAD_TO_DEG,
                                (ct.ll.lam + (ct.lim.lam - 1) * ct.del.lam) * Proj.RAD_TO_DEG, (ct.ll.phi + (ct.lim.phi - 1) * ct.del.phi) * Proj.RAD_TO_DEG);
                }
            }

            fp.Close();

            return(gilist);
        }
Example #7
0
        //**********************************************************************
        //						pj_gridinfo_init_gtx()
        //
        //		Load a NOAA .gtx vertical datum shift file.
        //**********************************************************************
        static bool pj_gridinfo_init_gtx(projCtx ctx, FileStream fid, PJ_GRIDINFO gi)
        {
            byte[] header = new byte[40];
            CTABLE ct;
            double xorigin, yorigin, xstep, ystep;
            int    rows, columns;

            // --------------------------------------------------------------------
            //		Read the header.
            // --------------------------------------------------------------------
            if (fid.Read(header, 0, 40) != 40)
            {
                Proj.pj_ctx_set_errno(ctx, -38);
                return(false);
            }

            // --------------------------------------------------------------------
            //		Regularize fields of interest and extract.
            // --------------------------------------------------------------------
            if (IS_LSB)
            {
                swap_words(header, 0, 8, 4);
                swap_words(header, 32, 4, 2);
            }

            yorigin = BitConverter.ToDouble(header, 0);
            xorigin = BitConverter.ToDouble(header, 8);
            ystep   = BitConverter.ToDouble(header, 16);
            xstep   = BitConverter.ToDouble(header, 24);

            rows    = BitConverter.ToInt32(header, 32);
            columns = BitConverter.ToInt32(header, 36);

            if (xorigin < -360 || xorigin > 360 ||
                yorigin < -90 || yorigin > 90)
            {
                Console.WriteLine("gtx file header has invalid extents, corrupt?");
                Proj.pj_ctx_set_errno(ctx, -38);
                return(false);
            }

            // --------------------------------------------------------------------
            //		Fill in CTABLE structure.
            // --------------------------------------------------------------------
            ct    = new CTABLE();
            ct.id = "GTX Vertical Grid Shift File";

            ct.ll.lam  = xorigin;
            ct.ll.phi  = yorigin;
            ct.del.lam = xstep;
            ct.del.phi = ystep;
            ct.lim.lam = columns;
            ct.lim.phi = rows;

            // some GTX files come in 0-360 and we shift them back into the
            // expected -180 to 180 range if possible. This does not solve
            // problems with grids spanning the dateline.
            if (ct.ll.lam >= 180.0)
            {
                ct.ll.lam -= 360.0;
            }

#if !DEBUG
            if (ct.ll.lam >= 0.0 && ct.ll.lam + ct.del.lam * ct.lim.lam > 180.0)
            {
                Console.Error.WriteLine("This GTX spans the dateline! This will cause problems.");
            }

            Console.Error.WriteLine("GTX {0}x{1}: LL=({2},{3}) UR=({4},{5})", ct.lim.lam, ct.lim.phi, ct.ll.lam, ct.ll.phi, ct.ll.lam + (columns - 1) * xstep, ct.ll.phi + (rows - 1) * ystep);
#endif

            ct.ll.lam  *= Proj.DEG_TO_RAD;
            ct.ll.phi  *= Proj.DEG_TO_RAD;
            ct.del.lam *= Proj.DEG_TO_RAD;
            ct.del.phi *= Proj.DEG_TO_RAD;
            ct.cvs      = null;

            gi.ct          = ct;
            gi.grid_offset = 40;
            gi.format      = "gtx";

            return(true);
        }
Example #8
0
        //**********************************************************************
        //                        pj_gridinfo_parent()
        //
        //        Seek a parent grid file by name from a grid list.
        //**********************************************************************
        static PJ_GRIDINFO pj_gridinfo_parent(PJ_GRIDINFO gilist, string name)
        {
            while(gilist!=null)
            {
                if(gilist.ct.id==name) return gilist;

                if(gilist.child!=null)
                {
                    PJ_GRIDINFO parent=pj_gridinfo_parent(gilist.child, name);
                    if(parent!=null) return parent;
                }

                gilist=gilist.next;
            }

            return gilist;
        }
Example #9
0
        //**********************************************************************
        //                        pj_gridinfo_init_gtx()
        //
        //        Load a NOAA .gtx vertical datum shift file.
        //**********************************************************************
        static bool pj_gridinfo_init_gtx(projCtx ctx, FileStream fid, PJ_GRIDINFO gi)
        {
            byte[] header=new byte[40];
            CTABLE ct;
            double xorigin, yorigin, xstep, ystep;
            int rows, columns;

            // --------------------------------------------------------------------
            //		Read the header.
            // --------------------------------------------------------------------
            if(fid.Read(header, 0, 40)!=40)
            {
                Proj.pj_ctx_set_errno(ctx, -38);
                return false;
            }

            // --------------------------------------------------------------------
            //		Regularize fields of interest and extract.
            // --------------------------------------------------------------------
            if(IS_LSB)
            {
                swap_words(header, 0, 8, 4);
                swap_words(header, 32, 4, 2);
            }

            yorigin=BitConverter.ToDouble(header, 0);
            xorigin=BitConverter.ToDouble(header, 8);
            ystep=BitConverter.ToDouble(header, 16);
            xstep=BitConverter.ToDouble(header, 24);

            rows=BitConverter.ToInt32(header, 32);
            columns=BitConverter.ToInt32(header, 36);

            if(xorigin<-360||xorigin>360
                ||yorigin<-90||yorigin>90)
            {
                Console.WriteLine("gtx file header has invalid extents, corrupt?");
                Proj.pj_ctx_set_errno(ctx, -38);
                return false;
            }

            // --------------------------------------------------------------------
            //		Fill in CTABLE structure.
            // --------------------------------------------------------------------
            ct=new CTABLE();
            ct.id="GTX Vertical Grid Shift File";

            ct.ll.lam=xorigin;
            ct.ll.phi=yorigin;
            ct.del.lam=xstep;
            ct.del.phi=ystep;
            ct.lim.lam=columns;
            ct.lim.phi=rows;

            // some GTX files come in 0-360 and we shift them back into the
            // expected -180 to 180 range if possible. This does not solve
            // problems with grids spanning the dateline.
            if(ct.ll.lam>=180.0) ct.ll.lam-=360.0;

            #if !DEBUG
            if(ct.ll.lam>=0.0&&ct.ll.lam+ct.del.lam*ct.lim.lam>180.0)
                Console.Error.WriteLine("This GTX spans the dateline! This will cause problems.");

            Console.Error.WriteLine("GTX {0}x{1}: LL=({2},{3}) UR=({4},{5})", ct.lim.lam, ct.lim.phi, ct.ll.lam, ct.ll.phi, ct.ll.lam+(columns-1)*xstep, ct.ll.phi+(rows-1)*ystep);
            #endif

            ct.ll.lam*=Proj.DEG_TO_RAD;
            ct.ll.phi*=Proj.DEG_TO_RAD;
            ct.del.lam*=Proj.DEG_TO_RAD;
            ct.del.phi*=Proj.DEG_TO_RAD;
            ct.cvs=null;

            gi.ct=ct;
            gi.grid_offset=40;
            gi.format="gtx";

            return true;
        }
        public static int pj_apply_vgridshift(PJ defn, string listname, ref PJ_GRIDINFO[] gridlist_p, ref int gridlist_count_p, bool inverse, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if (gridlist_p == null)
            {
                gridlist_p = pj_gridlist_from_nadgrids(Proj.pj_get_ctx(defn), Proj.pj_param_s(defn.ctx, defn.parameters, listname), out gridlist_count_p);
                if (gridlist_p == null || gridlist_count_p == 0)
                {
                    return(defn.ctx.last_errno);
                }
            }

            if (gridlist_p == null || gridlist_count_p == 0)
            {
                Proj.pj_ctx_set_errno(defn.ctx, -38);
                return(-38);
            }

            PJ_GRIDINFO[] tables = gridlist_p;
            defn.ctx.last_errno = 0;

            for (int i = 0; i < point_count; i++)
            {
                int    io    = i * point_offset;
                double value = Libc.HUGE_VAL;

                LP input;
                input.phi = y[io];
                input.lam = x[io];

                // keep trying till we find a table that works
                for (int itable = 0; itable < gridlist_count_p; itable++)
                {
                    PJ_GRIDINFO gi = tables[itable];
                    CTABLE      ct = gi.ct;
                    double      grid_x, grid_y;
                    int         grid_ix, grid_iy;

                    // skip tables that don't match our point at all.
                    if (ct.ll.phi > input.phi || ct.ll.lam > input.lam || ct.ll.phi + (ct.lim.phi - 1) * ct.del.phi < input.phi || ct.ll.lam + (ct.lim.lam - 1) * ct.del.lam < input.lam)
                    {
                        continue;
                    }

                    // If we have child nodes, check to see if any of them apply.
                    while (gi.child != null)
                    {
                        PJ_GRIDINFO child = gi.child;

                        for (; child != null; child = child.next)
                        {
                            CTABLE ct1 = child.ct;

                            if (ct1.ll.phi > input.phi || ct1.ll.lam > input.lam || ct1.ll.phi + (ct1.lim.phi - 1) * ct1.del.phi < input.phi || ct1.ll.lam + (ct1.lim.lam - 1) * ct1.del.lam < input.lam)
                            {
                                continue;
                            }

                            break;
                        }

                        // If we didn't find a child then nothing more to do,
                        if (child == null)
                        {
                            break;
                        }

                        // otherwise use the child, first checking it's children.
                        gi = child;
                        ct = child.ct;
                    }

                    // load the grid shift info if we don't have it.
                    if (ct.cvs == null && !pj_gridinfo_load(Proj.pj_get_ctx(defn), gi))
                    {
                        Proj.pj_ctx_set_errno(defn.ctx, -38);
                        return(-38);
                    }

                    // Interpolation a location within the grid
                    grid_x  = (input.lam - ct.ll.lam) / ct.del.lam;
                    grid_y  = (input.phi - ct.ll.phi) / ct.del.phi;
                    grid_ix = (int)Math.Floor(grid_x);
                    grid_iy = (int)Math.Floor(grid_y);
                    grid_x -= grid_ix;
                    grid_y -= grid_iy;

                    LP cvs1 = ct.cvs[(grid_ix + grid_iy * ct.lim.lam) / 2];
                    LP cvs2 = ct.cvs[(grid_ix + (grid_iy + 1) * ct.lim.lam) / 2];
                    value = cvs1.lam * (1.0 - grid_x) * (1.0 - grid_y) + cvs1.phi * grid_x * (1.0 - grid_y) +
                            cvs2.lam * (1.0 - grid_x) * grid_y + cvs2.phi * grid_x * grid_y;

                    if (Math.Abs(value + 88.8888) < 0.0001)
                    {
                        value = Libc.HUGE_VAL;                                                  // nodata?
                    }
                    else
                    {
                        if (inverse)
                        {
                            z[io] -= value;
                        }
                        else
                        {
                            z[io] += value;
                        }
                    }

                    if (value != Libc.HUGE_VAL)
                    {
                        if (debug_count_apply_vgridshift++ < 20)
                        {
                            Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MINOR, "pj_apply_gridshift(): used {0}", ct.id);
                        }
                        break;
                    }
                }

                if (value == Libc.HUGE_VAL)
                {
                    Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_vgridshift(): failed to find a grid shift table for\n\t\t\tlocation ({0}dW,{1}dN)", x[io] * Proj.RAD_TO_DEG, y[io] * Proj.RAD_TO_DEG);
                    StringBuilder gridlist = new StringBuilder();
                    for (int itable = 0; itable < gridlist_count_p; itable++)
                    {
                        PJ_GRIDINFO gi = tables[itable];
                        if (itable == 0)
                        {
                            gridlist.AppendFormat("   tried: {0}", gi.gridname);
                        }
                        else
                        {
                            gridlist.AppendFormat(",{0}", gi.gridname);
                        }
                    }
                    Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "{0}", gridlist.ToString());

                    Proj.pj_ctx_set_errno(defn.ctx, (int)PJD_ERR.GRID_AREA);
                    return((int)PJD_ERR.GRID_AREA);
                }
            }

            return(0);
        }
Example #11
0
        //**********************************************************************
        //                        pj_gridlist_merge_grid()
        //
        //        Find/load the named gridfile and merge it into the
        //        last_nadgrids_list.
        //**********************************************************************
        static bool pj_gridlist_merge_gridfile(projCtx ctx, string gridname, ref PJ_GRIDINFO[] p_gridlist, ref int p_gridcount, ref int p_gridmax)
        {
            bool got_match=false;
            PJ_GRIDINFO this_grid, tail=null;

            // --------------------------------------------------------------------
            //		Try to find in the existing list of loaded grids. Add all
            //		matching grids as with NTv2 we can get many grids from one
            //		file (one shared gridname).
            // --------------------------------------------------------------------
            for(this_grid=grid_list; this_grid!=null; this_grid=this_grid.next)
            {
                if(this_grid.gridname==gridname)
                {
                    got_match=true;

                    // dont add to the list if it is invalid.
                    if(this_grid.ct==null) return false;

                    // do we need to grow the list?
                    if(p_gridcount>=p_gridmax-2)
                    {
                        PJ_GRIDINFO[] new_list;
                        int new_max=p_gridmax+20;

                        new_list=new PJ_GRIDINFO[new_max];
                        if(p_gridlist!=null)
                        {
                            Array.Copy(p_gridlist, new_list, p_gridmax);
                            p_gridlist=null;
                        }

                        p_gridlist=new_list;
                        p_gridmax=new_max;
                    }

                    // add to the list
                    p_gridlist[p_gridcount++]=this_grid;
                    p_gridlist[p_gridcount]=null;
                }

                tail=this_grid;
            }

            if(got_match) return true;

            // --------------------------------------------------------------------
            //		Try to load the named grid.
            // --------------------------------------------------------------------
            this_grid=pj_gridinfo_init(ctx, gridname);

            // we should get at least a stub grid with a missing "ct" member
            if(this_grid==null) return false;

            if(tail!=null) tail.next=this_grid;
            else grid_list=this_grid;

            // --------------------------------------------------------------------
            //		Recurse to add the grid now that it is loaded.
            // --------------------------------------------------------------------
            return pj_gridlist_merge_gridfile(ctx, gridname, ref p_gridlist, ref p_gridcount, ref p_gridmax);
        }
Example #12
0
        public static int pj_apply_gridshift_3(projCtx ctx, PJ_GRIDINFO[] tables, int grid_count, bool inverse, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if(tables==null||grid_count==0)
            {
                Proj.pj_ctx_set_errno(ctx, -38);
                return -38;
            }

            ctx.last_errno=0;

            for(int i=0; i<point_count; i++)
            {
                long io=i*point_offset;
                LP input, output;
                int itable;

                input.phi=y[io];
                input.lam=x[io];
                output.phi=Libc.HUGE_VAL;
                output.lam=Libc.HUGE_VAL;

                // keep trying till we find a table that works
                for(itable=0; itable<grid_count; itable++)
                {
                    PJ_GRIDINFO gi=tables[itable];
                    CTABLE ct=gi.ct;

                    double epsilon=(Math.Abs(ct.del.phi)+Math.Abs(ct.del.lam))/10000.0;

                    // skip tables that don't match our point at all.
                    if(ct.ll.phi-epsilon>input.phi||
                        ct.ll.lam-epsilon>input.lam||
                        ct.ll.phi+(ct.lim.phi-1)*ct.del.phi+epsilon<input.phi||
                        ct.ll.lam+(ct.lim.lam-1)*ct.del.lam+epsilon<input.lam) continue;

                    // If we have child nodes, check to see if any of them apply.
                    while(gi.child!=null)
                    {
                        PJ_GRIDINFO child=gi.child;

                        for(; child!=null; child=child.next)
                        {
                            CTABLE ct1=child.ct;
                            if(ct1.ll.phi-epsilon>input.phi||
                                ct1.ll.lam-epsilon>input.lam||
                                ct1.ll.phi+(ct1.lim.phi-1)*ct1.del.phi+epsilon<input.phi||
                                ct1.ll.lam+(ct1.lim.lam-1)*ct1.del.lam+epsilon<input.lam) continue;

                            break;
                        }

                        // If we didn't find a child then nothing more to do,
                        if(child==null) break;

                        // otherwise use the child, first checking it's children.
                        gi=child;
                        ct=child.ct;
                    }

                    // load the grid shift info if we don't have it.
                    if(ct.cvs==null&&!pj_gridinfo_load(ctx, gi))
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return -38;
                    }

                    output=nad_cvt(input, inverse, ct);
                    if(output.lam!=Libc.HUGE_VAL)
                    {
                        if(debug_count_apply_gridshift_3++<20) Proj.pj_log(ctx, PJ_LOG.DEBUG_MINOR, "pj_apply_gridshift(): used {0}", ct.id);
                        break;
                    }
                }

                if(output.lam==Libc.HUGE_VAL)
                {
                    if(ctx.debug_level>=PJ_LOG.DEBUG_MAJOR)
                    {
                        Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for\n\t\t\tlocation ({0}dW,{1}dN)", x[io]*Proj.RAD_TO_DEG, y[io]*Proj.RAD_TO_DEG);
                        for(itable=0; itable<grid_count; itable++)
                        {
                            PJ_GRIDINFO gi=tables[itable];
                            if(itable==0) Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "   tried: {0}", gi.gridname);
                            else Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, ",{0}", gi.gridname);
                        }
                    }

                    // We don't actually have any machinery currently to set the
                    // following macro, so this is mostly kept here to make it clear
                    // how we ought to operate if we wanted to make it super clear
                    // that an error has occured when points are outside our available
                    // datum shift areas. But if this is on, we will find that "low
                    // value" points on the fringes of some datasets will completely
                    // fail causing lots of problems when it is more or less ok to
                    // just not apply a datum shift. So rather than deal with
                    // that we just fallback to no shift. (see also bug #45).
            #if ERR_GRID_AREA_TRANSIENT_SEVERE
                    y[io]=Libc.HUGE_VAL;
                    x[io]=Libc.HUGE_VAL;
            #else
                    // leave x/y unshifted.
            #endif
                }
                else
                {
                    y[io]=output.phi;
                    x[io]=output.lam;
                }
            }

            return 0;
        }
Example #13
0
        static int debug_count_apply_gridshift_3 = 0;       // TODO
        public static int pj_apply_gridshift_3(projCtx ctx, PJ_GRIDINFO[] tables, int grid_count, bool inverse, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if (tables == null || grid_count == 0)
            {
                Proj.pj_ctx_set_errno(ctx, -38);
                return(-38);
            }

            ctx.last_errno = 0;

            for (int i = 0; i < point_count; i++)
            {
                long io = i * point_offset;
                LP   input, output;
                int  itable;

                input.phi  = y[io];
                input.lam  = x[io];
                output.phi = Libc.HUGE_VAL;
                output.lam = Libc.HUGE_VAL;

                // keep trying till we find a table that works
                for (itable = 0; itable < grid_count; itable++)
                {
                    PJ_GRIDINFO gi = tables[itable];
                    CTABLE      ct = gi.ct;

                    double epsilon = (Math.Abs(ct.del.phi) + Math.Abs(ct.del.lam)) / 10000.0;

                    // skip tables that don't match our point at all.
                    if (ct.ll.phi - epsilon > input.phi ||
                        ct.ll.lam - epsilon > input.lam ||
                        ct.ll.phi + (ct.lim.phi - 1) * ct.del.phi + epsilon < input.phi ||
                        ct.ll.lam + (ct.lim.lam - 1) * ct.del.lam + epsilon < input.lam)
                    {
                        continue;
                    }

                    // If we have child nodes, check to see if any of them apply.
                    while (gi.child != null)
                    {
                        PJ_GRIDINFO child = gi.child;

                        for (; child != null; child = child.next)
                        {
                            CTABLE ct1 = child.ct;
                            if (ct1.ll.phi - epsilon > input.phi ||
                                ct1.ll.lam - epsilon > input.lam ||
                                ct1.ll.phi + (ct1.lim.phi - 1) * ct1.del.phi + epsilon < input.phi ||
                                ct1.ll.lam + (ct1.lim.lam - 1) * ct1.del.lam + epsilon < input.lam)
                            {
                                continue;
                            }

                            break;
                        }

                        // If we didn't find a child then nothing more to do,
                        if (child == null)
                        {
                            break;
                        }

                        // otherwise use the child, first checking it's children.
                        gi = child;
                        ct = child.ct;
                    }

                    // load the grid shift info if we don't have it.
                    if (ct.cvs == null && !pj_gridinfo_load(ctx, gi))
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(-38);
                    }

                    output = nad_cvt(input, inverse, ct);
                    if (output.lam != Libc.HUGE_VAL)
                    {
                        if (debug_count_apply_gridshift_3++ < 20)
                        {
                            Proj.pj_log(ctx, PJ_LOG.DEBUG_MINOR, "pj_apply_gridshift(): used {0}", ct.id);
                        }
                        break;
                    }
                }

                if (output.lam == Libc.HUGE_VAL)
                {
                    if (ctx.debug_level >= PJ_LOG.DEBUG_MAJOR)
                    {
                        Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for\n\t\t\tlocation ({0}dW,{1}dN)", x[io] * Proj.RAD_TO_DEG, y[io] * Proj.RAD_TO_DEG);
                        for (itable = 0; itable < grid_count; itable++)
                        {
                            PJ_GRIDINFO gi = tables[itable];
                            if (itable == 0)
                            {
                                Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "   tried: {0}", gi.gridname);
                            }
                            else
                            {
                                Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, ",{0}", gi.gridname);
                            }
                        }
                    }

                    // We don't actually have any machinery currently to set the
                    // following macro, so this is mostly kept here to make it clear
                    // how we ought to operate if we wanted to make it super clear
                    // that an error has occured when points are outside our available
                    // datum shift areas. But if this is on, we will find that "low
                    // value" points on the fringes of some datasets will completely
                    // fail causing lots of problems when it is more or less ok to
                    // just not apply a datum shift. So rather than deal with
                    // that we just fallback to no shift. (see also bug #45).
#if ERR_GRID_AREA_TRANSIENT_SEVERE
                    y[io] = Libc.HUGE_VAL;
                    x[io] = Libc.HUGE_VAL;
#else
                    // leave x/y unshifted.
#endif
                }
                else
                {
                    y[io] = output.phi;
                    x[io] = output.lam;
                }
            }

            return(0);
        }
Example #14
0
        //**********************************************************************
        //						pj_gridlist_merge_grid()
        //
        //		Find/load the named gridfile and merge it into the
        //		last_nadgrids_list.
        //**********************************************************************
        static bool pj_gridlist_merge_gridfile(projCtx ctx, string gridname, ref PJ_GRIDINFO[] p_gridlist, ref int p_gridcount, ref int p_gridmax)
        {
            bool        got_match = false;
            PJ_GRIDINFO this_grid, tail = null;

            // --------------------------------------------------------------------
            //		Try to find in the existing list of loaded grids. Add all
            //		matching grids as with NTv2 we can get many grids from one
            //		file (one shared gridname).
            // --------------------------------------------------------------------
            for (this_grid = grid_list; this_grid != null; this_grid = this_grid.next)
            {
                if (this_grid.gridname == gridname)
                {
                    got_match = true;

                    // dont add to the list if it is invalid.
                    if (this_grid.ct == null)
                    {
                        return(false);
                    }

                    // do we need to grow the list?
                    if (p_gridcount >= p_gridmax - 2)
                    {
                        PJ_GRIDINFO[] new_list;
                        int           new_max = p_gridmax + 20;

                        new_list = new PJ_GRIDINFO[new_max];
                        if (p_gridlist != null)
                        {
                            Array.Copy(p_gridlist, new_list, p_gridmax);
                            p_gridlist = null;
                        }

                        p_gridlist = new_list;
                        p_gridmax  = new_max;
                    }

                    // add to the list
                    p_gridlist[p_gridcount++] = this_grid;
                    p_gridlist[p_gridcount]   = null;
                }

                tail = this_grid;
            }

            if (got_match)
            {
                return(true);
            }

            // --------------------------------------------------------------------
            //		Try to load the named grid.
            // --------------------------------------------------------------------
            this_grid = pj_gridinfo_init(ctx, gridname);

            // we should get at least a stub grid with a missing "ct" member
            if (this_grid == null)
            {
                return(false);
            }

            if (tail != null)
            {
                tail.next = this_grid;
            }
            else
            {
                grid_list = this_grid;
            }

            // --------------------------------------------------------------------
            //		Recurse to add the grid now that it is loaded.
            // --------------------------------------------------------------------
            return(pj_gridlist_merge_gridfile(ctx, gridname, ref p_gridlist, ref p_gridcount, ref p_gridmax));
        }
Example #15
0
        public static int pj_apply_vgridshift(PJ defn, string listname, ref PJ_GRIDINFO[] gridlist_p, ref int gridlist_count_p, bool inverse, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            if(gridlist_p==null)
            {
                gridlist_p=pj_gridlist_from_nadgrids(Proj.pj_get_ctx(defn), Proj.pj_param_s(defn.ctx, defn.parameters, listname), out gridlist_count_p);
                if(gridlist_p==null||gridlist_count_p==0) return defn.ctx.last_errno;
            }

            if(gridlist_p==null||gridlist_count_p==0)
            {
                Proj.pj_ctx_set_errno(defn.ctx, -38);
                return -38;
            }

            PJ_GRIDINFO[] tables=gridlist_p;
            defn.ctx.last_errno=0;

            for(int i=0; i<point_count; i++)
            {
                int io=i*point_offset;
                double value=Libc.HUGE_VAL;

                LP input;
                input.phi=y[io];
                input.lam=x[io];

                // keep trying till we find a table that works
                for(int itable=0; itable<gridlist_count_p; itable++)
                {
                    PJ_GRIDINFO gi=tables[itable];
                    CTABLE ct=gi.ct;
                    double grid_x, grid_y;
                    int grid_ix, grid_iy;

                    // skip tables that don't match our point at all.
                    if(ct.ll.phi>input.phi||ct.ll.lam>input.lam||ct.ll.phi+(ct.lim.phi-1)*ct.del.phi<input.phi||ct.ll.lam+(ct.lim.lam-1)*ct.del.lam<input.lam)
                        continue;

                    // If we have child nodes, check to see if any of them apply.
                    while(gi.child!=null)
                    {
                        PJ_GRIDINFO child=gi.child;

                        for(; child!=null; child=child.next)
                        {
                            CTABLE ct1=child.ct;

                            if(ct1.ll.phi>input.phi||ct1.ll.lam>input.lam||ct1.ll.phi+(ct1.lim.phi-1)*ct1.del.phi<input.phi||ct1.ll.lam+(ct1.lim.lam-1)*ct1.del.lam<input.lam)
                                continue;

                            break;
                        }

                        // If we didn't find a child then nothing more to do,
                        if(child==null) break;

                        // otherwise use the child, first checking it's children.
                        gi=child;
                        ct=child.ct;
                    }

                    // load the grid shift info if we don't have it.
                    if(ct.cvs==null&&!pj_gridinfo_load(Proj.pj_get_ctx(defn), gi))
                    {
                        Proj.pj_ctx_set_errno(defn.ctx, -38);
                        return -38;
                    }

                    // Interpolation a location within the grid
                    grid_x=(input.lam-ct.ll.lam)/ct.del.lam;
                    grid_y=(input.phi-ct.ll.phi)/ct.del.phi;
                    grid_ix=(int)Math.Floor(grid_x);
                    grid_iy=(int)Math.Floor(grid_y);
                    grid_x-=grid_ix;
                    grid_y-=grid_iy;

                    LP cvs1=ct.cvs[(grid_ix+grid_iy*ct.lim.lam)/2];
                    LP cvs2=ct.cvs[(grid_ix+(grid_iy+1)*ct.lim.lam)/2];
                    value=cvs1.lam*(1.0-grid_x)*(1.0-grid_y)+cvs1.phi*grid_x*(1.0-grid_y)+
                            cvs2.lam*(1.0-grid_x)*grid_y+cvs2.phi*grid_x*grid_y;

                    if(Math.Abs(value+88.8888)<0.0001) value=Libc.HUGE_VAL; // nodata?
                    else
                    {
                        if(inverse) z[io]-=value;
                        else z[io]+=value;
                    }

                    if(value!=Libc.HUGE_VAL)
                    {
                        if(debug_count_apply_vgridshift++<20) Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MINOR, "pj_apply_gridshift(): used {0}", ct.id);
                        break;
                    }
                }

                if(value==Libc.HUGE_VAL)
                {
                    Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_vgridshift(): failed to find a grid shift table for\n\t\t\tlocation ({0}dW,{1}dN)", x[io]*Proj.RAD_TO_DEG, y[io]*Proj.RAD_TO_DEG);
                    StringBuilder gridlist=new StringBuilder();
                    for(int itable=0; itable<gridlist_count_p; itable++)
                    {
                        PJ_GRIDINFO gi=tables[itable];
                        if(itable==0) gridlist.AppendFormat("   tried: {0}", gi.gridname);
                        else gridlist.AppendFormat(",{0}", gi.gridname);
                    }
                    Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "{0}", gridlist.ToString());

                    Proj.pj_ctx_set_errno(defn.ctx, (int)PJD_ERR.GRID_AREA);
                    return (int)PJD_ERR.GRID_AREA;
                }
            }

            return 0;
        }
Example #16
0
        //**********************************************************************
        //                            pj_gridinfo_load()
        //
        //        This function is intended to implement delayed loading of
        //        the data contents of a grid file. The header and related
        //        stuff are loaded by pj_gridinfo_init().
        //**********************************************************************
        public static bool pj_gridinfo_load(projCtx ctx, PJ_GRIDINFO gi)
        {
            if(gi==null||gi.ct==null) return false;

            lock(gridlock)
            {
                if(gi.ct.cvs!=null) return true;

                CTABLE ct_tmp=gi.ct.Clone();

                // --------------------------------------------------------------------
                //		Original platform specific CTable format.
                // --------------------------------------------------------------------
                if(gi.format=="ctable")
                {
                    FileStream fid=Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if(fid==null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    bool result=nad_ctable_load(ctx, ct_tmp, fid);

                    fid.Close();

                    gi.ct.cvs=ct_tmp.cvs;

                    return result;
                }
                // --------------------------------------------------------------------
                //		CTable2 format.
                // --------------------------------------------------------------------
                else if(gi.format=="ctable2")
                {
                    FileStream fid=Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if(fid==null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    bool result=nad_ctable2_load(ctx, ct_tmp, fid);

                    fid.Close();

                    gi.ct.cvs=ct_tmp.cvs;

                    return result;
                }

                // --------------------------------------------------------------------
                //		NTv1 format.
                //		We process one line at a time. Note that the array storage
                //		direction (e-w) is different in the NTv1 file and what
                //		the CTABLE is supposed to have. The phi/lam are also
                //		reversed, and we have to be aware of byte swapping.
                // --------------------------------------------------------------------
                if(gi.format=="ntv1")
                {
                    FileStream fid=Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);

                    if(fid==null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] row_buf;
                    try
                    {
                        row_buf=new byte[gi.ct.lim.lam*2*sizeof(double)];
                        ct_tmp.cvs=new LP[gi.ct.lim.lam*gi.ct.lim.phi];
                    }
                    catch
                    {
                        row_buf=null;
                        ct_tmp.cvs=null;

                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    for(int row=0; row<gi.ct.lim.phi; row++)
                    {
                        try
                        {
                            if(fid.Read(row_buf, 0, gi.ct.lim.lam*2*sizeof(double))!=gi.ct.lim.lam*2*sizeof(double))
                            {
                                row_buf=null;
                                ct_tmp.cvs=null;

                                Proj.pj_ctx_set_errno(ctx, -38);
                                return false;
                            }
                        }
                        catch
                        {
                            row_buf=null;
                            ct_tmp.cvs=null;

                            Proj.pj_ctx_set_errno(ctx, -38);
                            return false;
                        }

                        if(IS_LSB) swap_words(row_buf, 8, gi.ct.lim.lam*2);

                        // convert seconds to radians
                        int diff_seconds=0;

                        for(int i=0; i<gi.ct.lim.lam; i++)
                        {
                            int cvs=row*gi.ct.lim.lam+(gi.ct.lim.lam-i-1);

                            ct_tmp.cvs[cvs].phi=BitConverter.ToDouble(row_buf, (diff_seconds++)*sizeof(double))*((Proj.PI/180.0)/3600.0);
                            ct_tmp.cvs[cvs].lam=BitConverter.ToDouble(row_buf, (diff_seconds++)*sizeof(double))*((Proj.PI/180.0)/3600.0);
                        }
                    }

                    row_buf=null;

                    fid.Close();

                    gi.ct.cvs=ct_tmp.cvs;

                    return true;
                }

                // --------------------------------------------------------------------
                //		NTv2 format.
                //		We process one line at a time. Note that the array storage
                //		direction (e-w) is different in the NTv2 file and what
                //		the CTABLE is supposed to have. The phi/lam are also
                //		reversed, and we have to be aware of byte swapping.
                // --------------------------------------------------------------------
                if(gi.format=="ntv2")
                {
            #if DEBUG
                    Console.Error.WriteLine("NTv2 - loading grid "+gi.ct.id);
            #endif

                    FileStream fid=Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);

                    if(fid==null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] row_buf;
                    try
                    {
                        row_buf=new byte[gi.ct.lim.lam*4*sizeof(float)];
                        ct_tmp.cvs=new LP[gi.ct.lim.lam*gi.ct.lim.phi];
                    }
                    catch
                    {
                        row_buf=null;
                        ct_tmp.cvs=null;

                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    for(int row=0; row<gi.ct.lim.phi; row++)
                    {
                        try
                        {
                            if(fid.Read(row_buf, 0, gi.ct.lim.lam*4*sizeof(float))!=gi.ct.lim.lam*4*sizeof(float))
                            {
                                row_buf=null;
                                ct_tmp.cvs=null;

                                Proj.pj_ctx_set_errno(ctx, -38);
                                return false;
                            }
                        }
                        catch
                        {
                            row_buf=null;
                            ct_tmp.cvs=null;

                            Proj.pj_ctx_set_errno(ctx, -38);
                            return false;
                        }

                        if(!IS_LSB) swap_words(row_buf, 4, gi.ct.lim.lam*4);

                        // convert seconds to radians
                        int diff_seconds=0;

                        for(int i=0; i<gi.ct.lim.lam; i++)
                        {
                            int cvs=row*gi.ct.lim.lam+(gi.ct.lim.lam-i-1);

                            ct_tmp.cvs[cvs].phi=BitConverter.ToSingle(row_buf, (diff_seconds++)*sizeof(float))*((Proj.PI/180.0)/3600.0);
                            ct_tmp.cvs[cvs].lam=BitConverter.ToSingle(row_buf, (diff_seconds++)*sizeof(float))*((Proj.PI/180.0)/3600.0);
                            diff_seconds+=2; // skip accuracy values
                        }
                    }

                    row_buf=null;

                    fid.Close();

                    gi.ct.cvs=ct_tmp.cvs;

                    return true;
                }

                // --------------------------------------------------------------------
                //		GTX format.
                // --------------------------------------------------------------------
                if(gi.format=="gtx")
                {
                    int words=gi.ct.lim.lam*gi.ct.lim.phi;
                    FileStream fid=Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if(fid==null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] buf;

                    try
                    {
                        buf=new byte[words*sizeof(float)];
                        ct_tmp.cvs=new LP[words/2];
                    }
                    catch
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }

                    try
                    {
                        if(fid.Read(buf, 0, words*sizeof(float))!=words*sizeof(float))
                        {
                            buf=null;
                            ct_tmp.cvs=null;
                            return false;
                        }
                    }
                    catch
                    {
                        buf=null;
                        ct_tmp.cvs=null;
                        return false;
                    }

                    if(IS_LSB) swap_words(buf, 4, words);

                    for(int i=0; i<words; i+=2)
                    {
                        ct_tmp.cvs[i/2].phi=BitConverter.ToSingle(buf, i*sizeof(float));
                        ct_tmp.cvs[i/2].lam=BitConverter.ToSingle(buf, (i+1)*sizeof(float));
                    }

                    fid.Close();

                    gi.ct.cvs=ct_tmp.cvs;

                    return true;
                }

                return false;
            } // lock(gridlock)
        }
Example #17
0
        //**********************************************************************
        //							pj_gridinfo_load()
        //
        //		This function is intended to implement delayed loading of
        //		the data contents of a grid file. The header and related
        //		stuff are loaded by pj_gridinfo_init().
        //**********************************************************************
        public static bool pj_gridinfo_load(projCtx ctx, PJ_GRIDINFO gi)
        {
            if (gi == null || gi.ct == null)
            {
                return(false);
            }

            lock (gridlock)
            {
                if (gi.ct.cvs != null)
                {
                    return(true);
                }

                CTABLE ct_tmp = gi.ct.Clone();

                // --------------------------------------------------------------------
                //		Original platform specific CTable format.
                // --------------------------------------------------------------------
                if (gi.format == "ctable")
                {
                    FileStream fid = Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if (fid == null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    bool result = nad_ctable_load(ctx, ct_tmp, fid);

                    fid.Close();

                    gi.ct.cvs = ct_tmp.cvs;

                    return(result);
                }
                // --------------------------------------------------------------------
                //		CTable2 format.
                // --------------------------------------------------------------------
                else if (gi.format == "ctable2")
                {
                    FileStream fid = Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if (fid == null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    bool result = nad_ctable2_load(ctx, ct_tmp, fid);

                    fid.Close();

                    gi.ct.cvs = ct_tmp.cvs;

                    return(result);
                }

                // --------------------------------------------------------------------
                //		NTv1 format.
                //		We process one line at a time. Note that the array storage
                //		direction (e-w) is different in the NTv1 file and what
                //		the CTABLE is supposed to have. The phi/lam are also
                //		reversed, and we have to be aware of byte swapping.
                // --------------------------------------------------------------------
                if (gi.format == "ntv1")
                {
                    FileStream fid = Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);

                    if (fid == null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] row_buf;
                    try
                    {
                        row_buf    = new byte[gi.ct.lim.lam * 2 * sizeof(double)];
                        ct_tmp.cvs = new LP[gi.ct.lim.lam * gi.ct.lim.phi];
                    }
                    catch
                    {
                        row_buf    = null;
                        ct_tmp.cvs = null;

                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    for (int row = 0; row < gi.ct.lim.phi; row++)
                    {
                        try
                        {
                            if (fid.Read(row_buf, 0, gi.ct.lim.lam * 2 * sizeof(double)) != gi.ct.lim.lam * 2 * sizeof(double))
                            {
                                row_buf    = null;
                                ct_tmp.cvs = null;

                                Proj.pj_ctx_set_errno(ctx, -38);
                                return(false);
                            }
                        }
                        catch
                        {
                            row_buf    = null;
                            ct_tmp.cvs = null;

                            Proj.pj_ctx_set_errno(ctx, -38);
                            return(false);
                        }

                        if (IS_LSB)
                        {
                            swap_words(row_buf, 8, gi.ct.lim.lam * 2);
                        }

                        // convert seconds to radians
                        int diff_seconds = 0;

                        for (int i = 0; i < gi.ct.lim.lam; i++)
                        {
                            int cvs = row * gi.ct.lim.lam + (gi.ct.lim.lam - i - 1);

                            ct_tmp.cvs[cvs].phi = BitConverter.ToDouble(row_buf, (diff_seconds++) * sizeof(double)) * ((Proj.PI / 180.0) / 3600.0);
                            ct_tmp.cvs[cvs].lam = BitConverter.ToDouble(row_buf, (diff_seconds++) * sizeof(double)) * ((Proj.PI / 180.0) / 3600.0);
                        }
                    }

                    row_buf = null;

                    fid.Close();

                    gi.ct.cvs = ct_tmp.cvs;

                    return(true);
                }

                // --------------------------------------------------------------------
                //		NTv2 format.
                //		We process one line at a time. Note that the array storage
                //		direction (e-w) is different in the NTv2 file and what
                //		the CTABLE is supposed to have. The phi/lam are also
                //		reversed, and we have to be aware of byte swapping.
                // --------------------------------------------------------------------
                if (gi.format == "ntv2")
                {
#if DEBUG
                    Console.Error.WriteLine("NTv2 - loading grid " + gi.ct.id);
#endif

                    FileStream fid = Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);

                    if (fid == null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] row_buf;
                    try
                    {
                        row_buf    = new byte[gi.ct.lim.lam * 4 * sizeof(float)];
                        ct_tmp.cvs = new LP[gi.ct.lim.lam * gi.ct.lim.phi];
                    }
                    catch
                    {
                        row_buf    = null;
                        ct_tmp.cvs = null;

                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    for (int row = 0; row < gi.ct.lim.phi; row++)
                    {
                        try
                        {
                            if (fid.Read(row_buf, 0, gi.ct.lim.lam * 4 * sizeof(float)) != gi.ct.lim.lam * 4 * sizeof(float))
                            {
                                row_buf    = null;
                                ct_tmp.cvs = null;

                                Proj.pj_ctx_set_errno(ctx, -38);
                                return(false);
                            }
                        }
                        catch
                        {
                            row_buf    = null;
                            ct_tmp.cvs = null;

                            Proj.pj_ctx_set_errno(ctx, -38);
                            return(false);
                        }

                        if (!IS_LSB)
                        {
                            swap_words(row_buf, 4, gi.ct.lim.lam * 4);
                        }

                        // convert seconds to radians
                        int diff_seconds = 0;

                        for (int i = 0; i < gi.ct.lim.lam; i++)
                        {
                            int cvs = row * gi.ct.lim.lam + (gi.ct.lim.lam - i - 1);

                            ct_tmp.cvs[cvs].phi = BitConverter.ToSingle(row_buf, (diff_seconds++) * sizeof(float)) * ((Proj.PI / 180.0) / 3600.0);
                            ct_tmp.cvs[cvs].lam = BitConverter.ToSingle(row_buf, (diff_seconds++) * sizeof(float)) * ((Proj.PI / 180.0) / 3600.0);
                            diff_seconds       += 2;                     // skip accuracy values
                        }
                    }

                    row_buf = null;

                    fid.Close();

                    gi.ct.cvs = ct_tmp.cvs;

                    return(true);
                }

                // --------------------------------------------------------------------
                //		GTX format.
                // --------------------------------------------------------------------
                if (gi.format == "gtx")
                {
                    int        words = gi.ct.lim.lam * gi.ct.lim.phi;
                    FileStream fid   = Proj.pj_open_lib(ctx, gi.filename, FileAccess.Read);
                    if (fid == null)
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    fid.Seek(gi.grid_offset, SeekOrigin.Begin);

                    byte[] buf;

                    try
                    {
                        buf        = new byte[words * sizeof(float)];
                        ct_tmp.cvs = new LP[words / 2];
                    }
                    catch
                    {
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }

                    try
                    {
                        if (fid.Read(buf, 0, words * sizeof(float)) != words * sizeof(float))
                        {
                            buf        = null;
                            ct_tmp.cvs = null;
                            return(false);
                        }
                    }
                    catch
                    {
                        buf        = null;
                        ct_tmp.cvs = null;
                        return(false);
                    }

                    if (IS_LSB)
                    {
                        swap_words(buf, 4, words);
                    }

                    for (int i = 0; i < words; i += 2)
                    {
                        ct_tmp.cvs[i / 2].phi = BitConverter.ToSingle(buf, i * sizeof(float));
                        ct_tmp.cvs[i / 2].lam = BitConverter.ToSingle(buf, (i + 1) * sizeof(float));
                    }

                    fid.Close();

                    gi.ct.cvs = ct_tmp.cvs;

                    return(true);
                }

                return(false);
            }             // lock(gridlock)
        }
Example #18
0
        //**********************************************************************
        //                        pj_gridinfo_init_ntv1()
        //
        //        Load an NTv1 style Canadian grid shift file.
        //**********************************************************************
        static bool pj_gridinfo_init_ntv1(projCtx ctx, FileStream fid, PJ_GRIDINFO gi)
        {
            byte[] header=new byte[176];

            // --------------------------------------------------------------------
            //		Read the header.
            // --------------------------------------------------------------------
            try
            {
                if(fid.Read(header, 0, header.Length)!=header.Length)
                {
                    header=null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return false;
                }
            }
            catch
            {
                header=null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return false;
            }

            // --------------------------------------------------------------------
            //		Regularize fields of interest.
            // --------------------------------------------------------------------
            if(IS_LSB)
            {
                swap_words(header, 8, 4, 1);
                swap_words(header, 24, 8, 1);
                swap_words(header, 40, 8, 1);
                swap_words(header, 56, 8, 1);
                swap_words(header, 72, 8, 1);
                swap_words(header, 88, 8, 1);
                swap_words(header, 104, 8, 1);
            }

            if(BitConverter.ToInt32(header, 8)!=12)
            {
                Console.Error.WriteLine("NTv1 grid shift file has wrong record count, corrupt?");
                Proj.pj_ctx_set_errno(ctx, -38);
                return false;
            }

            // --------------------------------------------------------------------
            //		Fill in CTABLE structure.
            // --------------------------------------------------------------------
            CTABLE ct=new CTABLE();
            ct.id="NTv1 Grid Shift File";

            ct.ll.lam=-BitConverter.ToDouble(header, 72);
            ct.ll.phi=BitConverter.ToDouble(header, 24);

            LP ur;
            ur.lam=-BitConverter.ToDouble(header, 56);
            ur.phi=BitConverter.ToDouble(header, 40);

            ct.del.lam=BitConverter.ToDouble(header, 104);
            ct.del.phi=BitConverter.ToDouble(header, 88);

            ct.lim.lam=(int)(Math.Abs(ur.lam-ct.ll.lam)/ct.del.lam+0.5)+1;
            ct.lim.phi=(int)(Math.Abs(ur.phi-ct.ll.phi)/ct.del.phi+0.5)+1;

            #if DEBUG
            Console.Error.WriteLine("NTv1 {0}x{1}: LL=({2},{3}) UR=({4},{5})",
                ct.lim.lam, ct.lim.phi, ct.ll.lam, ct.ll.phi, ur.lam, ur.phi);
            #endif

            ct.ll.lam*=Proj.DEG_TO_RAD;
            ct.ll.phi*=Proj.DEG_TO_RAD;
            ct.del.lam*=Proj.DEG_TO_RAD;
            ct.del.phi*=Proj.DEG_TO_RAD;
            ct.cvs=null;

            gi.ct=ct;
            gi.grid_offset=fid.Position;
            gi.format="ntv1";

            return true;
        }
Example #19
0
        //**********************************************************************
        //						pj_gridinfo_init_ntv2()
        //
        //		Load a ntv2 (.gsb) file.
        //**********************************************************************
        static bool pj_gridinfo_init_ntv2(projCtx ctx, FileStream fid, PJ_GRIDINFO gilist)
        {
            byte[] header = new byte[11 * 16];

            // --------------------------------------------------------------------
            //		Read the overview header.
            // --------------------------------------------------------------------
            try
            {
                if (fid.Read(header, 0, header.Length) != header.Length)
                {
                    header = null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(false);
                }
            }
            catch
            {
                header = null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return(false);
            }

            // --------------------------------------------------------------------
            //		Byte swap interesting fields if needed.
            // --------------------------------------------------------------------
            if (!IS_LSB)
            {
                swap_words(header, 8, 4, 1);
                swap_words(header, 8 + 16, 4, 1);
                swap_words(header, 8 + 32, 4, 1);
                swap_words(header, 8 + 7 * 16, 8, 1);
                swap_words(header, 8 + 8 * 16, 8, 1);
                swap_words(header, 8 + 9 * 16, 8, 1);
                swap_words(header, 8 + 10 * 16, 8, 1);
            }

            // --------------------------------------------------------------------
            //		Get the subfile count out ... all we really use for now.
            // --------------------------------------------------------------------
            int num_subfiles = BitConverter.ToInt32(header, 8 + 32);

            // ====================================================================
            //		Step through the subfiles, creating a PJ_GRIDINFO for each.
            // ====================================================================
            for (int subfile = 0; subfile < num_subfiles; subfile++)
            {
                // --------------------------------------------------------------------
                //		Read header.
                // --------------------------------------------------------------------
                try
                {
                    if (fid.Read(header, 0, header.Length) != header.Length)
                    {
                        header = null;
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return(false);
                    }
                }
                catch
                {
                    header = null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(false);
                }

                if (Encoding.ASCII.GetString(header, 0, 8).StartsWith("SUB_NAME"))
                {
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(false);
                }

                // --------------------------------------------------------------------
                //		Byte swap interesting fields if needed.
                // --------------------------------------------------------------------
                if (!IS_LSB)
                {
                    swap_words(header, 8 + 16 * 4, 8, 1);
                    swap_words(header, 8 + 16 * 5, 8, 1);
                    swap_words(header, 8 + 16 * 6, 8, 1);
                    swap_words(header, 8 + 16 * 7, 8, 1);
                    swap_words(header, +8 + 16 * 8, 8, 1);
                    swap_words(header, 8 + 16 * 9, 8, 1);
                    swap_words(header, 8 + 16 * 10, 4, 1);
                }

                // --------------------------------------------------------------------
                //		Initialize a corresponding "ct" structure.
                // --------------------------------------------------------------------
                CTABLE ct = new CTABLE();
                ct.id = Encoding.ASCII.GetString(header, 8, 8);

                ct.ll.lam = -BitConverter.ToDouble(header, 7 * 16 + 8);                 // W_LONG
                ct.ll.phi = BitConverter.ToDouble(header, 4 * 16 + 8);                  // S_LAT

                LP ur;
                ur.lam = -BitConverter.ToDouble(header, 6 * 16 + 8);                    // E_LONG
                ur.phi = BitConverter.ToDouble(header, 5 * 16 + 8);                     // N_LAT

                ct.del.lam = BitConverter.ToDouble(header, 9 * 16 + 8);
                ct.del.phi = BitConverter.ToDouble(header, 8 * 16 + 8);

                ct.lim.lam = (int)(Math.Abs(ur.lam - ct.ll.lam) / ct.del.lam + 0.5) + 1;
                ct.lim.phi = (int)(Math.Abs(ur.phi - ct.ll.phi) / ct.del.phi + 0.5) + 1;

#if DEBUG
                Console.Error.WriteLine("NTv2 {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})", ct.id,
                                        ct.lim.lam, ct.lim.phi, ct.ll.lam / 3600.0, ct.ll.phi / 3600.0, ur.lam / 3600.0, ur.phi / 3600.0);
#endif

                ct.ll.lam  *= Proj.DEG_TO_RAD / 3600.0;
                ct.ll.phi  *= Proj.DEG_TO_RAD / 3600.0;
                ct.del.lam *= Proj.DEG_TO_RAD / 3600.0;
                ct.del.phi *= Proj.DEG_TO_RAD / 3600.0;

                int gs_count = BitConverter.ToInt32(header, 8 + 16 * 10);
                if (gs_count != ct.lim.lam * ct.lim.phi)
                {
                    Console.Error.WriteLine("GS_COUNT({0}) does not match expected cells ({1}x{2}={3})",
                                            gs_count, ct.lim.lam, ct.lim.phi, ct.lim.lam * ct.lim.phi);
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(false);
                }

                ct.cvs = null;

                PJ_GRIDINFO gi;

                // --------------------------------------------------------------------
                //		Create a new gridinfo for this if we aren't processing the
                //		1st subfile, and initialize our grid info.
                // --------------------------------------------------------------------
                if (subfile == 0)
                {
                    gi = gilist;
                }
                else
                {
                    gi          = new PJ_GRIDINFO();
                    gi.gridname = gilist.gridname;
                    gi.filename = gilist.filename;
                    gi.next     = null;
                }

                gi.ct          = ct;
                gi.format      = "ntv2";
                gi.grid_offset = fid.Position;

                // --------------------------------------------------------------------
                //		Attach to the correct list or sublist.
                // --------------------------------------------------------------------
                if (Encoding.ASCII.GetString(header, 24, 4) == "NONE")
                {
                    if (gi != gilist)
                    {
                        PJ_GRIDINFO lnk = gilist;
                        while (lnk.next != null)
                        {
                            lnk = lnk.next;
                        }
                        lnk.next = gi;
                    }
                }
                else
                {
                    PJ_GRIDINFO gp = pj_gridinfo_parent(gilist, Encoding.ASCII.GetString(header, 24, 8));

                    if (gp == null)
                    {
#if DEBUG
                        Console.Error.WriteLine("pj_gridinfo_init_ntv2(): failed to find parent {0} for {1}.",
                                                Encoding.ASCII.GetString(header, 24, 8), gi.ct.id);
#endif

                        PJ_GRIDINFO lnk = gilist;
                        while (lnk.next != null)
                        {
                            lnk = lnk.next;
                        }
                        lnk.next = gi;
                    }
                    else if (gp.child == null)
                    {
                        gp.child = gi;
                    }
                    else
                    {
                        PJ_GRIDINFO lnk = gp.child;
                        while (lnk.next != null)
                        {
                            lnk = lnk.next;
                        }
                        lnk.next = gi;
                    }
                }

                // --------------------------------------------------------------------
                //		Seek past the data.
                // --------------------------------------------------------------------
                fid.Seek(gs_count * 16, SeekOrigin.Current);
            }

            return(true);
        }
Example #20
0
        //**********************************************************************
        //                        pj_gridinfo_init_ntv2()
        //
        //        Load a ntv2 (.gsb) file.
        //**********************************************************************
        static bool pj_gridinfo_init_ntv2(projCtx ctx, FileStream fid, PJ_GRIDINFO gilist)
        {
            byte[] header=new byte[11*16];

            // --------------------------------------------------------------------
            //		Read the overview header.
            // --------------------------------------------------------------------
            try
            {
                if(fid.Read(header, 0, header.Length)!=header.Length)
                {
                    header=null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return false;
                }
            }
            catch
            {
                header=null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return false;
            }

            // --------------------------------------------------------------------
            //		Byte swap interesting fields if needed.
            // --------------------------------------------------------------------
            if(!IS_LSB)
            {
                swap_words(header, 8, 4, 1);
                swap_words(header, 8+16, 4, 1);
                swap_words(header, 8+32, 4, 1);
                swap_words(header, 8+7*16, 8, 1);
                swap_words(header, 8+8*16, 8, 1);
                swap_words(header, 8+9*16, 8, 1);
                swap_words(header, 8+10*16, 8, 1);
            }

            // --------------------------------------------------------------------
            //		Get the subfile count out ... all we really use for now.
            // --------------------------------------------------------------------
            int num_subfiles=BitConverter.ToInt32(header, 8+32);

            // ====================================================================
            //		Step through the subfiles, creating a PJ_GRIDINFO for each.
            // ====================================================================
            for(int subfile=0; subfile<num_subfiles; subfile++)
            {
                // --------------------------------------------------------------------
                //		Read header.
                // --------------------------------------------------------------------
                try
                {
                    if(fid.Read(header, 0, header.Length)!=header.Length)
                    {
                        header=null;
                        Proj.pj_ctx_set_errno(ctx, -38);
                        return false;
                    }
                }
                catch
                {
                    header=null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return false;
                }

                if(Encoding.ASCII.GetString(header, 0, 8).StartsWith("SUB_NAME"))
                {
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return false;
                }

                // --------------------------------------------------------------------
                //		Byte swap interesting fields if needed.
                // --------------------------------------------------------------------
                if(!IS_LSB)
                {
                    swap_words(header, 8+16*4, 8, 1);
                    swap_words(header, 8+16*5, 8, 1);
                    swap_words(header, 8+16*6, 8, 1);
                    swap_words(header, 8+16*7, 8, 1);
                    swap_words(header, +8+16*8, 8, 1);
                    swap_words(header, 8+16*9, 8, 1);
                    swap_words(header, 8+16*10, 4, 1);
                }

                // --------------------------------------------------------------------
                //		Initialize a corresponding "ct" structure.
                // --------------------------------------------------------------------
                CTABLE ct=new CTABLE();
                ct.id=Encoding.ASCII.GetString(header, 8, 8);

                ct.ll.lam=-BitConverter.ToDouble(header, 7*16+8);	// W_LONG
                ct.ll.phi=BitConverter.ToDouble(header, 4*16+8);	// S_LAT

                LP ur;
                ur.lam=-BitConverter.ToDouble(header, 6*16+8);		// E_LONG
                ur.phi=BitConverter.ToDouble(header, 5*16+8);		// N_LAT

                ct.del.lam=BitConverter.ToDouble(header, 9*16+8);
                ct.del.phi=BitConverter.ToDouble(header, 8*16+8);

                ct.lim.lam=(int)(Math.Abs(ur.lam-ct.ll.lam)/ct.del.lam+0.5)+1;
                ct.lim.phi=(int)(Math.Abs(ur.phi-ct.ll.phi)/ct.del.phi+0.5)+1;

            #if DEBUG
                Console.Error.WriteLine("NTv2 {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})", ct.id,
                    ct.lim.lam, ct.lim.phi, ct.ll.lam/3600.0, ct.ll.phi/3600.0, ur.lam/3600.0, ur.phi/3600.0);
            #endif

                ct.ll.lam*=Proj.DEG_TO_RAD/3600.0;
                ct.ll.phi*=Proj.DEG_TO_RAD/3600.0;
                ct.del.lam*=Proj.DEG_TO_RAD/3600.0;
                ct.del.phi*=Proj.DEG_TO_RAD/3600.0;

                int gs_count=BitConverter.ToInt32(header, 8+16*10);
                if(gs_count!=ct.lim.lam*ct.lim.phi)
                {
                    Console.Error.WriteLine("GS_COUNT({0}) does not match expected cells ({1}x{2}={3})",
                        gs_count, ct.lim.lam, ct.lim.phi, ct.lim.lam*ct.lim.phi);
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return false;
                }

                ct.cvs=null;

                PJ_GRIDINFO gi;

                // --------------------------------------------------------------------
                //		Create a new gridinfo for this if we aren't processing the
                //		1st subfile, and initialize our grid info.
                // --------------------------------------------------------------------
                if(subfile==0) gi=gilist;
                else
                {
                    gi=new PJ_GRIDINFO();
                    gi.gridname=gilist.gridname;
                    gi.filename=gilist.filename;
                    gi.next=null;
                }

                gi.ct=ct;
                gi.format="ntv2";
                gi.grid_offset=fid.Position;

                // --------------------------------------------------------------------
                //		Attach to the correct list or sublist.
                // --------------------------------------------------------------------
                if(Encoding.ASCII.GetString(header, 24, 4)=="NONE")
                {
                    if(gi!=gilist)
                    {
                        PJ_GRIDINFO lnk=gilist;
                        while(lnk.next!=null) lnk=lnk.next;
                        lnk.next=gi;
                    }
                }
                else
                {
                    PJ_GRIDINFO gp=pj_gridinfo_parent(gilist, Encoding.ASCII.GetString(header, 24, 8));

                    if(gp==null)
                    {
            #if DEBUG
                        Console.Error.WriteLine("pj_gridinfo_init_ntv2(): failed to find parent {0} for {1}.",
                            Encoding.ASCII.GetString(header, 24, 8), gi.ct.id);
            #endif

                        PJ_GRIDINFO lnk=gilist;
                        while(lnk.next!=null) lnk=lnk.next;
                        lnk.next=gi;
                    }
                    else if(gp.child==null) gp.child=gi;
                    else
                    {
                        PJ_GRIDINFO lnk=gp.child;
                        while(lnk.next!=null) lnk=lnk.next;
                        lnk.next=gi;
                    }
                }

                // --------------------------------------------------------------------
                //		Seek past the data.
                // --------------------------------------------------------------------
                fid.Seek(gs_count*16, SeekOrigin.Current);
            }

            return true;
        }
Example #21
0
        //**********************************************************************
        //						pj_gridinfo_init_ntv1()
        //
        //		Load an NTv1 style Canadian grid shift file.
        //**********************************************************************
        static bool pj_gridinfo_init_ntv1(projCtx ctx, FileStream fid, PJ_GRIDINFO gi)
        {
            byte[] header = new byte[176];

            // --------------------------------------------------------------------
            //		Read the header.
            // --------------------------------------------------------------------
            try
            {
                if (fid.Read(header, 0, header.Length) != header.Length)
                {
                    header = null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return(false);
                }
            }
            catch
            {
                header = null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return(false);
            }

            // --------------------------------------------------------------------
            //		Regularize fields of interest.
            // --------------------------------------------------------------------
            if (IS_LSB)
            {
                swap_words(header, 8, 4, 1);
                swap_words(header, 24, 8, 1);
                swap_words(header, 40, 8, 1);
                swap_words(header, 56, 8, 1);
                swap_words(header, 72, 8, 1);
                swap_words(header, 88, 8, 1);
                swap_words(header, 104, 8, 1);
            }

            if (BitConverter.ToInt32(header, 8) != 12)
            {
                Console.Error.WriteLine("NTv1 grid shift file has wrong record count, corrupt?");
                Proj.pj_ctx_set_errno(ctx, -38);
                return(false);
            }

            // --------------------------------------------------------------------
            //		Fill in CTABLE structure.
            // --------------------------------------------------------------------
            CTABLE ct = new CTABLE();

            ct.id = "NTv1 Grid Shift File";

            ct.ll.lam = -BitConverter.ToDouble(header, 72);
            ct.ll.phi = BitConverter.ToDouble(header, 24);

            LP ur;

            ur.lam = -BitConverter.ToDouble(header, 56);
            ur.phi = BitConverter.ToDouble(header, 40);

            ct.del.lam = BitConverter.ToDouble(header, 104);
            ct.del.phi = BitConverter.ToDouble(header, 88);

            ct.lim.lam = (int)(Math.Abs(ur.lam - ct.ll.lam) / ct.del.lam + 0.5) + 1;
            ct.lim.phi = (int)(Math.Abs(ur.phi - ct.ll.phi) / ct.del.phi + 0.5) + 1;

#if DEBUG
            Console.Error.WriteLine("NTv1 {0}x{1}: LL=({2},{3}) UR=({4},{5})",
                                    ct.lim.lam, ct.lim.phi, ct.ll.lam, ct.ll.phi, ur.lam, ur.phi);
#endif

            ct.ll.lam  *= Proj.DEG_TO_RAD;
            ct.ll.phi  *= Proj.DEG_TO_RAD;
            ct.del.lam *= Proj.DEG_TO_RAD;
            ct.del.phi *= Proj.DEG_TO_RAD;
            ct.cvs      = null;

            gi.ct          = ct;
            gi.grid_offset = fid.Position;
            gi.format      = "ntv1";

            return(true);
        }
Example #22
0
        //**********************************************************************
        //                            pj_gridinfo_init()
        //
        //        Open and parse header details from a datum gridshift file
        //        returning a list of PJ_GRIDINFOs for the grids in that
        //        file. This superceeds use of nad_init() for modern
        //        applications.
        //**********************************************************************
        public static PJ_GRIDINFO pj_gridinfo_init(projCtx ctx, string gridname)
        {
            Libc.errno=Proj.pj_errno=0;
            ctx.last_errno=0;

            // --------------------------------------------------------------------
            //		Initialize a GRIDINFO with stub info we would use if it
            //		cannot be loaded.
            // --------------------------------------------------------------------
            PJ_GRIDINFO gilist=new PJ_GRIDINFO();
            gilist.gridname=gridname;
            gilist.filename=null;
            gilist.format="missing";
            gilist.grid_offset=0;
            gilist.ct=null;
            gilist.next=null;

            // --------------------------------------------------------------------
            //		Open the file using the usual search rules.
            // --------------------------------------------------------------------
            FileStream fp=Proj.pj_open_lib(ctx, gridname, FileAccess.Read);
            if(fp==null)
            {
                Proj.pj_errno=Libc.errno;
                ctx.last_errno=0; // don't treat as a persistent error
                return gilist;
            }

            gilist.filename=gridname;

            // --------------------------------------------------------------------
            //		Load a header, to determine the file type.
            // --------------------------------------------------------------------
            byte[] header=new byte[160];

            try
            {
                if(fp.Read(header, 0, header.Length)!=header.Length)
                {
                    fp.Close();
                    header=null;
                    Proj.pj_ctx_set_errno(ctx, -38);
                    return gilist;
                }
            }
            catch
            {
                fp.Close();
                header=null;
                Proj.pj_ctx_set_errno(ctx, -38);
                return gilist;
            }

            fp.Seek(0, SeekOrigin.Begin);

            // --------------------------------------------------------------------
            //		Determine file type.
            // --------------------------------------------------------------------
            if(Encoding.ASCII.GetString(header, 0, 6)=="HEADER"&&
                Encoding.ASCII.GetString(header, 96, 6)=="W GRID"&&
                Encoding.ASCII.GetString(header, 144, 16)=="TO      NAD83   ")
            {
                pj_gridinfo_init_ntv1(ctx, fp, gilist);
            }
            else if(Encoding.ASCII.GetString(header, 0, 8)=="NUM_OREC"&&
                Encoding.ASCII.GetString(header, 48, 7)=="GS_TYPE")
            {
                pj_gridinfo_init_ntv2(ctx, fp, gilist);
            }
            else if(gridname.Length>4&&gridname.EndsWith("gtx", StringComparison.CurrentCultureIgnoreCase))
            {
                pj_gridinfo_init_gtx(ctx, fp, gilist);
            }
            else if(Encoding.ASCII.GetString(header, 0, 9)=="CTABLE V2")
            {
                CTABLE ct=nad_ctable2_init(ctx, fp);

                gilist.format="ctable2";
                gilist.ct=ct;

                Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "Ctable2 {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})",
                    ct.id, ct.lim.lam, ct.lim.phi, ct.ll.lam*Proj.RAD_TO_DEG, ct.ll.phi*Proj.RAD_TO_DEG,
                    (ct.ll.lam+(ct.lim.lam-1)*ct.del.lam)*Proj.RAD_TO_DEG, (ct.ll.phi+(ct.lim.phi-1)*ct.del.phi)*Proj.RAD_TO_DEG);
            }
            else
            {
                CTABLE ct=nad_ctable_init(ctx, fp);

                if(ct==null)
                {
                    Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "CTABLE ct is NULL.");
                }
                else
                {
                    gilist.format="ctable";
                    gilist.ct=ct;

                    Proj.pj_log(ctx, PJ_LOG.DEBUG_MAJOR, "Ctable {0} {1}x{2}: LL=({3},{4}) UR=({5},{6})",
                        ct.id, ct.lim.lam, ct.lim.phi, ct.ll.lam*Proj.RAD_TO_DEG, ct.ll.phi*Proj.RAD_TO_DEG,
                        (ct.ll.lam+(ct.lim.lam-1)*ct.del.lam)*Proj.RAD_TO_DEG, (ct.ll.phi+(ct.lim.phi-1)*ct.del.phi)*Proj.RAD_TO_DEG);
                }
            }

            fp.Close();

            return gilist;
        }
Example #23
0
        //**********************************************************************
        //						pj_gc_apply_gridshift()
        //**********************************************************************
        public static int pj_gc_apply_gridshift(PJ defn, bool inverse, int point_count, int point_offset, double[] x, double[] y, double[] z)
        {
            int i;

            if (defn.catalog == null)
            {
                defn.catalog = pj_gc_findcatalog(defn.ctx, defn.catalog_name);
                if (defn.catalog == null)
                {
                    return(defn.ctx.last_errno);
                }
            }

            defn.ctx.last_errno = 0;

            for (i = 0; i < point_count; i++)
            {
                long io = i * point_offset;

                LP input;
                input.phi = y[io];
                input.lam = x[io];

                // make sure we have appropriate "after" shift file available
                if (defn.last_after_grid == null ||
                    input.lam < defn.last_after_region.ll_long || input.lam > defn.last_after_region.ur_long ||
                    input.phi < defn.last_after_region.ll_lat || input.phi > defn.last_after_region.ll_lat)
                {
                    defn.last_after_grid = pj_gc_findgrid(defn.ctx, defn.catalog, true, input, defn.datum_date, ref defn.last_after_region, ref defn.last_after_date);
                }

                PJ_GRIDINFO gi = defn.last_after_grid;
                Debug.Assert(gi.child == null);

                // load the grid shift info if we don't have it.
                if (gi.ct.cvs == null && !pj_gridinfo_load(defn.ctx, gi))
                {
                    Proj.pj_ctx_set_errno(defn.ctx, -38);
                    return(-38);
                }

                LP output_after = nad_cvt(input, inverse, gi.ct);
                if (output_after.lam == Libc.HUGE_VAL)
                {
                    if (defn.ctx.debug_level >= PJ_LOG.DEBUG_MAJOR)
                    {
                        Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for");
                        Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "                      location ({0:F7}dW,{1:F7}dN)", x[io] * Proj.RAD_TO_DEG, y[io] * Proj.RAD_TO_DEG);
                    }
                    continue;
                }

                if (defn.datum_date == 0.0)
                {
                    y[io] = output_after.phi;
                    x[io] = output_after.lam;
                    continue;
                }

                // make sure we have appropriate "before" shift file available
                if (defn.last_before_grid == null ||
                    input.lam < defn.last_before_region.ll_long || input.lam > defn.last_before_region.ur_long ||
                    input.phi < defn.last_before_region.ll_lat || input.phi > defn.last_before_region.ll_lat)
                {
                    defn.last_before_grid = pj_gc_findgrid(defn.ctx, defn.catalog, false, input, defn.datum_date, ref defn.last_before_region, ref defn.last_before_date);
                }

                gi = defn.last_before_grid;
                Debug.Assert(gi.child == null);

                // load the grid shift info if we don't have it.
                if (gi.ct.cvs == null && !pj_gridinfo_load(defn.ctx, gi))
                {
                    Proj.pj_ctx_set_errno(defn.ctx, -38);
                    return(-38);
                }

                LP output_before = nad_cvt(input, inverse, gi.ct);
                if (output_before.lam == Libc.HUGE_VAL)
                {
                    if (defn.ctx.debug_level >= PJ_LOG.DEBUG_MAJOR)
                    {
                        Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "pj_apply_gridshift(): failed to find a grid shift table for");
                        Proj.pj_log(defn.ctx, PJ_LOG.DEBUG_MAJOR, "                      location ({0:F7}dW,{1:F7}dN)", x[io] * Proj.RAD_TO_DEG, y[io] * Proj.RAD_TO_DEG);
                    }
                    continue;
                }

                double mix_ratio = (defn.datum_date - defn.last_before_date) / (defn.last_after_date - defn.last_before_date);

                y[io] = mix_ratio * output_after.phi + (1.0 - mix_ratio) * output_before.phi;
                x[io] = mix_ratio * output_after.lam + (1.0 - mix_ratio) * output_before.lam;
            }

            return(0);
        }