PLplot
5.15.0
Toggle main menu visibility
Loading...
Searching...
No Matches
pldtik.c
Go to the documentation of this file.
1
// Determine tick spacing and mode (fixed or floating) of
2
// numeric axis labels.
3
//
4
// Copyright (C) 2004-2014 Alan W. Irwin
5
//
6
// This file is part of PLplot.
7
//
8
// PLplot is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU Library General Public License as published
10
// by the Free Software Foundation; either version 2 of the License, or
11
// (at your option) any later version.
12
//
13
// PLplot is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
// GNU Library General Public License for more details.
17
//
18
// You should have received a copy of the GNU Library General Public License
19
// along with PLplot; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
//
22
23
#include "
plplotP.h
"
24
25
//--------------------------------------------------------------------------
26
// void pldtik()
27
//
28
// Determine tick spacing: works out a "nice" interval (if tick == 0) such
29
// that there are between 3 and 7.5 major tick intervals in the input
30
// range vmin to vmax. The recommended number of subticks is returned in
31
// "nsubt" unless the routine is entered with a non-zero value of "nsubt".
32
// n.b. big change: now returns only positive values of tick and nsubt
33
//--------------------------------------------------------------------------
34
35
void
36
pldtik
(
PLFLT
vmin,
PLFLT
vmax,
PLFLT
*tick,
PLINT
*nsubt,
PLBOOL
ld )
37
{
38
PLFLT
t1, t2, tick_reasonable;
39
PLINT
np, ns;
40
// Unnecessarily set factor to quiet -O3 -Wuninitialized warnings.
41
PLFLT
factor = 0.0;
42
43
44
if
( ld )
45
{
46
// Check suitable units for tick spacing
47
pldtfac
( vmin, vmax, &factor, NULL );
48
49
*tick = *tick / factor;
50
vmin = vmin / factor;
51
vmax = vmax / factor;
52
}
53
54
// Magnitude of min/max difference to get tick spacing
55
56
t1 = (
PLFLT
) log10(
ABS
( vmax - vmin ) );
57
np = (
PLINT
) floor( t1 );
58
t1 = t1 - np;
59
60
// Get tick spacing.
61
62
if
( t1 > 0.7781512503 )
63
{
64
t2 = 2.0;
65
ns = 4;
66
}
67
else
if
( t1 > 0.4771212549 )
68
{
69
t2 = 1.0;
70
ns = 5;
71
}
72
else
if
( t1 > 0.1760912591 )
73
{
74
t2 = 5.0;
75
ns = 5;
76
np = np - 1;
77
}
78
else
79
{
80
t2 = 2.0;
81
ns = 4;
82
np = np - 1;
83
}
84
85
// Now compute reasonable tick spacing
86
87
tick_reasonable = t2 * pow( 10.0, (
double
) np );
88
if
( *tick == 0 )
89
{
90
*tick = t2 * pow( 10.0, (
double
) np );
91
}
92
else
93
{
94
*tick =
ABS
( *tick );
95
if
( *tick < 1.e-4 * tick_reasonable )
96
{
97
plexit
(
"pldtik: magnitude of specified tick spacing is much too small"
);
98
return
;
99
}
100
}
101
if
( *nsubt == 0 )
102
*nsubt = ns;
103
104
*nsubt =
ABS
( *nsubt );
105
106
if
( ld )
107
{
108
*tick = *tick * factor;
109
}
110
}
111
112
//--------------------------------------------------------------------------
113
// PLFLT pldtfac()
114
//
115
// Calculate factor to convert a date/time interval in seconds
116
// into a more natural units (minutes, hours, days, week, years).
117
// Also optionally calculate the sensible start time for counting ticks
118
// from (e.g. beginning of day, beginning of year).
119
// Used to calculate sensible tick and label spacings.
120
//--------------------------------------------------------------------------
121
void
122
pldtfac
(
PLFLT
vmin,
PLFLT
vmax,
PLFLT
*factor,
PLFLT
*start )
123
{
124
PLFLT
diff;
125
PLINT
year, month, day, hour,
min
;
126
PLFLT
sec;
127
128
diff = vmax - vmin;
129
130
if
( start != NULL )
131
{
132
plbtime
( &year, &month, &day, &hour, &
min
, &sec, vmin );
133
}
134
135
if
( diff < 3.0 * 60.0 )
136
{
137
// Seconds
138
*factor = 1.0;
139
if
( start != NULL )
140
{
141
sec = 0.;
142
plctime
( year, month, day, hour,
min
, sec, start );
143
}
144
}
145
else
if
( diff < 3.0 * 60.0 * 60.0 )
146
{
147
// Minutes
148
*factor = 60.0;
149
if
( start != NULL )
150
{
151
sec = 0.;
152
min
= 0;
153
plctime
( year, month, day, hour,
min
, sec, start );
154
}
155
}
156
else
if
( diff < 3.0 * 60.0 * 60.0 * 24.0 )
157
{
158
// Hours
159
*factor = 60.0 * 60.0;
160
if
( start != NULL )
161
{
162
sec = 0.;
163
min
= 0;
164
hour = 0;
165
plctime
( year, month, day, hour,
min
, sec, start );
166
}
167
}
168
else
if
( diff < 3.0 * 60.0 * 60.0 * 24.0 * 7.0 )
169
{
170
// Days
171
*factor = 60.0 * 60.0 * 24.0;
172
if
( start != NULL )
173
{
174
sec = 0.;
175
min
= 0;
176
hour = 0;
177
plctime
( year, month, day, hour,
min
, sec, start );
178
}
179
}
180
else
if
( diff < 3.0 * 60.0 * 60.0 * 24.0 * 365 )
181
{
182
// Weeks
183
*factor = 60.0 * 60.0 * 24.0 * 7.0;
184
if
( start != NULL )
185
{
186
sec = 0.;
187
min
= 0;
188
hour = 0;
189
plctime
( year, month, day, hour,
min
, sec, start );
190
}
191
}
192
else
193
{
194
// Years
195
*factor = 60.0 * 60.0 * 24.0 * 365.25;
196
if
( start != NULL )
197
{
198
sec = 0.;
199
min
= 0;
200
hour = 0;
201
day = 0;
202
month = 0;
203
plctime
( year, month, day, hour,
min
, sec, start );
204
}
205
}
206
}
207
208
//--------------------------------------------------------------------------
209
// void pldprec()
210
//
211
// Determine precision: the output variable "mode" is set to 0 if labels
212
// are to be written in floating-point format, or to 1 if they are to be
213
// written in scientific format. For mode = 1, the exponent will be
214
// placed at:
215
//
216
// top left for vertical axis on left
217
// top right for vertical axis on right
218
// bottom right for horizontal axis
219
//
220
// The digmax flag can be set by the user, and represents the maximum
221
// number of digits a label may occupy including sign and decimal point.
222
// digmin, calculated internally, is the maximum number of digits
223
// labels at vmin and vmax would occupy if floating point.
224
// If digmax<0, it is disregarded,
225
// and if digmax=0 the default value is used. For digmax>0, mode=1 is
226
// chosen if there is insufficient room for the label within the specified
227
// # of digits (digmin > digfix, where digfix is determined from digmax with
228
// fuzz factors).
229
//
230
// In the case of mode=0, the actual # of digits will become too large
231
// when the magnitude of the labels become too large. The mode=1 case
232
// offers the greatest precision for the smallest field length.
233
//
234
// The determination of maximum length for fixed point quantities is
235
// complicated by the fact that very long fixed point representations look
236
// much worse than the same sized floating point representation. Further,
237
// a fixed point number with a large negative exponent will actually gain
238
// in precision when written as floating point. Thus we use certain fuzz
239
// factors to get 'digfix' from 'digmax', however it will always be true
240
// that digfix<=digmax.
241
//
242
// Finally, if 'digmax' is set, 'prec' is reduced in size if necessary so
243
// that the labels fit the requested field length, where prec is the number of
244
// places after the decimal place.
245
//--------------------------------------------------------------------------
246
247
#define MIN_FLTDIG 3
// disregarded if fractional part is 0
248
#define DIGMAX_DEF 5
249
250
void
251
pldprec
(
PLFLT
vmin,
PLFLT
vmax,
PLFLT
tick,
PLINT
lf,
252
PLINT
*mode,
PLINT
*prec,
PLINT
digmax,
PLINT
*scale )
253
{
254
PLFLT
chosen, notchosen, vmod, t0;
255
PLINT
msd, notmsd, np, digmin, digfix;
256
257
*mode = 0;
258
*scale = 0;
259
260
// Default xdigmax, ydigmax and zdigmax set in c_plinit so this is
261
// only an emergency measure in case of some internal PLplot
262
// logic error.
263
if
( digmax == 0 )
264
digmax =
DIGMAX_DEF
;
265
// No modification of digfix from digmax value.
266
digfix = digmax;
267
// Choose vmin or vmax depending on magnitudes of vmin and vmax.
268
chosen = (
ABS
( vmax ) >=
ABS
( vmin ) ) ? vmax : vmin;
269
notchosen = (
ABS
( vmax ) >=
ABS
( vmin ) ) ? vmin : vmax;
270
// Magnitute of chosen to get number of significant digits
271
272
if
(
ABS
( chosen ) > 0. )
273
{
274
vmod =
ABS
( chosen );
275
t0 = (
PLFLT
) log10( vmod );
276
msd = (
PLINT
) floor( t0 );
277
}
278
else
279
{
280
// this branch occurs only when 0. --- 0. range put in
281
vmod = 1.;
282
t0 = (
PLFLT
) log10( vmod );
283
msd = (
PLINT
) floor( t0 );
284
}
285
286
if
(
ABS
( notchosen ) > 0. )
287
notmsd = (
PLINT
) floor( (
PLFLT
) log10(
ABS
( notchosen ) ) );
288
else
289
notmsd = msd;
290
// Autoselect the mode flag
291
// 'digmin' is the minimum number of places taken up by the label
292
293
if
( msd >= 0 )
294
{
295
// n.b. no decimal point in the minimal case
296
digmin = msd + 1;
297
}
298
else
299
{
300
// adjust digmin to account for leading 0 and decimal point
301
digmin = -msd + 2;
302
}
303
// adjust digmin to account for sign on the chosen end of axis or sign on the
304
// nonchosen end of axis if notmsd = msd or (msd <= 0 and notmsd < 0)
305
// For the latter case the notchosen label starts with "-0."
306
// For checking for the latter case, the notmsd < 0 condition is redundant
307
// since notmsd <= msd always and the equal part is selected by the first
308
// condition.
309
//
310
if
( chosen < 0. || ( notchosen < 0. && ( notmsd == msd || msd <= 0 ) ) )
311
digmin = digmin + 1;
312
313
if
( digmin > digfix && !lf )
314
{
315
*mode = 1;
316
*scale = msd;
317
}
318
319
// Establish precision.
320
// It must be fine enough to resolve the tick spacing
321
322
np = (
PLINT
) floor( log10(
ABS
( tick ) ) );
323
324
if
( *mode != 0 )
325
*prec = msd - np;
326
else
327
*prec =
MAX
( -np, 0 );
328
329
// One last hack required: if exponent < 0, i.e. number has leading '0.',
330
// it's better to change to floating point form if the number of digits
331
// is insufficient to represent the tick spacing.
332
//
333
if
( *mode == 0 && digmax > 0 && !lf )
334
{
335
if
( t0 < 0.0 )
336
{
337
if
( digmax - 2 - *prec < 0 )
338
{
339
*mode = 1;
340
*scale = msd;
341
}
342
}
343
else
344
*prec =
MAX
(
MIN
( *prec, digmax - msd - 1 ), 0 );
345
}
346
if
( *mode != 0 )
347
{
348
*prec = msd - np;
349
*prec =
MAX
(
MIN
( *prec,
MAX
( digmax - 1,
MIN_FLTDIG
) ), 0 );
350
}
351
}
MIN
#define MIN(a, b)
Definition
dsplint.c:29
MAX
#define MAX(a, b)
Definition
dsplint.c:28
min
#define min(x, y)
Definition
nnpi.c:87
plexit
void plexit(PLCHAR_VECTOR errormsg)
Definition
plctrl.c:1958
pldtik
void pldtik(PLFLT vmin, PLFLT vmax, PLFLT *tick, PLINT *nsubt, PLBOOL ld)
Definition
pldtik.c:36
DIGMAX_DEF
#define DIGMAX_DEF
Definition
pldtik.c:248
pldprec
void pldprec(PLFLT vmin, PLFLT vmax, PLFLT tick, PLINT lf, PLINT *mode, PLINT *prec, PLINT digmax, PLINT *scale)
Definition
pldtik.c:251
pldtfac
void pldtfac(PLFLT vmin, PLFLT vmax, PLFLT *factor, PLFLT *start)
Definition
pldtik.c:122
MIN_FLTDIG
#define MIN_FLTDIG
Definition
pldtik.c:247
plplotP.h
ABS
#define ABS(a)
Definition
plplotP.h:199
PLFLT
float PLFLT
Definition
plplot.h:163
plctime
#define plctime
Definition
plplot.h:708
PLINT
int PLINT
Definition
plplot.h:181
PLBOOL
PLINT PLBOOL
Definition
plplot.h:204
plbtime
#define plbtime
Definition
plplot.h:699
src
pldtik.c
Generated on
for PLplot by
1.17.0