From: <hez...@us...> - 2010-04-12 05:23:49
|
Revision: 10905 http://plplot.svn.sourceforge.net/plplot/?rev=10905&view=rev Author: hezekiahcarty Date: 2010-04-12 05:23:41 +0000 (Mon, 12 Apr 2010) Log Message: ----------- Add basic global/universal coordinate transform support This commit adds a function plstransform which allows a user to define a global coordinate transform which will be used by all PLplot plotting functions which act inside the plotting window. C example 19 has been updated with an extra page to illustrate the use of plstransform. This commit also adds the plpath function which acts like pljoin when no transform is defined and approximates the translated path with a given number of line segments when a transform is defined. The OCaml bindings have been updated to include support for plstransform and plpath. OCaml example 19 has been updated to match the updated C example. No other language bindings are updated by this commit. The API documentation has been updated to reflect these changes. Modified Paths: -------------- trunk/bindings/ocaml/plplot.mli trunk/bindings/ocaml/plplot_core.idl trunk/bindings/ocaml/plplot_h trunk/bindings/ocaml/plplot_h.inc trunk/bindings/ocaml/plplot_impl.c trunk/doc/docbook/src/api.xml trunk/doc/docbook/src/plplotdoc.xml.in trunk/examples/c/x19c.c trunk/examples/ocaml/x19.ml trunk/include/plplot.h trunk/include/plplotP.h trunk/include/plstrm.h trunk/src/plbox.c trunk/src/plcore.c trunk/src/plfill.c trunk/src/plline.c trunk/src/plmap.c trunk/src/plshade.c trunk/src/plsym.c Modified: trunk/bindings/ocaml/plplot.mli =================================================================== --- trunk/bindings/ocaml/plplot.mli 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/bindings/ocaml/plplot.mli 2010-04-12 05:23:41 UTC (rev 10905) @@ -660,6 +660,8 @@ = "camlidl_plplot_core_c_plot3dc" external plpat : int array -> int array -> unit = "camlidl_plplot_core_c_plpat" +external plpath : int -> float -> float -> float -> float -> unit + = "camlidl_plplot_core_c_plpath" external plpoin : float array -> float array -> int -> unit = "camlidl_plplot_core_c_plpoin" external plpoin3 : float array -> float array -> float array -> int -> unit @@ -868,6 +870,8 @@ val plunset_mapform : unit -> unit val plset_defined : (float -> float -> int) -> unit val plunset_defined : unit -> unit +val plstransform : (float -> float -> (float * float)) -> unit +val plunset_transform : unit -> unit type plplot_grid_method_type = PL_GRID_CSA | PL_GRID_DTLI Modified: trunk/bindings/ocaml/plplot_core.idl =================================================================== --- trunk/bindings/ocaml/plplot_core.idl 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/bindings/ocaml/plplot_core.idl 2010-04-12 05:23:41 UTC (rev 10905) @@ -172,6 +172,19 @@ "let plunset_defined () = Callback.register \"caml_plplot_defined\" 0"); quote(mli, "val plunset_defined : unit -> unit"); +// Setting the translation function for the global coordinate transform +quote(ml, "external ml_plstransform : unit -> unit = \"ml_plstransform\""); +quote(ml, + "let plstransform (f : float -> float -> (float * float)) =\ + Callback.register \"caml_plplot_transform\" f;\ + ml_plstransform ()"); +quote(mli, "val plstransform : (float -> float -> (float * float)) -> unit"); +quote(ml, + "let plunset_transform () =\ + Callback.register \"caml_plplot_transform\" 0;\ + ml_plstransform ()"); +quote(mli, "val plunset_transform : unit -> unit"); + // Hand-translated PL_GRID_* flags for use with plgriddata quote(mlmli, "type plplot_grid_method_type = \ PL_GRID_CSA | \ Modified: trunk/bindings/ocaml/plplot_h =================================================================== --- trunk/bindings/ocaml/plplot_h 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/bindings/ocaml/plplot_h 2010-04-12 05:23:41 UTC (rev 10905) @@ -294,6 +294,9 @@ c_plpat(PLINT nlin, PLINT *inc, PLINT *del); void +c_plpath(PLINT n, PLFLT x1, PLFLT y1, PLFLT x2, PLFLT y2); + + void c_plpoin(PLINT n, PLFLT *x, PLFLT *y, PLINT code); void Modified: trunk/bindings/ocaml/plplot_h.inc =================================================================== --- trunk/bindings/ocaml/plplot_h.inc 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/bindings/ocaml/plplot_h.inc 2010-04-12 05:23:41 UTC (rev 10905) @@ -71,6 +71,7 @@ [mlname(plot3d)] void c_plot3d ( [size_is(nx), in] double * x, [size_is(ny), in] double * y, [size_is(nx, ny), in] double ** z, int nx, int ny, plplot3d_style opt, boolean side ); [mlname(plot3dc)] void c_plot3dc ( [size_is(nx), in] double * x, [size_is(ny), in] double * y, [size_is(nx, ny), in] double ** z, int nx, int ny, plplot3d_style opt, [size_is(nlevel), in] double * clevel, int nlevel ); [mlname(plpat)] void c_plpat ( int nlin, [in, size_is(nlin)] int * inc, [in, size_is(nlin)] int * del ); +[mlname(plpath)] void c_plpath ( int n, double x1, double y1, double x2, double y2); [mlname(plpoin)] void c_plpoin ( int n, [in, size_is(n)] double * x, [in, size_is(n)] double * y, int code ); [mlname(plpoin3)] void c_plpoin3 ( int n, [in, size_is(n)] double * x, [in, size_is(n)] double * y, [in, size_is(n)] double * z, int code ); [mlname(plprec)] void c_plprec ( int setp, int prec ); Modified: trunk/bindings/ocaml/plplot_impl.c =================================================================== --- trunk/bindings/ocaml/plplot_impl.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/bindings/ocaml/plplot_impl.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -33,13 +33,14 @@ #include <stdio.h> -#define MAX_EXCEPTION_MESSAGE_LENGTH 1000 -#define CAML_PLPLOT_PLOTTER_FUNC_NAME "caml_plplot_plotter" -#define CAML_PLPLOT_MAPFORM_FUNC_NAME "caml_plplot_mapform" -#define CAML_PLPLOT_DEFINED_FUNC_NAME "caml_plplot_defined" -#define CAML_PLPLOT_LABEL_FUNC_NAME "caml_plplot_customlabel" -#define CAML_PLPLOT_ABORT_FUNC_NAME "caml_plplot_abort" -#define CAML_PLPLOT_EXIT_FUNC_NAME "caml_plplot_exit" +#define MAX_EXCEPTION_MESSAGE_LENGTH 1000 +#define CAML_PLPLOT_PLOTTER_FUNC_NAME "caml_plplot_plotter" +#define CAML_PLPLOT_MAPFORM_FUNC_NAME "caml_plplot_mapform" +#define CAML_PLPLOT_DEFINED_FUNC_NAME "caml_plplot_defined" +#define CAML_PLPLOT_LABEL_FUNC_NAME "caml_plplot_customlabel" +#define CAML_PLPLOT_ABORT_FUNC_NAME "caml_plplot_abort" +#define CAML_PLPLOT_EXIT_FUNC_NAME "caml_plplot_exit" +#define CAML_PLPLOT_TRANSFORM_FUNC_NAME "caml_plplot_transform" typedef void ( *ML_PLOTTER_FUNC )( PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer ); typedef PLINT ( *ML_DEFINED_FUNC )( PLFLT, PLFLT ); @@ -200,6 +201,30 @@ CAMLreturn( Int_val( result ) ); } +// A simple routine to wrap a properly registered OCaml callback in a form +// usable by PLPlot routines. If an appropriate callback is not registered +// then nothing is done. +void ml_transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data ) +{ + CAMLparam0(); + CAMLlocal1( result ); + + // Get the OCaml callback function (if there is one) + static value * transform = NULL; + if ( transform == NULL ) + transform = caml_named_value( CAML_PLPLOT_TRANSFORM_FUNC_NAME ); + + // No check to see if a callback function has been designated yet, + // because that is checked before we get to this point. + result = + caml_callback2( *transform, caml_copy_double( x ), caml_copy_double( y ) ); + + *xt = Double_val( Field( result, 0 ) ); + *yt = Double_val( Field( result, 1 ) ); + + CAMLreturn0; +} + // Check if the matching OCaml callback is defined. Return NULL if it is not, // and the proper function pointer if it is. ML_PLOTTER_FUNC get_ml_plotter_func() @@ -316,6 +341,27 @@ CAMLreturn( Val_unit ); } +// Set a global coordinate transform +value ml_plstransform( value unit ) +{ + CAMLparam1( unit ); + static value * handler = NULL; + if ( handler == NULL ) + handler = caml_named_value( CAML_PLPLOT_TRANSFORM_FUNC_NAME ); + + if ( handler == NULL || Val_int( 0 ) == *handler ) + { + // No handler defined + plstransform( NULL, NULL ); + } + else + { + // Handler is defined + plstransform( ml_transform, NULL ); + } + CAMLreturn( Val_unit ); +} + /* * * CONTOURING, SHADING and IMAGE FUNCTIONS Modified: trunk/doc/docbook/src/api.xml =================================================================== --- trunk/doc/docbook/src/api.xml 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/doc/docbook/src/api.xml 2010-04-12 05:23:41 UTC (rev 10905) @@ -7934,6 +7934,106 @@ </sect1> + <sect1 id="plpath" renderas="sect3"> + <title> + <function>plpath</function>: Draw a line between two points, accounting + for coordinate transforms. + </title> + + <para> + <funcsynopsis> + <funcprototype> + <funcdef> + <function>plpath</function> + </funcdef> + <paramdef><parameter>n</parameter></paramdef> + <paramdef><parameter>x1</parameter></paramdef> + <paramdef><parameter>y1</parameter></paramdef> + <paramdef><parameter>x2</parameter></paramdef> + <paramdef><parameter>y2</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </para> + + <para> + Joins the point <literal>(<parameter>x1</parameter>, + <parameter>y1</parameter>)</literal> to + <literal>(<parameter>x2</parameter>, + <parameter>y2</parameter>)</literal>. If a global coordinate transform + is defined then the line is broken in to + <literal><parameter>n</parameter></literal> segments to approximate the + path. If no transform is defined then this simply acts like a call to + &pljoin;. + </para> + + <variablelist> + <varlistentry> + <term> + <parameter>n</parameter> + (<literal>PLINT</literal>, input) + </term> + <listitem> + <para> + number of points to use to approximate the path. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>x1</parameter> + (<literal>PLFLT</literal>, input) + </term> + <listitem> + <para> + x coordinate of first point. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>y1</parameter> + (<literal>PLFLT</literal>, input) + </term> + <listitem> + <para> + y coordinate of first point. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>x2</parameter> + (<literal>PLFLT</literal>, input) + </term> + <listitem> + <para> + x coordinate of second point. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>y2</parameter> + (<literal>PLFLT</literal>, input) + </term> + <listitem> + <para> + y coordinate of second point. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Redacted form: <function>plpath(n,x1,y1,x2,y2)</function> + </para> + + <para> + This function is not used in any examples. + </para> + + </sect1> + <sect1 id="plpoin" renderas="sect3"> <title> <function>plpoin</function>: Plots a character at the specified points @@ -12899,6 +12999,79 @@ </sect1> + <sect1 id="plstransform" renderas="sect3"> + <title> + <function>plstransform</function>: Set a global coordinate transform + function + </title> + + <para> + <funcsynopsis> + <funcprototype> + <funcdef> + <function>plstransform</function> + </funcdef> + <paramdef><parameter>transform_fun</parameter></paramdef> + <paramdef><parameter>data</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </para> + + <para> + This function can be used to define a coordinate transformation which + affects all elements drawn within the current plot window. The + transformation function is similar to that provided for the &plmap; + and &plmeridians; functions. The + <literal><parameter>data</parameter></literal> parameter may be used to + pass extra data to + <literal><parameter>transform_fun</parameter></literal>. + </para> + + <variablelist> + <varlistentry> + <term> + <parameter>transform_fun</parameter> + (<literal>void (*) (PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer) + </literal>, input) + </term> + <listitem> + <para> + Pointer to a function that defines a transformation from the + input (x, y) coordinate to a new plot world coordiante. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <parameter>data</parameter> + (<literal>PLPointer</literal>, input) + </term> + <listitem> + <para> + Optional extra data for + <parameter><literal>transform_fun</literal></parameter>. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Redacted form: + <itemizedlist> + <listitem> + <para> + General: <function>plstransform(transform_fun, data)</function> + </para> + </listitem> + </itemizedlist> + </para> + + <para> + This function is used in example 19. + </para> + + </sect1> + <sect1 id="plstripa" renderas="sect3"> <title> <function>plstripa</function>: Add a point to a stripchart Modified: trunk/doc/docbook/src/plplotdoc.xml.in =================================================================== --- trunk/doc/docbook/src/plplotdoc.xml.in 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/doc/docbook/src/plplotdoc.xml.in 2010-04-12 05:23:41 UTC (rev 10905) @@ -153,6 +153,8 @@ <!ENTITY plline '<link linkend="plline"><function>plline</function></link>'> <!ENTITY plline3 '<link linkend="plline3"><function>plline3</function></link>'> <!ENTITY pllsty '<link linkend="pllsty"><function>pllsty</function></link>'> +<!ENTITY plmap '<link linkend="plmap"><function>plmap</function></link>'> +<!ENTITY plmeridians '<link linkend="plmeridians"><function>plmeridians</function></link>'> <!ENTITY plMergeOpts '<link linkend="plMergeOpts"><function>plMergeOpts</function></link>'> <!ENTITY plmesh '<link linkend="plmesh"><function>plmesh</function></link>'> <!ENTITY plmeshc '<link linkend="plmeshc"><function>plmeshc</function></link>'> @@ -169,6 +171,7 @@ <!ENTITY plparseoptsfortran95 '<link linkend="plparseoptsfortran95"><function>plparseoptsfortran95</function></link>'> <!ENTITY plparseoptsfortran77 '<link linkend="plparseoptsfortran77"><function>plparseoptsfortran77</function></link>'> <!ENTITY plpat '<link linkend="plpat"><function>plpat</function></link>'> +<!ENTITY plpath '<link linkend="plpath"><function>plpath</function></link>'> <!ENTITY plpoin '<link linkend="plpoin"><function>plpoin</function></link>'> <!ENTITY plpoin3 '<link linkend="plpoin3"><function>plpoin3</function></link>'> <!ENTITY plpoly3 '<link linkend="plpoly3"><function>plpoly3</function></link>'> @@ -224,6 +227,7 @@ <!ENTITY plstripc '<link linkend="plstripc"><function>plstripc</function></link>'> <!ENTITY plstripd '<link linkend="plstripd"><function>plstripd</function></link>'> <!ENTITY plstart '<link linkend="plstart"><function>plstart</function></link>'> +<!ENTITY plstransform '<link linkend="plstransform"><function>plstransform</function></link>'> <!ENTITY plstyl '<link linkend="plstyl"><function>plstyl</function></link>'> <!ENTITY plsurf3d '<link linkend="plsurf3d"><function>plsurf3d</function></link>'> <!ENTITY plsvect '<link linkend="plsvect"><function>plsvect</function></link>'> Modified: trunk/examples/c/x19c.c =================================================================== --- trunk/examples/c/x19c.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/examples/c/x19c.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -6,6 +6,16 @@ #include "plcdemos.h" +void +map_transform( PLFLT x, PLFLT y, PLFLT *xt, PLFLT *yt, PLPointer data ) +{ + double radius; + + radius = 90.0 - y; + *xt = radius * cos( x * M_PI / 180.0 ); + *yt = radius * sin( x * M_PI / 180.0 ); +} + /*--------------------------------------------------------------------------*\ * mapform19 * @@ -18,14 +28,12 @@ mapform19( PLINT n, PLFLT *x, PLFLT *y ) { int i; - double xp, yp, radius; + double xp, yp; for ( i = 0; i < n; i++ ) { - radius = 90.0 - y[i]; - xp = radius * cos( x[i] * M_PI / 180.0 ); - yp = radius * sin( x[i] * M_PI / 180.0 ); - x[i] = xp; - y[i] = yp; + map_transform( x[i], y[i], &xp, &yp, NULL ); + x[i] = xp; + y[i] = yp; } } @@ -159,6 +167,35 @@ pllsty( 2 ); plmeridians( mapform19, 10.0, 10.0, 0.0, 360.0, -10.0, 80.0 ); + +/* Polar, Northern hemisphere, this time with a PLplot-wide transform */ + + minx = 0; + maxx = 360; + + plstransform( map_transform, NULL ); + + pllsty( 1 ); + plenv( -75., 75., -75., 75., 1, -1 ); + /* No need to set the map transform here as the global transform will be + * used. */ + plmap( NULL, "globe", minx, maxx, miny, maxy ); + + pllsty( 2 ); + plmeridians( NULL, 10.0, 10.0, 0.0, 360.0, -10.0, 80.0 ); + + /* Show Baltimore, MD on the map */ + plcol0( 2 ); + plssym( 0.0, 2.0 ); + PLFLT x = -76.6125; + PLFLT y = 39.2902778; + plpoin( 1, &x, &y, 18 ); + plssym( 0.0, 1.0 ); + plptex( -76.6125, 43.0, 0.0, 0.0, 0.0, "Baltimore, MD" ); + + /* For C, this is how the global transform is cleared */ + plstransform( NULL, NULL ); + plend(); exit( 0 ); } Modified: trunk/examples/ocaml/x19.ml =================================================================== --- trunk/examples/ocaml/x19.ml 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/examples/ocaml/x19.ml 2010-04-12 05:23:41 UTC (rev 10905) @@ -144,5 +144,33 @@ (* This call to plmeridians is also after the set_mapform call, so it uses the same projection as the plmap call above. *) plmeridians 10.0 10.0 0.0 360.0 (-10.0) 80.0; + + plunset_mapform (); + + (* Polar, Northern hemisphere, this time with a PLplot-wide transform *) + let minx = 0.0 in + let maxx = 360.0 in + + plstransform mapform19; + + pllsty 1; + plenv (-75.) 75. (-75.) 75. 1 (-1); + (* No need to set the map transform here as the global transform will be + used. *) + plmap "globe" minx maxx miny maxy; + + pllsty 2; + plmeridians 10.0 10.0 0.0 360.0 (-10.0) 80.0; + + (* Show Baltimore, MD on the map *) + plcol0 2; + plssym 0.0 2.0; + plpoin [|-76.6125|] [|39.2902778|] 18; + plssym 0.0 1.0; + plptex ~-.76.6125 43.0 0.0 0.0 0.0 "Baltimore, MD"; + + (* For OCaml, this is how the global transform is cleared *) + plunset_transform (); + plend (); () Modified: trunk/include/plplot.h =================================================================== --- trunk/include/plplot.h 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/include/plplot.h 2010-04-12 05:23:41 UTC (rev 10905) @@ -656,6 +656,7 @@ #define plgcolbg c_plgcolbg #define plgcolbga c_plgcolbga #define plgcompression c_plgcompression +#define plstransform c_plstransform #define plgdev c_plgdev #define plgdidev c_plgdidev #define plgdiori c_plgdiori @@ -688,6 +689,7 @@ #define pllab c_pllab #define pllightsource c_pllightsource #define plline c_plline +#define plpath c_plpath #define plline3 c_plline3 #define pllsty c_pllsty #define plmap c_plmap @@ -1046,6 +1048,10 @@ PLDLLIMPEXP void c_plgcompression( PLINT *compression ); +/* Set the coordinate transform */ +PLDLLIMPEXP void +c_plstransform( void ( *coordinate_transform )( PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer ), PLPointer coordinate_transform_data ); + /* Get the current device (keyword) name */ PLDLLIMPEXP void @@ -1349,6 +1355,11 @@ PLDLLIMPEXP void c_plpat( PLINT nlin, PLINT *inc, PLINT *del ); +/* Draw a line connecting two points, accounting for coordinate transforms */ + +PLDLLIMPEXP void +c_plpath( PLINT n, PLFLT x1, PLFLT y1, PLFLT x2, PLFLT y2 ); + /* Plots array y against x for n points using ASCII code "code".*/ PLDLLIMPEXP void Modified: trunk/include/plplotP.h =================================================================== --- trunk/include/plplotP.h 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/include/plplotP.h 2010-04-12 05:23:41 UTC (rev 10905) @@ -195,26 +195,29 @@ /* Lots of cool math macros */ #ifndef MAX -#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #endif #ifndef MIN -#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) +#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #endif #ifndef ABS -#define ABS( a ) ( ( a ) < 0 ? -( a ) : ( a ) ) +#define ABS( a ) ( ( a ) < 0 ? -( a ) : ( a ) ) #endif #ifndef ROUND -#define ROUND( a ) (PLINT) ( ( a ) < 0. ? ( ( a ) - .5 ) : ( ( a ) + .5 ) ) +#define ROUND( a ) (PLINT) ( ( a ) < 0. ? ( ( a ) - .5 ) : ( ( a ) + .5 ) ) #endif #ifndef BETW -#define BETW( ix, ia, ib ) ( ( ( ix ) <= ( ia ) && ( ix ) >= ( ib ) ) || ( ( ix ) >= ( ia ) && ( ix ) <= ( ib ) ) ) +#define BETW( ix, ia, ib ) ( ( ( ix ) <= ( ia ) && ( ix ) >= ( ib ) ) || ( ( ix ) >= ( ia ) && ( ix ) <= ( ib ) ) ) #endif #ifndef SSQR -#define SSQR( a, b ) sqrt( ( a ) * ( a ) + ( b ) * ( b ) ) +#define SSQR( a, b ) sqrt( ( a ) * ( a ) + ( b ) * ( b ) ) #endif #ifndef SIGN -#define SIGN( a ) ( ( a ) < 0 ? -1 : 1 ) +#define SIGN( a ) ( ( a ) < 0 ? -1 : 1 ) #endif +#ifndef TRANSFORM +#define TRANSFORM( x, y, xnew, ynew ) if ( plsc->coordinate_transform ) { plsc->coordinate_transform( ( x ), ( y ), ( xnew ), ( ynew ), plsc->coordinate_transform_data ); } else { *xnew = x; *ynew = y; } +#endif /* A coordinate value that should never occur */ Modified: trunk/include/plstrm.h =================================================================== --- trunk/include/plstrm.h 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/include/plstrm.h 2010-04-12 05:23:41 UTC (rev 10905) @@ -519,6 +519,11 @@ PLINT ipls, level, verbose, debug, initialized, dev_initialized; const char *program; +/* Plot-wide coordinate transform */ + + void ( *coordinate_transform )( PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer ); + PLPointer coordinate_transform_data; + /* Colormaps */ PLINT icol0, ncol0, icol1, ncol1, ncp1, curcmap; Modified: trunk/src/plbox.c =================================================================== --- trunk/src/plbox.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plbox.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -24,9 +24,10 @@ #include "plplotP.h" -#define STRING_LEN 40 -#define FORMAT_LEN 10 -#define TEMP_LEN 30 +#define STRING_LEN 40 +#define FORMAT_LEN 10 +#define TEMP_LEN 30 +#define N_EDGE_SEGMENTS 50 static PLFLT xlog[8] = { Modified: trunk/src/plcore.c =================================================================== --- trunk/src/plcore.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plcore.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -4230,3 +4230,16 @@ plsc->plbuf_write = plbuf_write; #endif /* END dev_fastimg COMMENT */ } + +/*--------------------------------------------------------------------------*\ + * plstransform + * + * Set a universal coordinate transform function which will be applied to all + * plotted items. + \*--------------------------------------------------------------------------*/ +void +c_plstransform( void ( *coordinate_transform )( PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer ), PLPointer coordinate_transform_data ) +{ + plsc->coordinate_transform = coordinate_transform; + plsc->coordinate_transform_data = coordinate_transform_data; +} Modified: trunk/src/plfill.c =================================================================== --- trunk/src/plfill.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plfill.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -132,6 +132,7 @@ { PLINT xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY]; PLINT i; + PLFLT xt, yt; if ( plsc->level < 3 ) { @@ -150,15 +151,17 @@ } for ( i = 0; i < n; i++ ) { - xpoly[i] = plP_wcpcx( x[i] ); - ypoly[i] = plP_wcpcy( y[i] ); + TRANSFORM( x[i], y[i], &xt, &yt ); + xpoly[i] = plP_wcpcx( xt ); + ypoly[i] = plP_wcpcy( yt ); } if ( x[0] != x[n - 1] || y[0] != y[n - 1] ) { if ( n < PL_MAXPOLY ) n++; - xpoly[n - 1] = plP_wcpcx( x[0] ); - ypoly[n - 1] = plP_wcpcy( y[0] ); + TRANSFORM( x[0], y[0], &xt, &yt ); + xpoly[n - 1] = plP_wcpcx( xt ); + ypoly[n - 1] = plP_wcpcy( yt ); } plP_plfclp( xpoly, ypoly, n, plsc->clpxmi, plsc->clpxma, Modified: trunk/src/plline.c =================================================================== --- trunk/src/plline.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plline.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -49,6 +49,11 @@ /* Determines if a point is inside a polygon or not */ +/* Interpolate between two points in n steps */ + +static PLFLT * +interpolate_between( int n, PLFLT a, PLFLT b ); + /*----------------------------------------------------------------------*\ * void pljoin() * @@ -80,6 +85,42 @@ } /*----------------------------------------------------------------------*\ + * void plpath() + * + * Draws a line segment from (x1, y1) to (x2, y2). If a coordinate + * transform is defined then break the line up in to n pieces to approximate + * the path. Otherwise it simply calls pljoin(). + \*----------------------------------------------------------------------*/ + +void +c_plpath( PLINT n, PLFLT x1, PLFLT y1, PLFLT x2, PLFLT y2 ) +{ + PLFLT *xs, *ys; + + if ( plsc->coordinate_transform == NULL ) + { + /* No transform, so fall back on pljoin for a normal straight line */ + pljoin( x1, y1, x2, y2 ); + } + else + { + /* Approximate the path in transformed space with a sequence of line + * segments. */ + xs = interpolate_between( n, x1, x2 ); + ys = interpolate_between( n, y1, y2 ); + if ( xs == NULL || ys == NULL ) + { + plexit( "c_plpath: Insufficient memory" ); + return; + } + plline( n, xs, ys ); + /* plP_interpolate allocates memory, so we have to free it here. */ + free( xs ); + free( ys ); + } +} + +/*----------------------------------------------------------------------*\ * void plline3(n, x, y, z) * * Draws a line in 3 space. You must first set up the viewport, the @@ -450,8 +491,11 @@ void plP_movwor( PLFLT x, PLFLT y ) { - plsc->currx = plP_wcpcx( x ); - plsc->curry = plP_wcpcy( y ); + PLFLT xt, yt; + TRANSFORM( x, y, &xt, &yt ); + + plsc->currx = plP_wcpcx( xt ); + plsc->curry = plP_wcpcy( yt ); } /*----------------------------------------------------------------------*\ @@ -463,10 +507,13 @@ void plP_drawor( PLFLT x, PLFLT y ) { + PLFLT xt, yt; + TRANSFORM( x, y, &xt, &yt ); + xline[0] = plsc->currx; - xline[1] = plP_wcpcx( x ); + xline[1] = plP_wcpcx( xt ); yline[0] = plsc->curry; - yline[1] = plP_wcpcy( y ); + yline[1] = plP_wcpcy( yt ); pllclp( xline, yline, 2 ); } @@ -510,6 +557,7 @@ plP_drawor_poly( PLFLT *x, PLFLT *y, PLINT n ) { PLINT i, j, ib, ilim; + PLFLT xt, yt; for ( ib = 0; ib < n; ib += PL_MAXPOLY - 1 ) { @@ -517,9 +565,10 @@ for ( i = 0; i < ilim; i++ ) { - j = ib + i; - xline[i] = plP_wcpcx( x[j] ); - yline[i] = plP_wcpcy( y[j] ); + j = ib + i; + TRANSFORM( x[j], y[j], &xt, &yt ); + xline[i] = plP_wcpcx( xt ); + yline[i] = plP_wcpcy( yt ); } pllclp( xline, yline, ilim ); } @@ -914,3 +963,35 @@ lasty = ytmp; } } + +/*----------------------------------------------------------------------*\ + * interpolate_between() + * + * Returns a pointer to an array of PLFLT values which interpolate in n steps + * from a to b. + * Note: + * The returned array is allocated by the function and needs to be freed by + * the function's caller. + * If the return value is NULL, the allocation failed and it is up to the + * caller to handle the error. + \*----------------------------------------------------------------------*/ + +PLFLT *interpolate_between( PLINT n, PLFLT a, PLFLT b ) +{ + PLFLT *values; + PLFLT step_size; + int i; + + if ( ( values = (PLFLT *) malloc( n * sizeof ( PLFLT ) ) ) == NULL ) + { + return NULL; + } + + step_size = ( b - a ) / (PLFLT) ( n - 1 ); + for ( i = 0; i < n; i++ ) + { + values[i] = a + step_size * (PLFLT) i; + } + + return values; +} Modified: trunk/src/plmap.c =================================================================== --- trunk/src/plmap.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plmap.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -292,10 +292,7 @@ { if ( mapform == NULL ) { - y[0] = y[1] = yy; - x[0] = minlong; - x[1] = maxlong; - plline( 2, x, y ); + plpath( NSEG, minlong, yy, maxlong, yy ); } else { @@ -316,10 +313,7 @@ { if ( mapform == NULL ) { - x[0] = x[1] = xx; - y[0] = minlat; - y[1] = maxlat; - plline( 2, x, y ); + plpath( NSEG, xx, minlat, xx, maxlat ); } else { Modified: trunk/src/plshade.c =================================================================== --- trunk/src/plshade.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plshade.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -514,7 +514,7 @@ return; } - if ( pltr == NULL ) + if ( pltr == NULL && plsc->coordinate_transform == NULL ) rectangular = 1; int_val = shade_max - shade_min; Modified: trunk/src/plsym.c =================================================================== --- trunk/src/plsym.c 2010-04-12 05:11:37 UTC (rev 10904) +++ trunk/src/plsym.c 2010-04-12 05:23:41 UTC (rev 10905) @@ -87,6 +87,7 @@ c_plsym( PLINT n, PLFLT *x, PLFLT *y, PLINT code ) { PLINT i; + PLFLT xt, yt; if ( plsc->level < 3 ) { @@ -101,7 +102,8 @@ for ( i = 0; i < n; i++ ) { - plhrsh( code, plP_wcpcx( x[i] ), plP_wcpcy( y[i] ) ); + TRANSFORM( x[i], y[i], &xt, &yt ); + plhrsh( code, plP_wcpcx( xt ), plP_wcpcy( yt ) ); } } @@ -122,6 +124,7 @@ c_plpoin( PLINT n, PLFLT *x, PLFLT *y, PLINT code ) { PLINT i, sym, ifont = plsc->cfont; + PLFLT xt, yt; if ( plsc->level < 3 ) { @@ -137,7 +140,10 @@ if ( code == -1 ) { for ( i = 0; i < n; i++ ) - pljoin( x[i], y[i], x[i], y[i] ); + { + TRANSFORM( x[i], y[i], &xt, &yt ); + pljoin( xt, yt, xt, yt ); + } } else { @@ -148,7 +154,10 @@ // fprintf(stdout, "plploin code, sym = %d, %d\n", code, sym); for ( i = 0; i < n; i++ ) - plhrsh( sym, plP_wcpcx( x[i] ), plP_wcpcy( y[i] ) ); + { + TRANSFORM( x[i], y[i], &xt, &yt ); + plhrsh( sym, plP_wcpcx( xt ), plP_wcpcy( yt ) ); + } } } @@ -598,6 +607,7 @@ PLFLT xform[4], diag; PLFLT chrdef, chrht; PLFLT dispx, dispy; + PLFLT wxt, wyt, dxt, dyt; if ( plsc->level < 3 ) { @@ -605,13 +615,19 @@ return; } - if ( dx == 0.0 && dy == 0.0 ) + /* Transform both the origin and offset values */ + TRANSFORM( wx, wy, &wxt, &wyt ); + TRANSFORM( wx + dx, wy + dy, &dxt, &dyt ); + dxt = dxt - wxt; + dyt = dyt - wyt; + if ( dxt == 0.0 && dyt == 0.0 ) { - dx = 1.0; - dy = 0.0; + dxt = 1.0; + dyt = 0.0; } - cc = plsc->wmxscl * dx; - ss = plsc->wmyscl * dy; + + cc = plsc->wmxscl * dxt; + ss = plsc->wmyscl * dyt; diag = sqrt( cc * cc + ss * ss ); cc /= diag; ss /= diag; @@ -621,8 +637,8 @@ xform[2] = ss; xform[3] = cc; - xdv = plP_wcdcx( wx ); - ydv = plP_wcdcy( wy ); + xdv = plP_wcdcx( wxt ); + ydv = plP_wcdcy( wyt ); dispx = 0.; dispy = 0.; @@ -1828,6 +1844,7 @@ else plP_affine_scale( affineL, 1. / stride, 1.e300 ); plP_affine_multiply( xform, affineL, xform ); + plP_text( 0, just, xform, (PLINT) xpc, (PLINT) ypc, (PLINT) xrefpc, (PLINT) yrefpc, text ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |