Updated 2018-07-15 06:28:52 by pd

proj  edit

swig based binding for tcl for the proj.4 library using the new API described here. A simple binding to the old API using critcl has been moved to proj4tcl - deprecated.

usage

Here is the c example from proj quick start
#include <stdio.h>
#include <proj.h>

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
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]]

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]]                 


proj_destroy $P
proj_context_destroy $C    

build

swig wrapper

file: proj.i
%module proj

%{
#include <proj.h>
%}

%include <proj.h>

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 msys2/mingw64 static (tested with bawt)
pacboy -S gcc 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
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);