From: <fu...@us...> - 2010-05-11 17:17:17
|
Revision: 10990 http://plplot.svn.sourceforge.net/plplot/?rev=10990&view=rev Author: furnish Date: 2010-05-11 17:17:11 +0000 (Tue, 11 May 2010) Log Message: ----------- Reimplement the last plot in Tcl example 19, using a global coordinate transform, as is done in x19c. Updates to tclAPI.c to support plstransform(), providing a C-side wrapper which evaluates a Tcl proc to do the job. Example 19 now produces equivalent results in C and Tcl. Modified Paths: -------------- trunk/bindings/tcl/tclAPI.c trunk/examples/tcl/x19.tcl Modified: trunk/bindings/tcl/tclAPI.c =================================================================== --- trunk/bindings/tcl/tclAPI.c 2010-05-11 14:21:06 UTC (rev 10989) +++ trunk/bindings/tcl/tclAPI.c 2010-05-11 17:17:11 UTC (rev 10990) @@ -60,6 +60,7 @@ static int plshadesCmd( ClientData, Tcl_Interp *, int, const char ** ); static int plmapCmd( ClientData, Tcl_Interp *, int, const char ** ); static int plmeridiansCmd( ClientData, Tcl_Interp *, int, const char ** ); +static int plstransformCmd( ClientData, Tcl_Interp *, int, const char ** ); static int plvectCmd( ClientData, Tcl_Interp *, int, const char ** ); static int plranddCmd( ClientData, Tcl_Interp *, int, const char ** ); static int plgriddataCmd( ClientData, Tcl_Interp *, int, const char ** ); @@ -98,6 +99,7 @@ { "plcont", plcontCmd }, { "plmap", plmapCmd }, { "plmeridians", plmeridiansCmd }, + { "plstransform", plstransformCmd }, { "plmesh", plmeshCmd }, { "plmeshc", plmeshcCmd }, { "plot3d", plot3dCmd }, @@ -3327,7 +3329,99 @@ return TCL_OK; } +static Tcl_Interp *tcl_xform_interp = 0; +static char *tcl_xform_procname = 0; +static const char *tcl_xform_template = + "set result [%s ${_##_x} ${_##_y}] ; lassign $result _##_x _##_y"; + +static char *tcl_xform_code = 0; + +static void +Tcl_transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data ) +{ +// Set Tcl x to x + Tcl_Obj *objx = Tcl_NewDoubleObj( x ); + Tcl_IncrRefCount( objx ); + Tcl_SetVar2Ex( tcl_xform_interp, + "_##_x", NULL, objx, 0 ); + Tcl_DecrRefCount( objx ); + +// Set Tcl y to y + Tcl_Obj *objy = Tcl_NewDoubleObj( y ); + Tcl_IncrRefCount( objy ); + Tcl_SetVar2Ex( tcl_xform_interp, + "_##_y", NULL, objy, 0 ); + Tcl_DecrRefCount( objy ); + +// Call identified Tcl proc. Forget data, Tcl can use namespaces and custom +// procs to manage transmission of the custom client data. +// Proc should return a two element list which is xt yt. + int code = Tcl_Eval( tcl_xform_interp, tcl_xform_code ); + + if ( code != TCL_OK ) + { + printf( "Unable to evaluate Tcl-side coordinate transform.\n" ); + return; + } + + objx = Tcl_GetVar2Ex( tcl_xform_interp, "_##_x", NULL, 0 ); + objy = Tcl_GetVar2Ex( tcl_xform_interp, "_##_y", NULL, 0 ); + +// In case PLFLT != double, we have to make sure we perform the extraction in +// a safe manner. + double dx, dy; + + if ( Tcl_GetDoubleFromObj( tcl_xform_interp, objx, &dx ) != TCL_OK || + Tcl_GetDoubleFromObj( tcl_xform_interp, objy, &dy ) != TCL_OK ) + { + printf( "Unable to extract Tcl results.\n" ); + return; + } + + *xt = dx; + *yt = dy; +} + /*--------------------------------------------------------------------------*\ + * plstransform + * + * Implement Tcl-side global coordinate transformation setting/restoring API. + \*--------------------------------------------------------------------------*/ + +static int +plstransformCmd( ClientData clientData, Tcl_Interp *interp, + int argc, const char *argv[] ) +{ + if ( argc == 1 + || argv[1] == "NULL" ) + { + // The user has requested to clear the transform setting. + plstransform( NULL, NULL ); + tcl_xform_interp = 0; + if ( tcl_xform_procname ) + { + free( tcl_xform_procname ); + tcl_xform_procname = 0; + } + } + else + { + const char *data = argc > 2 ? argv[2] : 0; + + tcl_xform_interp = interp; + tcl_xform_procname = strdup( argv[1] ); + + int len = strlen( tcl_xform_template ) + strlen( tcl_xform_procname ); + tcl_xform_code = malloc( len ); + sprintf( tcl_xform_code, tcl_xform_template, tcl_xform_procname ); + + plstransform( Tcl_transform, NULL ); + } + + return TCL_OK; +} + +/*--------------------------------------------------------------------------*\ * plgriddataCmd * * Processes plgriddata Tcl command. Modified: trunk/examples/tcl/x19.tcl =================================================================== --- trunk/examples/tcl/x19.tcl 2010-05-11 14:21:06 UTC (rev 10989) +++ trunk/examples/tcl/x19.tcl 2010-05-11 17:17:11 UTC (rev 10990) @@ -30,6 +30,18 @@ # The coordinate transformation works directly on the two matrices # containing the x and y coordinates # + +proc map_transform { x y } { + + set scale [expr acos(-1.) / 180.] + + set radius [expr {90. - $y}] + + return [list \ + [expr {$radius * cos( $x * $scale )}] \ + [expr {$radius * sin( $x * $scale )}]] +} + proc mapform19 {n matx maty} { set deg_to_rad [expr {acos(-1.0)/180.0}] @@ -137,50 +149,37 @@ $w cmd plmeridians mapform19 10.0 10.0 0.0 360.0 -10.0 80.0 # Polar, Northern hemisphere -# In x19c this next plot is done with a global, PLplot-wide transform, set -# via plstransform. Looks like we need to build a Tcl proc evaluator -# callback function to handle this case. For now, we just do this plot sort -# of like how we did the last one. +# This time we use a global coordinate transformation, so no coordinate +# transform function is required on the plmap/plmeridians calls. set minx 0 set maxx 360 + $w cmd plstransform map_transform + $w cmd pllsty 1 $w cmd plenv -75 75 -75 75 1 -1 -# If we had a Tcl-analogue for plstransform, then we could drop the mapform19 -# transform function. But since we don't have Tcl support for global -# transform functions yet, we must pass in mapform19 here again. - $w cmd plmap mapform19 globe minx maxx miny maxy + $w cmd plmap globe $minx $maxx $miny $maxy $w cmd pllsty 2 - $w cmd plmeridians mapform19 10.0 10.0 0.0 360.0 -10.0 80.0 + $w cmd plmeridians 10.0 10.0 0.0 360.0 -10.0 80.0 # Show Baltimore, MD on the map. $w cmd plcol0 2 $w cmd plssym 0. 2. -# In the C example, the global transform function has been set, so x19c just -# uses the desired long/lat coords. In Tcl, till we implement a global -# transform capability, we have to do the transforms manually before calling -# the plotting functions. - +# This is kind of a messy way to use plpoin for plotting a single symbol. +# But it's what we have for now. matrix x f 1 matrix y f 1 x 0 = -76.6125 y 0 = 39.2902778 - mapform19 1 x y - $w cmd plpoin 1 x y 18 - x 0 = -76.6125 - y 0 = 43. - - mapform19 1 x y - $w cmd plssym 0. 1. - $w cmd plptex [x 0] [y 0] 0.0 0.0 0.0 "Baltimore, MD" + $w cmd plptex -76.6125 43. 0.0 0.0 0.0 "Baltimore, MD" $w cmd pllsty 1 # No defaults to restore This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |