[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/gnuplot/gnuplot-old/gnuplot-4-4-alpha/src/axis.h [Back]  [Original]

/*
 * $Id: axis.h,v 1.56 2009/01/31 17:21:32 vanzandt Exp $
 *
 */

/*[
 * Copyright 2000, 2004   Thomas Williams, Colin Kelley
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the complete modified source code.  Modifications are to
 * be distributed as patches to the released version.  Permission to
 * distribute binaries produced by compiling modified sources is granted,
 * provided you
 *   1. distribute the corresponding source modifications from the
 *    released version in the form of a patch file along with the binaries,
 *   2. add special version identification to distinguish your version
 *    in addition to the base release version number,
 *   3. provide your name and address as the primary contact for the
 *    support of your modified version, and
 *   4. retain our contact information in regard to use of the base
 *    software.
 * Permission to distribute the released version of the source code along
 * with corresponding source modifications in the form of a patch file is
 * granted with same provisions 2 through 4 for binary distributions.
 *
 * This software is provided "as is" without express or implied warranty
 * to the extent permitted by applicable law.
]*/

#ifndef GNUPLOT_AXIS_H
#define GNUPLOT_AXIS_H

#include "gp_types.h"		/* for TBOOLEAN */

#include "gadgets.h"
#include "parse.h"		/* for const_*() */
#include "tables.h"		/* for the axis name parse table */
#include "term_api.h"		/* for lp_style_type */
#include "util.h"		/* for int_error() */

/* typedefs / #defines */

/* give some names to some array elements used in command.c and grap*.c
 * maybe one day the relevant items in setshow will also be stored
 * in arrays.
 *
 * Always keep the following conditions alive:
 * SECOND_X_AXIS = FIRST_X_AXIS + SECOND_AXES
 * FIRST_X_AXIS & SECOND_AXES == 0
 */
typedef enum AXIS_INDEX {
#define FIRST_AXES 0
    FIRST_Z_AXIS,
    FIRST_Y_AXIS,
    FIRST_X_AXIS,
    T_AXIS,			/* fill gap */
#define SECOND_AXES 4
    SECOND_Z_AXIS,		/* not used, yet */
    SECOND_Y_AXIS,
    SECOND_X_AXIS,
    R_AXIS,			/* never used ? */
    U_AXIS,			/* ditto */
    V_AXIS			/* ditto */
    ,COLOR_AXIS
#define NO_AXIS 99
} AXIS_INDEX;

# define AXIS_ARRAY_SIZE 11

/* What kind of ticmarking is wanted? */
typedef enum en_ticseries_type {
    TIC_COMPUTED=1, 		/* default; gnuplot figures them */
    TIC_SERIES,			/* user-defined series */
    TIC_USER,			/* user-defined points */
    TIC_MONTH,   		/* print out month names ((mo-1)%12)+1 */
    TIC_DAY      		/* print out day of week */
} t_ticseries_type;

/* Defines one ticmark for TIC_USER style.
 * If label==NULL, the value is printed with the usual format string.
 * else, it is used as the format string (note that it may be a constant
 * string, like "high" or "low").
 */
typedef struct ticmark {
    double position;		/* where on axis is this */
    char *label;		/* optional (format) string label */
    int level;			/* 0=major tic, 1=minor tic */
    struct ticmark *next;	/* linked list */
} ticmark;

/* Tic-mark labelling definition; see set xtics */
typedef struct ticdef {
    t_ticseries_type type;
    char *font;
    struct t_colorspec textcolor;
    struct {
	   struct ticmark *user;	/* for TIC_USER */
	   struct {			/* for TIC_SERIES */
		  double start, incr;
		  double end;		/* ymax, if VERYLARGE */
	   } series;
	   TBOOLEAN mix;		/* TRUE to use both the above */
    } def;
    struct position offset;
    TBOOLEAN rangelimited;		/* Limit tics to data range */
} t_ticdef;

/* we want two auto modes for minitics - default where minitics are
 * auto for log/time and off for linear, and auto where auto for all
 * graphs I've done them in this order so that logscale-mode can
 * simply test bit 0 to see if it must do the minitics automatically.
 * similarly, conventional plot can test bit 1 to see if minitics are
 * required */
enum en_minitics_status {
    MINI_OFF,
    MINI_DEFAULT,
    MINI_USER,
    MINI_AUTO
};

/* Function pointer type for callback functions doing operations for a
 * single ticmark */
typedef void (*tic_callback) __PROTO((AXIS_INDEX, double, char *, struct lp_style_type ));

/* Values to put in the axis_tics[] variables that decides where the
 * ticmarks should be drawn: not at all, on one or both plot borders,
 * or the zeroaxes. These look like a series of values, but TICS_MASK
 * shows that they're actually bit masks --> don't turn into an enum
 * */
#define NO_TICS        0
#define TICS_ON_BORDER 1
#define TICS_ON_AXIS   2
#define TICS_MASK      3
#define TICS_MIRROR    4


#if 0 /* HBB 20010806 --- move GRID flags into axis struct */
/* Need to allow user to choose grid at first and/or second axes tics.
 * Also want to let user choose circles at x or y tics for polar grid.
 * Also want to allow user rectangular grid for polar plot or polar
 * grid for parametric plot. So just go for full configurability.
 * These are bitmasks
 */
#define GRID_OFF    0
#define GRID_X      (1log = 0;							\
	this->base = 1;							\
	this->log_base = 0;						\
    } else {								\
	this->log_base = this->log ? log(this->base) : 0;		\
    }									\
    this->data_min = VERYLARGE;						\
    this->data_max = -VERYLARGE;					\
} while(0)

#define AXIS_INIT2D(axis, infinite)					\
do {									\
    AXIS *this = axis_array + axis;					\
									\
    this->autoscale = this->set_autoscale;				\
    this->min = (infinite && (this->set_autoscale & AUTOSCALE_MIN))	\
	? VERYLARGE : this->set_min;					\
    this->max = (infinite && (this->set_autoscale & AUTOSCALE_MAX))	\
	? -VERYLARGE : this->set_max;					\
    this->log_base = this->log ? log(this->base) : 0;			\
    this->data_min = VERYLARGE;						\
    this->data_max = -VERYLARGE;					\
} while(0)

#ifdef VOLATILE_REFRESH
#define AXIS_INIT2D_REFRESH(axis, infinite)				\
do {									\
    AXIS *this = axis_array + axis;					\
									\
    this->autoscale = this->set_autoscale;				\
    this->min = (infinite && (this->set_autoscale & AUTOSCALE_MIN))	\
	? VERYLARGE*1e-3 : AXIS_LOG_VALUE(axis, this->set_min);		\
    this->max = (infinite && (this->set_autoscale & AUTOSCALE_MAX))	\
	? -VERYLARGE*1e-3 : AXIS_LOG_VALUE(axis, this->set_max);	\
    this->log_base = this->log ? log(this->base) : 0;			\
} while(0)
/* why multiply by 1e-3: if an already VERYLARGE x2 and y2 ranges are
   calculated after zoom-out by mouse, then they would become even larger
*/

#define AXIS_UPDATE2D_REFRESH(axis)					\
do {									\
    AXIS *this_axis = axis_array + axis;				\
    if ((this_axis->set_autoscale & AUTOSCALE_MIN) == 0)		\
	this_axis->min = AXIS_LOG_VALUE(axis, this_axis->set_min);	\
    if ((this_axis->set_autoscale & AUTOSCALE_MAX) == 0)		\
	this_axis->max = AXIS_LOG_VALUE(axis, this_axis->set_max);				\
} while (0)

#endif
/* handle reversed ranges */
#define CHECK_REVERSE(axis) do {					\
    AXIS *this = axis_array + axis;					\
									\
    if (((this->autoscale & AUTOSCALE_BOTH) == AUTOSCALE_NONE)		\
	&& (this->max < this->min)) {					\
	double temp = this->min;					\
									\
	this->min = this->max;						\
	this->max = temp;						\
	this->range_is_reverted = 1;					\
    } else								\
	this->range_is_reverted = (this->range_flags & RANGE_REVERSE);	\
} while(0)

/* HBB NEW 20050316: macros to always access the actual minimum, even
 * if 'set view map' or something else flipped things around behind
 * our back */
#define AXIS_ACTUAL_MIN(axis)				\
    (axis_array[axis].range_flags & RANGE_REVERSE	\
     ? axis_array[axis].max : axis_array[axis].min)

#define AXIS_ACTUAL_MAX(axis)				\
    (axis_array[axis].range_flags & RANGE_REVERSE	\
     ? axis_array[axis].min : axis_array[axis].max)

/* HBB 20000725: new macro, built upon ULIG's SAVE_WRITEBACK(axis),
 * but easier to use. Code like this occured twice, in plot2d and
 * plot3d: */
#define SAVE_WRITEBACK_ALL_AXES					\
do {								\
    AXIS_INDEX axis;						\
								\
    for (axis = 0; axis < AXIS_ARRAY_SIZE; axis++)		\
	if(axis_array[axis].range_flags & RANGE_WRITEBACK) {	\
	    set_writeback_min(axis);				\
	    set_writeback_max(axis);				\
	}							\
} while(0)

/* get optional [min:max] */
#define PARSE_RANGE(axis)						   \
do {									   \
    if (equals(c_token, "[")) {						   \
	c_token++;							   \
	axis_array[axis].autoscale =					   \
	    load_range(axis, &axis_array[axis].min, &axis_array[axis].max, \
		       axis_array[axis].autoscale);			   \
	if (!equals(c_token, "]"))					   \
	    int_error(c_token, "']' expected");				   \
	c_token++;							   \
    }									   \
} while (0)

/* HBB 20000430: new macro, like PARSE_RANGE, but for named ranges as
 * in 'plot [phi=3.5:7] sin(phi)' */
#define PARSE_NAMED_RANGE(axis, dummy_token)				     \
do {									     \
    if (equals(c_token, "[")) {						     \
	c_token++;							     \
	if (isletter(c_token)) {					     \
	    if (equals(c_token + 1, "=")) {				     \
		dummy_token = c_token;					     \
		c_token += 2;						     \
	    }								     \
		/* oops; probably an expression with a variable: act	     \
		 * as if no variable name had been seen, by		     \
		 * fallthrough */					     \
	}								     \
	axis_array[axis].autoscale = load_range(axis, &axis_array[axis].min, \
				      &axis_array[axis].max,		     \
				      axis_array[axis].autoscale);	     \
	if (!equals(c_token, "]"))					     \
	    int_error(c_token, "']' expected");				     \
	c_token++;							     \
    }				/* first '[' */				     \
} while (0)

/* parse a position of the form
 *    [coords] x, [coords] y {,[coords] z}
 * where coords is one of first,second.graph,screen,character
 * if first or second, we need to take axis_is_timedata into account
 */
#define GET_NUMBER_OR_TIME(store,axes,axis)				\
do {									\
    if (((axes) >= 0) && (axis_array[(axes)+(axis)].is_timedata)	\
	&& isstringvalue(c_token)) {					\
	struct tm tm;							\
	char *ss = try_to_get_string();					\
	if (gstrptime(ss,axis_array[axis].timefmt,&tm))			\
	    (store) = (double) gtimegm(&tm);				\
	free(ss);							\
    } else {								\
	(store) = real_expression();						\
    }									\
} while(0)

/* This is one is very similar to GET_NUMBER_OR_TIME, but has slightly
 * different usage: it writes out '0' in case of inparsable time data,
 * and it's used when the target axis is fixed without a 'first' or
 * 'second' keyword in front of it. */
#define GET_NUM_OR_TIME(store,axis)			\
do {							\
    (store) = 0;					\
    GET_NUMBER_OR_TIME(store, FIRST_AXES, axis);	\
} while (0);

/* store VALUE or log(VALUE) in STORE, set TYPE as appropriate
 * Do OUT_ACTION or UNDEF_ACTION as appropriate
 * adjust range provided type is INRANGE (ie dont adjust y if x is outrange
 * VALUE must not be same as STORE
 * NOAUTOSCALE is per-plot property, whereas AUTOSCALE_XXX is per-axis.
 * Note: see the particular implementation for COLOR AXIS below.
 */

#define STORE_WITH_LOG_AND_UPDATE_RANGE(STORE, VALUE, TYPE, AXIS,	  \
			        NOAUTOSCALE, OUT_ACTION, UNDEF_ACTION)	  \
do {									  \
    if (AXIS == NO_AXIS)                                                  \
	break;                                                            \
    /* HBB 20040304: new check to avoid storing infinities and NaNs */	  \
    if (! (VALUE > -VERYLARGE && VALUE < VERYLARGE)) {			  \
	TYPE = UNDEFINED;						  \
	UNDEF_ACTION;							  \
	break;								  \
    }									  \
    if (axis_array[AXIS].log) {						  \
	if (VALUElp_properties.use_palette)
int set_cbminmax __PROTO((void));

#endif /* GNUPLOT_AXIS_H */

Web Proxy Viewer  |  New URL  |  Original Page