** proj ** [swig] based binding for tcl for the proj.4 library using the new API described [https://proj4.org/development/reference/index.html%|%here%|%]. A simple binding to the old API using critcl has been moved to [proj4tcl - deprecated]. *** usage*** Here is the c example from [https://proj4.org/development/quickstart.html%|%proj quick start%|%] ======c #include #include int main (void) { PJ_CONTEXT *C; PJ *P; PJ_COORD a, b; /* or you may set C=PJ_DEFAULT_CTX if you are sure you will */ /* use PJ objects from only one thread */ C = proj_context_create(); P = proj_create (C, "+proj=utm +zone=32 +ellps=GRS80"); if (0==P) return puts ("Oops"), 0; /* a coordinate union representing Copenhagen: 55d N, 12d E */ /* note: PROJ.4 works in radians, hence the proj_torad() calls */ a = proj_coord (proj_torad(12), proj_torad(55), 0, 0); /* transform to UTM zone 32, then back to geographical */ b = proj_trans (P, PJ_FWD, a); printf ("easting: %.3f, northing: %.3f\n", b.enu.e, b.enu.n); b = proj_trans (P, PJ_INV, b); printf ("longitude: %.9f, latitude: %.9f\n", b.lp.lam, b.lp.phi); /* Clean up */ proj_destroy (P); proj_context_destroy (C); /* may be omitted in the single threaded case */ return 0; } ====== and a translation to tcl ======tcl lappend auto_path . package require proj set C [proj_context_create] set p "+proj=utm +zone=32 +ellps=GRS80" set P [proj_create $C $p] set a [proj_coord [proj_torad 12] [proj_torad 55] 0 0 ] set b [proj_trans $P $PJ_FWD $a] puts [format "easting: %.3f, northing: %.3f" \ [PJ_ENU_e_get [PJ_COORD_enu_get $b]] \ [PJ_ENU_n_get [PJ_COORD_enu_get $b]]] set c [proj_trans $P $PJ_INV $b] puts [format "longitude: %.9f, latitude: %.9f" \ [[$c cget -lp] cget -lam] \ [[$c cget -lp] cget -phi]] proj_destroy $P proj_context_destroy $C ====== because of the new union PJ_COORD, getting the result is somewhat verbose. A procedure that converts the union to a list simplifies that. ====== proc proj_list {a} { set t [$a cget -xyzt] return [list \ [$t cget -x] \ [$t cget -y] \ [$t cget -z] \ [$t cget -t] ] } puts [format "easting: %.3f, northing: %.3f" \ {*}[proj_list $b]] puts [format "longitude: %.9f, latitude: %.9f" \ {*}[proj_list $c]] ====== *** swig wrapper *** file: proj.i ====== %module proj %{ #include %} %include ====== *** build *** ****linux**** ====== swig -tcl -pkgversion 1.0 -I/usr/include proj.i gcc -shared -fpic -DUSE_TCL_STUBS proj_wrap.c -o proj.so -ltclstub8.6 -lproj ====== **** windows**** using [http://www.msys2.org/%|%msys2/mingw64%|%] static (tested with [http://www.bawt.tcl3d.org/download/Tcl-BI/SetupTcl-8.6.8-x64_Bawt-0.8.0.exe%|%bawt%|%]) ====== pacman -S base-devel pacboy -S toolchain swig proj tcl swig -tcl -pkgversion 1.0 -I/mingw64/include proj.i gcc -shared -fpic -DUSE_TCL_STUBS proj_wrap.c -o proj.so -L/mingw64/lib -ltclstub86 -l:libproj.a ====== ****both**** file: pkgIndex.tcl ====== package ifneeded proj 1.0 [list load [file join $dir proj.so]] ====== ***bugs*** A number of functions are not supported using this simple wrapper eg ======c PJ *proj_create_argv (PJ_CONTEXT *ctx, int argc, char **argv); int proj_trans_array (PJ *P, PJ_DIRECTION direction, size_t n, PJ_COORD *coord); size_t proj_trans_generic ( PJ *P, PJ_DIRECTION direction, double *x, size_t sx, size_t nx, double *y, size_t sy, size_t ny, double *z, size_t sz, size_t nz, double *t, size_t st, size_t nt ); double proj_roundtrip (PJ *P, PJ_DIRECTION direction, int n, PJ_COORD *coord); void proj_log_func (PJ_CONTEXT *ctx, void *app_data, PJ_LOG_FUNCTION logf); const PJ_OPERATIONS *proj_list_operations(void); const PJ_ELLPS *proj_list_ellps(void); const PJ_UNITS *proj_list_units(void); const PJ_PRIME_MERIDIANS *proj_list_prime_meridians(void); double proj_dmstor(const char *is, char **rs); ====== ---- <>GIS