/*
* Grace - GRaphing, Advanced Computation and Exploration of data
*
* Home page: http://plasma-gate.weizmann.ac.il/Grace/
*
* Copyright (c) 1991-1995 Paul J Turner, Portland, OR
* Copyright (c) 1996-2003 Grace Development Team
*
* Maintained by Evgeny Stambulchik
*
*
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
*
* utilities for graphs
*
*/
#include <config.h>
#include <cmath.h>
#include <stdio.h>
#include "globals.h"
#include "utils.h"
#include "draw.h"
#include "device.h"
#include "graphs.h"
#include "graphutils.h"
#include "protos.h"
extern char print_file[];
static void auto_ticks(int gno, int axis);
char *get_format_types(int f)
{
char *s;
s = "decimal";
switch (f) {
case FORMAT_DECIMAL:
s = "decimal";
break;
case FORMAT_EXPONENTIAL:
s = "exponential";
break;
case FORMAT_GENERAL:
s = "general";
break;
case FORMAT_POWER:
s = "power";
break;
case FORMAT_SCIENTIFIC:
s = "scientific";
break;
case FORMAT_ENGINEERING:
s = "engineering";
break;
case FORMAT_COMPUTING:
s = "computing";
break;
case FORMAT_DDMMYY:
s = "ddmmyy";
break;
case FORMAT_MMDDYY:
s = "mmddyy";
break;
case FORMAT_YYMMDD:
s = "yymmdd";
break;
case FORMAT_MMYY:
s = "mmyy";
break;
case FORMAT_MMDD:
s = "mmdd";
break;
case FORMAT_MONTHDAY:
s = "monthday";
break;
case FORMAT_DAYMONTH:
s = "daymonth";
break;
case FORMAT_MONTHS:
s = "months";
break;
case FORMAT_MONTHSY:
s = "monthsy";
break;
case FORMAT_MONTHL:
s = "monthl";
break;
case FORMAT_DAYOFWEEKS:
s = "dayofweeks";
break;
case FORMAT_DAYOFWEEKL:
s = "dayofweekl";
break;
case FORMAT_DAYOFYEAR:
s = "dayofyear";
break;
case FORMAT_HMS:
s = "hms";
break;
case FORMAT_MMDDHMS:
s = "mmddhms";
break;
case FORMAT_MMDDYYHMS:
s = "mmddyyhms";
break;
case FORMAT_YYMMDDHMS:
s = "yymmddhms";
break;
case FORMAT_DEGREESLON:
s = "degreeslon";
break;
case FORMAT_DEGREESMMLON:
s = "degreesmmlon";
break;
case FORMAT_DEGREESMMSSLON:
s = "degreesmmsslon";
break;
case FORMAT_MMSSLON:
s = "mmsslon";
break;
case FORMAT_DEGREESLAT:
s = "degreeslat";
break;
case FORMAT_DEGREESMMLAT:
s = "degreesmmlat";
break;
case FORMAT_DEGREESMMSSLAT:
s = "degreesmmsslat";
break;
case FORMAT_MMSSLAT:
s = "mmsslat";
break;
default:
s = "unknown";
errmsg("Internal error in get_format_types()");
break;
}
return s;
}
int wipeout(void)
{
if (!noask && is_dirtystate()) {
if (!yesno("Abandon unsaved changes?", NULL, NULL, NULL)) {
return 1;
}
}
kill_all_graphs();
do_clear_lines();
do_clear_boxes();
do_clear_ellipses();
do_clear_text();
kill_all_regions();
reset_project_version();
map_fonts(FONT_MAP_DEFAULT);
set_docname(NULL);
set_project_description(NULL);
print_file[0] = '\0';
/* a hack! the global "curtype" (as well as all others) should be removed */
curtype = SET_XY;
clear_dirtystate();
return 0;
}
/* The following routines determine default axis range and tickmarks */
static void autorange_byset(int gno, int setno, int autos_type);
static double nicenum(double x, int nrange, int round);
#define NICE_FLOOR 0
#define NICE_CEIL 1
#define NICE_ROUND 2
void autotick_axis(int gno, int axis)
{
switch (axis) {
case ALL_AXES:
auto_ticks(gno, X_AXIS);
auto_ticks(gno, ZX_AXIS);
auto_ticks(gno, Y_AXIS);
auto_ticks(gno, ZY_AXIS);
break;
case ALL_X_AXES:
auto_ticks(gno, X_AXIS);
auto_ticks(gno, ZX_AXIS);
break;
case ALL_Y_AXES:
auto_ticks(gno, Y_AXIS);
auto_ticks(gno, ZY_AXIS);
break;
default:
auto_ticks(gno, axis);
break;
}
}
void autoscale_byset(int gno, int setno, int autos_type)
{
if ((setno == ALL_SETS && is_valid_gno(gno)) || is_set_active(gno, setno)) {
autorange_byset(gno, setno, autos_type);
switch (autos_type) {
case AUTOSCALE_X:
autotick_axis(gno, ALL_X_AXES);
break;
case AUTOSCALE_Y:
autotick_axis(gno, ALL_Y_AXES);
break;
case AUTOSCALE_XY:
autotick_axis(gno, ALL_AXES);
break;
}
}
}
int autoscale_graph(int gno, int autos_type)
{
if (number_of_active_sets(gno) > 0) {
autoscale_byset(gno, ALL_SETS, autos_type);
return RETURN_SUCCESS;
} else {
return RETURN_FAILURE;
}
}
static void round_axis_limits(double *amin, double *amax, int scale)
{
double smin, smax;
int nrange;
if (*amin == *amax) {
switch (sign(*amin)) {
case 0:
*amin = -1.0;
*amax = +1.0;
break;
case 1:
*amin /= 2.0;
*amax *= 2.0;
break;
case -1:
*amin *= 2.0;
*amax /= 2.0;
break;
}
}
if (scale == SCALE_LOG) {
if (*amax <= 0.0) {
errmsg("Can't autoscale a log axis by non-positive data");
*amax = 10.0;
*amin = 1.0;
return;
} else if (*amin <= 0.0) {
errmsg("Data have non-positive values");
*amin = *amax/1.0e3;
}
smin = log10(*amin);
smax = log10(*amax);
} else if (scale == SCALE_LOGIT) {
if (*amax <= 0.0) {
errmsg("Can't autoscale a logit axis by non-positive data");
*amax = 0.9;
*amin = 0.1;
return;
} else if (*amin <= 0.0) {
errmsg("Data have non-positive values");
*amin = 0.1;
}
smin = log(*amin/(1-*amin));
smax = log(*amax/(1-*amax));
} else {
smin = *amin;
smax = *amax;
}
if (sign(smin) == sign(smax)) {
nrange = -rint(log10(fabs(2*(smax - smin)/(smax + smin))));
nrange = MAX2(0, nrange);
} else {
nrange = 0;
}
smin = nicenum(smin, nrange, NICE_FLOOR);
smax = nicenum(smax, nrange, NICE_CEIL);
if (sign(smin) == sign(smax)) {
if (smax/smin > 5.0) {
smin = 0.0;
} else if (smin/smax > 5.0) {
smax = 0.0;
}
}
if (scale == SCALE_LOG) {
*amin = pow(10.0, smin);
*amax = pow(10.0, smax);
} else if (scale == SCALE_LOGIT) {
*amin = exp(smin)/(1.0 + exp(smin));
*amax = exp(smax)/(1.0 + exp(smax));
} else {
*amin = smin;
*amax = smax;
}
}
static void autorange_byset(int gno, int setno, int autos_type)
{
world w;
double xmax, xmin, ymax, ymin;
int scale;
if (autos_type == AUTOSCALE_NONE) {
return;
}
get_graph_world(gno, &w);
if (get_graph_type(gno) == GRAPH_SMITH) {
if (autos_type == AUTOSCALE_X || autos_type == AUTOSCALE_XY) {
w.xg1 = -1.0;
w.yg1 = -1.0;
}
if (autos_type == AUTOSCALE_Y || autos_type == AUTOSCALE_XY) {
w.xg2 = 1.0;
w.yg2 = 1.0;
}
set_graph_world(gno, w);
return;
}
xmin=w.xg1;
xmax=w.xg2;
ymin=w.yg1;
ymax=w.yg2;
if (autos_type == AUTOSCALE_XY) {
getsetminmax(gno, setno, &xmin, &xmax, &ymin, &ymax);
} else if (autos_type == AUTOSCALE_X) {
getsetminmax_c(gno, setno, &xmin, &xmax, &ymin, &ymax, 2);
} else if (autos_type == AUTOSCALE_Y) {
getsetminmax_c(gno, setno, &xmin, &xmax, &ymin, &ymax, 1);
}
if (autos_type == AUTOSCALE_X || autos_type == AUTOSCALE_XY) {
scale = get_graph_xscale(gno);
round_axis_limits(&xmin, &xmax, scale);
w.xg1 = xmin;
w.xg2 = xmax;
}
if (autos_type == AUTOSCALE_Y || autos_type == AUTOSCALE_XY) {
scale = get_graph_yscale(gno);
round_axis_limits(&ymin, &ymax, scale);
w.yg1 = ymin;
w.yg2 = ymax;
}
set_graph_world(gno, w);
}
static void auto_ticks(int gno, int axis)
{
tickmarks *t;
world w;
double range, d, tmpmax, tmpmin;
int axis_scale;
t = get_graph_tickmarks(gno, axis);
if (t == NULL) {
return;
}
get_graph_world(gno, &w);
if (is_xaxis(axis)) {
tmpmin = w.xg1;
tmpmax = w.xg2;
axis_scale = get_graph_xscale(gno);
} else {
tmpmin = w.yg1;
tmpmax = w.yg2;
axis_scale = get_graph_yscale(gno);
}
if (axis_scale == SCALE_LOG) {
if (t->tmajor <= 1.0) {
t->tmajor = 10.0;
}
tmpmax = log10(tmpmax)/log10(t->tmajor);
tmpmin = log10(tmpmin)/log10(t->tmajor);
} else if (axis_scale == SCALE_LOGIT) {
if (t->tmajor >= 0.5) {
t->tmajor = 0.4;
}
tmpmax = log(tmpmax/(1-tmpmax))/log(t->tmajor/(1-t->tmajor));
tmpmin = log(tmpmin/(1-tmpmin))/log(t->tmajor/(1-t->tmajor));
} else if (t->tmajor <= 0.0) {
t->tmajor = 1.0;
}
range = tmpmax - tmpmin;
if (axis_scale == SCALE_LOG) {
d = ceil(range/(t->t_autonum - 1));
t->tmajor = pow(t->tmajor, d);
}
else if (axis_scale == SCALE_LOGIT ){
d = ceil(range/(t->t_autonum - 1));
t->tmajor = exp(d)/(1.0 + exp(d));
}
else {
d = nicenum(range/(t->t_autonum - 1), 0, NICE_ROUND);
t->tmajor = d;
}
/* alter # of minor ticks only if the current value is anomalous */
if (t->nminor < 0 || t->nminor > 10) {
if (axis_scale != SCALE_LOG) {
t->nminor = 1;
} else {
t->nminor = 8;
}
}
set_dirtystate();
}
/*
* nicenum: find a "nice" number approximately equal to x
*/
static double nicenum(double x, int nrange, int round)
{
int xsign;
double f, y, fexp, rx, sx;
if (x == 0.0) {
return(0.0);
}
xsign = sign(x);
x = fabs(x);
fexp = floor(log10(x)) - nrange;
sx = x/pow(10.0, fexp)/10.0; /* scaled x */
rx = floor(sx); /* rounded x */
f = 10*(sx - rx); /* fraction between 0 and 10 */
if ((round == NICE_FLOOR && xsign == +1) ||
(round == NICE_CEIL && xsign == -1)) {
y = (int) floor(f);
} else if ((round == NICE_FLOOR && xsign == -1) ||
(round == NICE_CEIL && xsign == +1)) {
y = (int) ceil(f);
} else { /* round == NICE_ROUND */
if (f < 1.5)
y = 1;
else if (f < 3.)
y = 2;
else if (f < 7.)
y = 5;
else
y = 10;
}
sx = rx + (double) y/10.0;
return (xsign*sx*10.0*pow(10.0, fexp));
}
/*
* set scroll amount
*/
void scroll_proc(int value)
{
scrollper = value / 100.0;
}
void scrollinout_proc(int value)
{
shexper = value / 100.0;
}
/*
* pan through world coordinates
*/
int graph_scroll(int type)
{
world w;
double xmax, xmin, ymax, ymin;
double dwc;
int gstart, gstop, i;
if (scrolling_islinked) {
gstart = 0;
gstop = number_of_graphs() - 1;
} else {
gstart = get_cg();
gstop = gstart;
}
for (i = gstart; i <= gstop; i++) {
if (get_graph_world(i, &w) == RETURN_SUCCESS) {
if (islogx(i) == TRUE) {
xmin = log10(w.xg1);
xmax = log10(w.xg2);
} else {
xmin = w.xg1;
xmax = w.xg2;
}
if (islogy(i) == TRUE) {
ymin = log10(w.yg1);
ymax = log10(w.yg2);
} else {
ymin = w.yg1;
ymax = w.yg2;
}
dwc = 1.0;
switch (type) {
case GSCROLL_LEFT:
dwc = -1.0;
case GSCROLL_RIGHT:
dwc *= scrollper * (xmax - xmin);
xmin += dwc;
xmax += dwc;
break;
case GSCROLL_DOWN:
dwc = -1.0;
case GSCROLL_UP:
dwc *= scrollper * (ymax - ymin);
ymin += dwc;
ymax += dwc;
break;
}
if (islogx(i) == TRUE) {
w.xg1 = pow(10.0, xmin);
w.xg2 = pow(10.0, xmax);
} else {
w.xg1 = xmin;
w.xg2 = xmax;
}
if (islogy(i) == TRUE) {
w.yg1 = pow(10.0, ymin);
w.yg2 = pow(10.0, ymax);
} else {
w.yg1 = ymin;
w.yg2 = ymax;
}
set_graph_world(i, w);
}
}
return RETURN_SUCCESS;
}
int graph_zoom(int type)
{
double dx, dy;
double xmax, xmin, ymax, ymin;
world w;
int gstart, gstop, gno;
if (scrolling_islinked) {
gstart = 0;
gstop = number_of_graphs() - 1;
} else {
gstart = get_cg();
gstop = gstart;
}
for (gno = gstart; gno <= gstop; gno++) {
if (get_graph_world(gno, &w) == RETURN_SUCCESS) {
if (islogx(gno) == TRUE) {
xmin = log10(w.xg1);
xmax = log10(w.xg2);
} else {
xmin = w.xg1;
xmax = w.xg2;
}
if (islogy(gno) == TRUE) {
ymin = log10(w.yg1);
ymax = log10(w.yg2);
} else {
ymin = w.yg1;
ymax = w.yg2;
}
dx = shexper * (xmax - xmin);
dy = shexper * (ymax - ymin);
if (type == GZOOM_SHRINK) {
dx *= -1;
dy *= -1;
}
xmin -= dx;
xmax += dx;
ymin -= dy;
ymax += dy;
if (islogx(gno) == TRUE) {
w.xg1 = pow(10.0, xmin);
w.xg2 = pow(10.0, xmax);
} else {
w.xg1 = xmin;
w.xg2 = xmax;
}
if (islogy(gno) == TRUE) {
w.yg1 = pow(10.0, ymin);
w.yg2 = pow(10.0, ymax);
} else {
w.yg1 = ymin;
w.yg2 = ymax;
}
set_graph_world(gno, w);
}
}
return RETURN_SUCCESS;
}
/*
* Arrange graphs
*/
int arrange_graphs(int *graphs, int ngraphs,
int nrows, int ncols, int order, int snake,
double loff, double roff, double toff, double boff,
double vgap, double hgap,
int hpack, int vpack)
{
int i, imax, j, jmax, iw, ih, ng, gno;
double pw, ph, w, h;
view v;
if (hpack) {
hgap = 0.0;
}
if (vpack) {
vgap = 0.0;
}
if (ncols < 1 || nrows < 1) {
errmsg("# of rows and columns must be > 0");
return RETURN_FAILURE;
}
if (hgap < 0.0 || vgap < 0.0) {
errmsg("hgap and vgap must be >= 0");
return RETURN_FAILURE;
}
get_page_viewport(&pw, &ph);
w = (pw - loff - roff)/(ncols + (ncols - 1)*hgap);
h = (ph - toff - boff)/(nrows + (nrows - 1)*vgap);
if (h <= 0.0 || w <= 0.0) {
errmsg("Page offsets are too large");
return RETURN_FAILURE;
}
ng = 0;
if (order & GA_ORDER_HV_INV) {
imax = ncols;
jmax = nrows;
} else {
imax = nrows;
jmax = ncols;
}
for (i = 0; i < imax && ng < ngraphs; i++) {
for (j = 0; j < jmax && ng < ngraphs; j++) {
gno = graphs[ng];
set_graph_active(gno);
if (order & GA_ORDER_HV_INV) {
iw = i;
ih = j;
if (snake && (iw % 2)) {
ih = nrows - ih - 1;
}
} else {
iw = j;
ih = i;
if (snake && (ih % 2)) {
iw = ncols - iw - 1;
}
}
if (order & GA_ORDER_H_INV) {
iw = ncols - iw - 1;
}
/* viewport y coord goes bottom -> top ! */
if (!(order & GA_ORDER_V_INV)) {
ih = nrows - ih - 1;
}
v.xv1 = loff + iw*w*(1.0 + hgap);
v.xv2 = v.xv1 + w;
v.yv1 = boff + ih*h*(1.0 + vgap);
v.yv2 = v.yv1 + h;
set_graph_viewport(gno, v);
if (hpack) {
if (iw == 0) {
tickmarks *t = get_graph_tickmarks(gno, Y_AXIS);
if (!t) {
continue;
}
t->active = TRUE;
t->label_op = PLACEMENT_NORMAL;
t->t_op = PLACEMENT_NORMAL;
t->tl_op = PLACEMENT_NORMAL;
} else {
activate_tick_labels(gno, Y_AXIS, FALSE);
}
}
if (vpack) {
if (ih == 0) {
tickmarks *t = get_graph_tickmarks(gno, X_AXIS);
if (!t) {
continue;
}
t->active = TRUE;
t->label_op = PLACEMENT_NORMAL;
t->t_op = PLACEMENT_NORMAL;
t->tl_op = PLACEMENT_NORMAL;
} else {
activate_tick_labels(gno, X_AXIS, FALSE);
}
}
ng++;
}
}
return RETURN_SUCCESS;
}
int arrange_graphs_simple(int nrows, int ncols,
int order, int snake, double offset, double hgap, double vgap)
{
int *graphs, i, ngraphs, retval;
ngraphs = nrows*ncols;
graphs = xmalloc(ngraphs*SIZEOF_INT);
if (graphs == NULL) {
return RETURN_FAILURE;
}
for (i = 0; i < ngraphs; i++) {
graphs[i] = i;
}
for (i = number_of_graphs() - 1; i >= ngraphs; i--) {
kill_graph(i);
}
retval = arrange_graphs(graphs, ngraphs, nrows, ncols, order, snake,
offset, offset, offset, offset, vgap, hgap, FALSE, FALSE);
xfree(graphs);
return retval;
}
void move_legend(int gno, VVector shift)
{
double xtmp, ytmp;
legend l;
if (is_valid_gno(gno)) {
get_graph_legend(gno, &l);
if (l.loctype == COORD_VIEW) {
l.legx += shift.x;
l.legy += shift.y;
} else {
world2view(l.legx, l.legy, &xtmp, &ytmp);
xtmp += shift.x;
ytmp += shift.y;
view2world(xtmp, ytmp, &l.legx, &l.legy);
}
set_graph_legend(gno, &l);
set_dirtystate();
}
}
void move_timestamp(VVector shift)
{
timestamp.x += shift.x;
timestamp.y += shift.y;
set_dirtystate();
}
void rescale_viewport(double ext_x, double ext_y)
{
int i, gno;
view v;
legend leg;
linetype l;
boxtype b;
ellipsetype e;
plotstr s;
for (gno = 0; gno < number_of_graphs(); gno++) {
get_graph_viewport(gno, &v);
v.xv1 *= ext_x;
v.xv2 *= ext_x;
v.yv1 *= ext_y;
v.yv2 *= ext_y;
set_graph_viewport(gno, v);
get_graph_legend(gno, &leg);
if (leg.loctype == COORD_VIEW) {
leg.legx *= ext_x;
leg.legy *= ext_y;
set_graph_legend(gno, &leg);
}
/* TODO: tickmark offsets */
}
for (i = 0; i < number_of_lines(); i++) {
get_graph_line(i, &l);
if (l.loctype == COORD_VIEW) {
l.x1 *= ext_x;
l.x2 *= ext_x;
l.y1 *= ext_y;
l.y2 *= ext_y;
set_graph_line(i, &l);
}
}
for (i = 0; i < number_of_boxes(); i++) {
get_graph_box(i, &b);
if (b.loctype == COORD_VIEW) {
b.x1 *= ext_x;
b.x2 *= ext_x;
b.y1 *= ext_y;
b.y2 *= ext_y;
set_graph_box(i, &b);
}
}
for (i = 0; i < number_of_ellipses(); i++) {
get_graph_ellipse(i, &e);
if (e.loctype == COORD_VIEW) {
e.x1 *= ext_x;
e.x2 *= ext_x;
e.y1 *= ext_y;
e.y2 *= ext_y;
set_graph_ellipse(i, &e);
}
}
for (i = 0; i < number_of_strings(); i++) {
get_graph_string(i, &s);
if (s.loctype == COORD_VIEW) {
s.x *= ext_x;
s.y *= ext_y;
set_graph_string(i, &s);
}
}
}
int overlay_graphs(int gsec, int gpri, int type)
{
int i;
tickmarks *tsec, *tpri;
world wpri, wsec;
view v;
if (gsec == gpri) {
return RETURN_FAILURE;
}
if (is_valid_gno(gpri) == FALSE || is_valid_gno(gsec) == FALSE) {
return RETURN_FAILURE;
}
get_graph_viewport(gpri, &v);
get_graph_world(gpri, &wpri);
get_graph_world(gsec, &wsec);
switch (type) {
case GOVERLAY_SMART_AXES_XY:
wsec = wpri;
for (i = 0; i < MAXAXES; i++) {
tpri = get_graph_tickmarks(gpri, i);
tsec = get_graph_tickmarks(gsec, i);
switch(i) {
case X_AXIS:
case Y_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_BOTH;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = FALSE;
break;
default:
/* don't touch alternative axes */
break;
}
}
break;
case GOVERLAY_SMART_AXES_X:
wsec.xg1 = wpri.xg1;
wsec.xg2 = wpri.xg2;
for (i = 0; i < MAXAXES; i++) {
tpri = get_graph_tickmarks(gpri, i);
tsec = get_graph_tickmarks(gsec, i);
switch(i) {
case X_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_BOTH;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = FALSE;
break;
case Y_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_NORMAL;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = TRUE;
tsec->label_op = PLACEMENT_OPPOSITE;
tsec->t_op = PLACEMENT_OPPOSITE;
tsec->tl_op = PLACEMENT_OPPOSITE;
break;
default:
/* don't touch alternative axes */
break;
}
}
break;
case GOVERLAY_SMART_AXES_Y:
wsec.yg1 = wpri.yg1;
wsec.yg2 = wpri.yg2;
for (i = 0; i < MAXAXES; i++) {
tpri = get_graph_tickmarks(gpri, i);
tsec = get_graph_tickmarks(gsec, i);
switch(i) {
case X_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_NORMAL;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = TRUE;
tsec->label_op = PLACEMENT_OPPOSITE;
tsec->t_op = PLACEMENT_OPPOSITE;
tsec->tl_op = PLACEMENT_OPPOSITE;
break;
case Y_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_BOTH;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = FALSE;
break;
default:
/* don't touch alternative axes */
break;
}
}
break;
case GOVERLAY_SMART_AXES_NONE:
for (i = 0; i < MAXAXES; i++) {
tpri = get_graph_tickmarks(gpri, i);
tsec = get_graph_tickmarks(gsec, i);
switch(i) {
case X_AXIS:
case Y_AXIS:
tpri->active = TRUE;
tpri->label_op = PLACEMENT_NORMAL;
tpri->t_op = PLACEMENT_NORMAL;
tpri->tl_op = PLACEMENT_NORMAL;
tsec->active = TRUE;
tsec->label_op = PLACEMENT_OPPOSITE;
tsec->t_op = PLACEMENT_OPPOSITE;
tsec->tl_op = PLACEMENT_OPPOSITE;
break;
default:
/* don't touch alternative axes */
break;
}
}
break;
default:
break;
}
/* set identical viewports */
set_graph_viewport(gsec, v);
/* update world coords */
set_graph_world(gsec, wsec);
return RETURN_SUCCESS;
}
syntax highlighted by Code2HTML, v. 0.9.1