From: <hez...@us...> - 2009-08-18 16:26:29
|
Revision: 10285 http://plplot.svn.sourceforge.net/plplot/?rev=10285&view=rev Author: hezekiahcarty Date: 2009-08-18 16:26:04 +0000 (Tue, 18 Aug 2009) Log Message: ----------- Add plslabelfunc to the OCaml bindings and update x19.ml to use it Modified Paths: -------------- trunk/bindings/ocaml/plplot.idl trunk/bindings/ocaml/plplot_impl.c trunk/examples/ocaml/x19.ml Modified: trunk/bindings/ocaml/plplot.idl =================================================================== --- trunk/bindings/ocaml/plplot.idl 2009-08-18 16:21:50 UTC (rev 10284) +++ trunk/bindings/ocaml/plplot.idl 2009-08-18 16:26:04 UTC (rev 10285) @@ -178,6 +178,25 @@ PL_PARSE_NODASH | \ PL_PARSE_SKIP"); +// Data type to reference axes +quote(mlmli, "type plplot_axis_type = \ + PL_X_AXIS | \ + PL_Y_AXIS | \ + PL_Z_AXIS"); + +// Custom axis labeling +quote(ml, "external ml_plslabelfunc : unit -> unit = \"ml_plslabelfunc\""); +quote(ml, +"let plslabelfunc (f : plplot_axis_type -> float -> string) =\ + Callback.register \"caml_plplot_customlabel\" f;\ + ml_plslabelfunc ()"); +quote(mli, "val plslabelfunc : (plplot_axis_type -> float -> string) -> unit"); +quote(ml, +"let plunset_labelfunc () =\ + Callback.register \"caml_plplot_customlabel\" 0;\ + ml_plslabelfunc ()"); +quote(mli, "val plunset_labelfunc : unit -> unit"); + RAW_ML(external plgriddata : float array -> float array -> float array -> float array -> float array -> plplot_grid_method_type -> float -> float array array = "ml_plgriddata_bytecode" "ml_plgriddata") RAW_ML(external plparseopts : string array -> plplot_parse_method_type list -> int = "ml_plparseopts") Modified: trunk/bindings/ocaml/plplot_impl.c =================================================================== --- trunk/bindings/ocaml/plplot_impl.c 2009-08-18 16:21:50 UTC (rev 10284) +++ trunk/bindings/ocaml/plplot_impl.c 2009-08-18 16:26:04 UTC (rev 10285) @@ -17,8 +17,6 @@ along with PLplot. If not, see <http://www.gnu.org/licenses/>. */ -#include <plplotP.h> - /* The "usual" OCaml includes */ #include <caml/alloc.h> #include <caml/callback.h> @@ -28,18 +26,23 @@ #include <caml/mlvalues.h> #include <caml/bigarray.h> +#include <plplotP.h> #include <plplot.h> +#undef snprintf + #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" typedef void(*ML_PLOTTER_FUNC)(PLFLT, PLFLT, PLFLT*, PLFLT*, PLPointer); typedef PLINT(*ML_DEFINED_FUNC)(PLFLT, PLFLT); typedef void(*ML_MAPFORM_FUNC)(PLINT, PLFLT*, PLFLT*); +typedef void(*ML_LABEL_FUNC)(PLINT, PLFLT, char*, PLINT, PLPointer); /* @@ -130,6 +133,28 @@ CAMLreturn0; } +// A simple routine to wrap a properly registered OCaml callback in a form +// usable by PLPlot routines. +void ml_labelfunc(PLINT axis, PLFLT n, char *label, PLINT length, PLPointer d) { + CAMLparam0(); + CAMLlocal1(result); + + // Get the OCaml callback function (if there is one) + static value * callback = NULL; + if (callback == NULL) + callback = caml_named_value(CAML_PLPLOT_LABEL_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(*callback, Val_int(axis - 1), caml_copy_double(n)); + + // Copy the OCaml callback output to the proper location. + snprintf(label, length, "%s", String_val(result)); + + 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() { @@ -175,7 +200,25 @@ } } +// Custom wrapper for plslabelfunc +value ml_plslabelfunc(value unit) { + CAMLparam1(unit); + static value * label = NULL; + if (label == NULL) + label = caml_named_value(CAML_PLPLOT_LABEL_FUNC_NAME); + if (label == NULL || Val_int(0) == *label) { + // No plotter defined + plslabelfunc(NULL, NULL); + } + else { + // Plotter is defined + plslabelfunc(ml_labelfunc, NULL); + } + + CAMLreturn(Val_unit); +} + /* CONTOURING, SHADING and IMAGE FUNCTIONS Modified: trunk/examples/ocaml/x19.ml =================================================================== --- trunk/examples/ocaml/x19.ml 2009-08-18 16:21:50 UTC (rev 10284) +++ trunk/examples/ocaml/x19.ml 2009-08-18 16:26:04 UTC (rev 10285) @@ -23,6 +23,7 @@ *) open Plplot +open Printf (*--------------------------------------------------------------------------*\ * mapform19 @@ -43,6 +44,48 @@ let yp = radius *. sin (x *. pi /. 180.0) in (xp, yp) +(* "Normalize" longitude values so that they always fall between -180.0 and + 180.0 *) +let normalize_longitude lon = + if lon >= -180.0 && lon <= 180.0 then + lon + else + let times = floor ((abs_float lon +. 180.0) /. 360.0) in + if lon < 0.0 then + lon +. 360.0 *. times + else + lon -. 360.0 *. times + +(* A custom axis labeling function for longitudes and latitudes. *) +let geolocation_labeler axis value = + let label_val, direction_label = + match axis with + | PL_Y_AXIS -> + let label_val = value in + label_val, + if label_val > 0.0 then + " N" + else if label_val < 0.0 then + " S" + else + "Eq" + | PL_X_AXIS -> + let label_val = normalize_longitude value in + label_val, + if label_val > 0.0 then + " E" + else if label_val < 0.0 then + " W" + else + "" + | PL_Z_AXIS -> invalid_arg "Invalid axis - only X or Y are supported" + in + if axis = PL_Y_AXIS && label_val = 0.0 then + (* A special case for the equator *) + sprintf "%s" direction_label + else + sprintf "%.0f%s" (abs_float label_val) direction_label + (*--------------------------------------------------------------------------*\ * main * @@ -65,8 +108,11 @@ let minx = 190.0 in let maxx = 190.0 +. 360.0 in + (* Setup a custom latitude and longitude-based scaling function. *) + plslabelfunc geolocation_labeler; + plcol0 1; - plenv minx maxx miny maxy 1 (-1); + plenv minx maxx miny maxy 1 70; (* No transform function is passed to plmap. Since we have not set one yet, it defaults to using an identity function (xp = x, yp = y) *) plmap "usaglobe" minx maxx miny maxy; @@ -76,11 +122,14 @@ let maxx = 340.0 in plcol0 1; - plenv minx maxx miny maxy 1 (-1); + plenv minx maxx miny maxy 1 70; (* Again, we have not set a transform. Everything remains in a Cartesian projection. *) plmap "usaglobe" minx maxx miny maxy; + (* Clear the labeling function *) + plunset_labelfunc (); + (* Polar, Northern hemisphere *) let minx = 0.0 in let maxx = 360.0 in This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |