1 /*--------------------------------------------------------------------
2  *
3  *	Copyright (c) 1991-2021 by the GMT Team (https://www.generic-mapping-tools.org/team.html)
4  *	See LICENSE.TXT file for copying and redistribution conditions.
5  *
6  *	This program is free software; you can redistribute it and/or modify
7  *	it under the terms of the GNU Lesser General Public License as published by
8  *	the Free Software Foundation; version 3 or any later version.
9  *
10  *	This program is distributed in the hope that it will be useful,
11  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *	GNU Lesser General Public License for more details.
14  *
15  *	Contact info: www.generic-mapping-tools.org
16  *--------------------------------------------------------------------*/
17 /*
18  * Include file for programs that use the map-projections functions.  Note
19  * that most programs will include this by including gmt_dev.h
20  *
21  * Author:	Paul Wessel
22  * Date:	1-JAN-2010
23  * Version:	6 API
24  *
25  */
26 
27 /*!
28  * \file gmt_project.h
29  * \brief Include file for programs that use the map-projections functions.
30  */
31 
32 #ifndef GMT_PROJECT_H
33 #define GMT_PROJECT_H
34 
35 #define HALF_DBL_MAX (DBL_MAX/2.0)
36 
37 /*! GMT_180 is used to see if a value really is exceeding it (beyond roundoff) */
38 #define GMT_180	(180.0 + GMT_CONV8_LIMIT)
39 /*! gmt_M_wind_lon will remove central meridian value and adjust so lon fits between -180/+180 */
40 #define gmt_M_wind_lon(C,lon) {lon -= C->current.proj.central_meridian; while (lon < -GMT_180) lon += 360.0; while (lon > +GMT_180) lon -= 360.0;}
41 
42 /*! Some shorthand notation for GMT specific cases */
43 EXTERN_MSC double gmtmap_lat_swap_quick (struct GMT_CTRL *GMT, double lat, double c[]);
44 
45 #define gmt_M_latg_to_latc(C,lat) gmtmap_lat_swap_quick (C, lat, C->current.proj.lat_swap_vals.c[GMT_LATSWAP_G2C])
46 #define gmt_M_latg_to_lata(C,lat) gmtmap_lat_swap_quick (C, lat, C->current.proj.lat_swap_vals.c[GMT_LATSWAP_G2A])
47 #define gmt_M_latc_to_latg(C,lat) gmtmap_lat_swap_quick (C, lat, C->current.proj.lat_swap_vals.c[GMT_LATSWAP_C2G])
48 #define gmt_M_lata_to_latg(C,lat) gmtmap_lat_swap_quick (C, lat, C->current.proj.lat_swap_vals.c[GMT_LATSWAP_A2G])
49 
50 /*! Macros returns true if the two coordinates are lon/lat; way should be GMT_IN or GMT_OUT */
51 #define gmt_M_x_is_lon(C,way) (C->current.io.col_type[way][GMT_X] & GMT_IS_LON)
52 #define gmt_M_y_is_lon(C,way) (C->current.io.col_type[way][GMT_Y] & GMT_IS_LON)
53 #define gmt_M_x_is_lat(C,way) (C->current.io.col_type[way][GMT_X] & GMT_IS_LAT)
54 #define gmt_M_y_is_lat(C,way) (C->current.io.col_type[way][GMT_Y] & GMT_IS_LAT)
55 #define gmt_M_is_geographic(C,way) (gmt_M_x_is_lon(C,way) && gmt_M_y_is_lat(C,way))
56 #define gmt_M_is_cartesian(C,way) (!gmt_M_is_geographic(C,way))
57 
58 #define GMT_N_PROJECTIONS	29	/* Total number of projections in GMT */
59 
60 /* These numbers should remain flexible. Do not use them in any programming. Use only their symbolic names.
61    However, all the first items in each section (i.e. GMT_LINEAR, GMT_MERCATOR,...) should remain the first.
62 */
63 #define GMT_NO_PROJ		-1	/* Projection not specified (initial value) */
64 
65 /*! Linear projections tagged 0-99 */
66 #define gmt_M_is_linear(C) (C->current.proj.projection / 100 == 0)
67 
68 enum gmt_enum_annot {GMT_LINEAR = 0,
69 	GMT_LOG10,	/* These numbers are only used for GMT->current.proj.xyz_projection[3], */
70 	GMT_POW,	/* while GMT->current.proj.projection = 0 */
71 	GMT_TIME,
72 	GMT_ANNOT_CPT,
73 	GMT_CUSTOM};
74 
75 #define GMT_ZAXIS		50
76 
77 /*! Cylindrical projections tagged 100-199 */
78 #define gmt_M_is_cylindrical(C) (C->current.proj.projection / 100 == 1)
79 
80 enum gmt_enum_cyl {GMT_MERCATOR = 100,
81 	GMT_CYL_EQ,
82 	GMT_CYL_EQDIST,
83 	GMT_CYL_STEREO,
84 	GMT_MILLER,
85 	GMT_TM,
86 	GMT_UTM,
87 	GMT_CASSINI,
88 	GMT_OBLIQUE_MERC = 150,
89 	GMT_OBLIQUE_MERC_POLE};
90 
91 /*! Conic projections tagged 200-299 */
92 #define gmt_M_is_conical(C) (C->current.proj.projection / 100 == 2)
93 
94 enum gmt_enum_conic {GMT_ALBERS = 200,
95 	GMT_ECONIC,
96 	GMT_POLYCONIC,
97 	GMT_LAMBERT = 250};
98 
99 /* Azimuthal projections tagged 300-399 */
100 #define gmt_M_is_azimuthal(C) (C->current.proj.projection / 100 == 3)
101 #define gmt_M_is_perspective(C) (C->current.proj.projection == GMT_ORTHO || C->current.proj.projection == GMT_GENPER)
102 enum gmt_enum_azim {GMT_STEREO = 300,
103 	GMT_LAMB_AZ_EQ,
104 	GMT_ORTHO,
105 	GMT_AZ_EQDIST,
106 	GMT_GNOMONIC,
107 	GMT_GENPER,
108 	GMT_POLAR = 350};
109 
110 /* Misc projections tagged 400-499 */
111 #define gmt_M_is_misc(C) (C->current.proj.projection / 100 == 4)
112 enum gmt_enum_misc {GMT_MOLLWEIDE = 400,
113 	GMT_HAMMER,
114 	GMT_SINUSOIDAL,
115 	GMT_VANGRINTEN,
116 	GMT_ROBINSON,
117 	GMT_ECKERT4,
118 	GMT_ECKERT6,
119 	GMT_WINKEL};
120 
121 /* All projections from proj.4 lib */
122 enum gmt_enum_allprojs {GMT_PROJ4_PROJS = 500};
123 
124 /*! The various GMT measurement units */
125 enum gmt_enum_units {GMT_IS_METER = 0,
126 	GMT_IS_KM,
127 	GMT_IS_MILE,
128 	GMT_IS_NAUTICAL_MILE,
129 	GMT_IS_INCH,
130 	GMT_IS_CM,
131 	GMT_IS_PT,
132 	GMT_IS_FOOT,
133 	GMT_IS_SURVEY_FOOT,
134 	GMT_N_UNITS,
135 	GMT_IS_NOUNIT = -1};
136 
137 /* For annotating radial polar axes */
138 enum GMT_enum_zdown {GMT_ZDOWN_R = 0,	/* Default: Annotating radius */
139 	GMT_ZDOWN_Z		= 1,	/* Annotating north - r */
140 	GMT_ZDOWN_ZP	= 2,	/* Annotating planetary radius - r */
141 	GMT_ZDOWN_ZR	= 3};	/* Annotating given radius - r */
142 
143 /* For drawing the 3-D backboard */
144 enum GMT_enum_3Dmode {
145 	GMT_3D_NONE = 0,	/* Default: No 3-D backboard */
146 	GMT_3D_WALL	= 1,	/* Draw the backboard */
147 	GMT_3D_BOX	= 2};	/* Draw the backboard and the 3-D wire box */
148 
149 /* gmt_M_is_periodic means the east and west meridians of a global map are separated */
150 #define gmt_M_is_periodic(C) (gmt_M_is_cylindrical (C) || gmt_M_is_misc (C))
151 
152 /* gmt_M_is_rect_graticule means parallels and meridians are orthogonal, but does not imply linear spacing */
153 #define gmt_M_is_rect_graticule(C) (C->current.proj.projection <= GMT_MILLER)
154 
155 /* gmt_M_is_nonlinear_graticule means parallels and meridians are not orthogonal or have nonlinear spacing */
156 #define gmt_M_is_nonlinear_graticule(C)	(!(C->current.proj.projection == GMT_CYL_EQDIST || C->current.proj.projection == GMT_LINEAR) || \
157 	C->current.proj.xyz_projection[GMT_X] == GMT_LOG10 || C->current.proj.xyz_projection[GMT_X] == GMT_POW || \
158 	C->current.proj.xyz_projection[GMT_Y] == GMT_LOG10 || C->current.proj.xyz_projection[GMT_Y] == GMT_POW)
159 
160 #define gmt_M_is_spherical(C) (C->current.setting.ref_ellipsoid[C->current.setting.proj_ellipsoid].flattening < 1.0e-10)
161 #define gmt_M_is_flatearth(C) (!strcmp (C->current.setting.ref_ellipsoid[C->current.setting.proj_ellipsoid].name, "FlatEarth"))
162 
163 /* Return 0 for Flat Earth, 1 for Great-circles, 2 for geodesics, and 3 for loxodromes */
164 #define gmt_M_sph_mode(C) (gmt_M_is_flatearth (C) ? GMT_FLATEARTH : (gmt_M_is_spherical (C) ? GMT_GREATCIRCLE : (C->current.map.loxodrome ? GMT_LOXODROME : GMT_GEODESIC)))
165 
166 //#define gmt_M_360_range(w,e) (doubleAlmostEqual (fabs((e) - (w)), 360.0))	/* PW: Reconsider this later perhaps but for now too tight [see issue #954] */
167 #define gmt_M_180_range(s,n) (doubleAlmostEqual (fabs((n) - (s)), 180.0))
168 #define gmt_M_360_range(w,e) (gmt_M_is_zero (fabs ((e) - (w)) - 360.0))
169 #define gmt_M_is_pole(y) (doubleAlmostEqual (fabs(y), 90.0))
170 #define gmt_M_is_Npole(y) (gmt_M_is_zero(y-90.0))
171 #define gmt_M_is_Spole(y) (gmt_M_is_zero(y+90.0))
172 #define gmt_M_is_zero(x) (fabs (x) < GMT_CONV8_LIMIT)
173 
174 #ifndef D2R
175 #define D2R (M_PI / 180.0)
176 #endif
177 #ifndef R2D
178 #define R2D (180.0 / M_PI)
179 #endif
180 
181 /* UTM offsets */
182 
183 #define GMT_FALSE_EASTING    500000.0
184 #define GMT_FALSE_NORTHING 10000000.0
185 
186 /* Number of proj4 look-ups */
187 
188 #define GMT_N_PROJ4 31
189 
190 /* Number of nodes in Robinson interpolation */
191 
192 #define GMT_N_ROBINSON	19
193 
194 struct GMT_LATSWAP_CONSTS {
195 	double  c[GMT_LATSWAP_N][4];	/* Coefficients in 4-term series  */
196 	double	ra;			/* Authalic   radius (sphere for equal-area)  */
197 	double	rm;			/* Meridional radius (sphere for N-S distance)  */
198 	bool spherical;			/* True if no conversions need to be done.  */
199 };
200 
201 struct GMT_THREE_D {
202 	double view_azimuth, view_elevation;
203 	double cos_az, sin_az, cos_el, sin_el;
204 	double corner_x[4], corner_y[4];
205 	double xmin, xmax, ymin, ymax;
206 	double world_x, world_y, world_z;	/* Users coordinates of fixed point */
207 	double view_x, view_y;			/* Desired projected 2-D coordinates of fixed point */
208 	double x_off, y_off;			/* Offsets to the final projected coordinates */
209 	double sign[4];		/* Used to determine direction of tickmarks etc */
210 	double level;		/* Indicates the last level of the perspective plane (if any) */
211 	unsigned int view_plane;	/* Determines on which plane needs to be projected */
212 	int plane;		/* Indicates which last plane was plotted in perspective (-1 = none) */
213 	unsigned int quadrant;	/* quadrant we're looking from */
214 	unsigned int z_axis;	/* Which z-axis to draw. */
215 	unsigned int face[3];	/* Tells if this facet has normal in pos direction */
216 	bool draw[4];		/* axes to draw */
217 	bool fixed;		/* true if we want a given point to be fixed in the projection [for animations] */
218 	bool world_given;	/* true if a fixed world point was given in -E ..+glon/lat/z */
219 	bool view_given;	/* true if a fixed projected point was given in -E ..+cx0/y0 */
220 };
221 
222 struct GMT_DATUM {	/* Main parameter for a particular datum */
223 	double a, b, f, e_squared, ep_squared;
224 	double xyz[7];
225 	int ellipsoid_id;	/* Ellipsoid GMT ID number (or -1) */
226 };
227 
228 struct GMT_DATUM_CONV {
229 	bool h_given;		/* true if we have incoming height data [h = 0] */
230 	double da;		/* Major semi-axis in meters */
231 	double df;		/* Flattening */
232 	double e_squared;	/* Eccentricity squared (e^2 = 2*f - f*f) */
233 	double one_minus_f;	/* 1 - f */
234 	double dxyz[3];		/* Ellipsoids offset in meter from Earth's center of mass for x,y, and z */
235 	double bursa[7];	/* Bursa-Wolf seven parameters */
236 	struct GMT_DATUM from, to;	/* The old and new datums */
237 };
238 
239 struct GMT_PROJ4 {	/* Used to assign proj4 projections from GMT projections */
240 	char *name;
241 	unsigned int id;
242 };
243 
244 struct GMT_PROJ {
245 
246 	struct GMT_THREE_D z_project;
247 	struct GMT_DATUM_CONV datum;	/* For datum conversions */
248 	struct GMT_PROJ4 *proj4;	/* A read-only resource we allocate once and pass pointer around */
249 	void (*fwd) (struct GMT_CTRL *, double, double, double *, double *);/* Pointers to the selected forward mapping function */
250 	void (*inv) (struct GMT_CTRL *, double *, double *, double, double);/* Pointers to the selected inverse mapping function */
251 	void (*fwd_x) (struct GMT_CTRL *, double, double *);	/* Pointers to the selected linear x forward function */
252 	void (*fwd_y) (struct GMT_CTRL *, double, double *);	/* Pointers to the selected linear y forward function */
253 	void (*fwd_z) (struct GMT_CTRL *, double, double *);	/* Pointers to the selected linear z forward function */
254 	void (*inv_x) (struct GMT_CTRL *, double *, double);	/* Pointers to the selected linear x inverse function */
255 	void (*inv_y) (struct GMT_CTRL *, double *, double);	/* Pointers to the selected linear y inverse function */
256 	void (*inv_z) (struct GMT_CTRL *, double *, double);	/* Pointers to the selected linear z inverse function */
257 
258 	double pars[16];		/* Raw unprocessed map-projection parameters as passed on command line */
259 	double z_pars[2];		/* Raw unprocessed z-projection parameters as passed on command line */
260 
261 	/* Common projection parameters */
262 
263 	int projection;		/* Gives the id number for the projection used (-1 if not set) */
264 	int projection_GMT;	/* A copy of the above to use when using the Proj.4 lib for coord/map transforms */
265 	int autoscl[2];		/* If +1 then set x/y-scale to y/x-scale and compute height/width, -1 reverses direction */
266 	int corner[4];		/* In/on/out status of map corners w.r.t. current polygon for -R...+r regions */
267 
268 	bool search;		/* true if we are allowed to search along oblique boundary for min/max lon/lats */
269 	bool units_pr_degree;	/* true if scale is given as inch (or cm)/degree.  false for 1:xxxxx */
270 	bool north_pole;		/* true if projection is on northern hemisphere, false on southern */
271 	bool pole_in_map[2];		/* true if S and N poles are inside the domain of an oblique projection */
272 	bool edge[4];		/* true if the edge is a map boundary */
273 	bool three_D;		/* Parameters for 3-D projections */
274 	bool JZ_set;		/* true if -Jz|Z was set */
275 	bool GMT_convert_latitudes;	/* true if using spherical code with authalic/conformal latitudes */
276 	bool inv_coordinates;	/* true if -fp[unit] was given and we must first recover lon,lat during reading */
277 	bool N_hemi;		/* true if we only allow northern hemisphere oblique Mercator poles */
278 	bool sph_inside;	/* true is we must use the spherical in-on-out machinery [false = Cartesian] */
279 	bool obl_flip;	/* true is we want the oblique equator to be the vertical axis [horizontal] */
280 	unsigned int n_antipoles;	/* Number of antipole coordinates so far [used for -JE only] */
281 	struct GMT_LATSWAP_CONSTS lat_swap_vals;
282 
283 	enum gmt_enum_units inv_coord_unit;		/* Index to scale that converts input map coordinates to meter before inverting for lon,lat */
284 	char unit_name[GMT_N_UNITS][GMT_LEN16];	/* Names of the various distance units */
285 	double m_per_unit[GMT_N_UNITS];	/* Meters in various units.  Use to scale units to meters */
286 	double origin[3];		/* Projected values of the logical origin for the projection (x, y, z) */
287 	double rect[4], zmin, zmax;	/* Extreme projected values */
288 	double rect_m[4];		/* Extreme projected original meter values */
289 	double scale[3];		/* Scaling for meters to map-distance (typically inch) conversion (x, y, z) */
290 	double i_scale[3];		/* Inverse Scaling for meters to map-distance (typically inch) conversion (x, y, z) */
291 	double z_level;			/* Level at which to draw basemap [0] */
292 	double unit;			/* Gives meters pr plot unit (0.01 or 0.0254) */
293 	double central_meridian;	/* Central meridian for projection [NaN] */
294 	double lon0, lat0;		/* Projection center [NaN/NaN if not specified in -J] */
295 	double pole;			/* +90 pr -90, depending on which pole */
296 	double mean_radius;		/* Mean radius given the PROJ_* settings */
297 	double EQ_RAD, i_EQ_RAD;	/* Current ellipsoid parameters */
298 	double ECC, ECC2, ECC4, ECC6;	/* Powers of eccentricity */
299 	double M_PR_DEG, KM_PR_DEG;	/* Current spherical approximations to convert degrees to dist */
300 	double DIST_M_PR_DEG;		/* Current spherical approximations to convert degrees to m even if -J was not set */
301 	double DIST_KM_PR_DEG;		/* Current spherical approximations to convert degrees to km even if -J was not set */
302 	double half_ECC, i_half_ECC;	/* 0.5 * ECC and 0.5 / ECC */
303 	double one_m_ECC2, i_one_m_ECC2; /* 1.0 - ECC2 and inverse */
304 	unsigned int gave_map_width;	/* nonzero if map width (1), height (2), max dim (3) or min dim (4) is given instead of scale.  0 for 1:xxxxx */
305 
306 	uint64_t n_geodesic_calls;	/* Number of calls for geodesics in this session */
307 	uint64_t n_geodesic_approx;	/* Number of calls for geodesics in this session that exceeded iteration limit */
308 
309 	double f_horizon, rho_max;	/* Azimuthal horizon (deg) and in plot coordinates */
310 
311 	/* Linear plot parameters */
312 
313 	unsigned int xyz_projection[3];	/* For linear projection, 0 = linear, 1 = log10, 2 = pow */
314 	bool xyz_pos[3];		/* true if x,y,z-axis increases in normal positive direction */
315 	bool compute_scale[3];	/* true if axes lengths were set rather than scales */
316 	double xyz_pow[3];		/* For GMT_POW projection */
317 	double xyz_ipow[3];
318 	double VE;				/* Vertical exaggeration for x-z plots */
319 
320 	/* Center of radii for all conic projections */
321 
322 	double c_x0, c_y0;
323 
324 	/* Lambert conformal conic parameters. */
325 
326 	double l_N, l_i_N, l_Nr, l_i_Nr;
327 	double l_F, l_rF, l_i_rF;
328 	double l_rho0;
329 
330 	/* Oblique Mercator Projection (Spherical version )*/
331 
332 	double o_sin_pole_lat, o_cos_pole_lat;	/* Pole of rotation */
333 	double o_pole_lon, o_pole_lat;	/* In degrees */
334 	double o_beta;			/* lon' = beta for central_meridian (degrees) */
335 	double o_shift;			/* Projected distance between oblique equator and chosen oblique latitude */
336 	bool o_spole;			/* True if pole is in the southern hemisphere */
337 	double o_FP[3], o_FC[3], o_IP[3], o_IC[3];
338 
339 	/* TM and UTM Projections */
340 
341 	double t_lat0;
342 	double t_e2, t_M0;
343 	double t_c1, t_c2, t_c3, t_c4;
344 	double t_i1, t_i2, t_i3, t_i4, t_i5;
345 	double t_r, t_ir;		/* Short for GMT->current.proj.EQ_RAD * GMT->current.setting.proj_scale_factor and its inverse */
346 	int utm_hemisphere;	/* -1 for S, +1 for N, 0 if to be set by -R */
347 	unsigned int utm_zonex;	/* The longitude component 1-60 */
348 	char utm_zoney;			/* The latitude component A-Z */
349 
350 	/* Lambert Azimuthal Equal-Area Projection */
351 
352 	double sinp;
353 	double cosp;
354 	double Dx, Dy, iDx, iDy;	/* Fudge factors for projections w/authalic lats */
355 
356 	/* Stereographic Projection */
357 
358 	double s_c, s_ic;
359 	double r;		/* Radius of projected sphere in plot units (inch or cm) */
360 	bool polar;		/* True if projection pole coincides with S or N pole */
361 
362 	/* Mollweide, Hammer-Aitoff and Winkel Projection */
363 
364 	double w_x, w_y, w_iy, w_r;
365 
366 	/* Winkel Tripel Projection */
367 
368 	double r_cosphi1;	/* = cos (50.467) */
369 
370 	/* Robinson Projection */
371 
372 	double n_cx, n_cy;	/* = = 0.8487R, 1.3523R */
373 	double n_i_cy;
374 	double n_phi[GMT_N_ROBINSON], n_X[GMT_N_ROBINSON], n_Y[GMT_N_ROBINSON];
375 	double n_x_coeff[3*GMT_N_ROBINSON], n_y_coeff[3*GMT_N_ROBINSON], n_yx_coeff[3*GMT_N_ROBINSON], n_iy_coeff[3*GMT_N_ROBINSON];
376 
377 	/* Eckert IV Projection */
378 
379 	double k4_x, k4_y, k4_ix, k4_iy;
380 
381 	/* Eckert VI Projection */
382 
383 	double k6_r, k6_ir;
384 
385 	/* Cassini Projection */
386 
387 	double c_M0, c_c1, c_c2, c_c3, c_c4;
388 	double c_i1, c_i2, c_i3, c_i4, c_i5, c_p;
389 
390 	/* All Cylindrical Projections */
391 
392 	double j_x, j_y, j_ix, j_iy, j_yc;
393 
394 	/* Albers Equal-area conic parameters. */
395 
396 	double a_n, a_i_n;
397 	double a_C, a_n2ir2, a_test, a_Cin;
398 	double a_rho0;
399 
400 	/* Equidistant conic parameters. */
401 
402 	double d_n, d_i_n;
403 	double d_G, d_rho0;
404 
405 	/* Van der Grinten parameters. */
406 
407 	double v_r, v_ir;
408 
409 	/* General Perspective parameters */
410 	double g_H, g_R;
411 	double g_P, g_P_inverse;
412 	double g_lon0;
413 	double g_sphi1, g_cphi1;
414 	double g_phig, g_sphig, g_cphig;
415 	double g_sdphi, g_cdphi;
416 	double g_B, g_D, g_L, g_G, g_J;
417 	double g_BLH, g_DG, g_BJ, g_DHJ, g_LH2, g_HJ;
418 	double g_sin_tilt, g_cos_tilt;
419 	double g_azimuth, g_sin_azimuth, g_cos_azimuth;
420 	double g_sin_twist, g_cos_twist;
421 	double g_width;
422 	double g_yoffset;
423 	double g_rmax;
424 	double g_max_yt;
425 	double g_xmin, g_xmax;
426 	double g_ymin, g_ymax;
427 
428 	unsigned int g_debug;
429 	bool g_box, g_outside, g_longlat_set, g_sphere, g_radius, g_geosync, g_earth_radius;
430 	bool windowed;
431 
432 	/* Polar (cylindrical) projection */
433 
434 	double p_base_angle, flip_radius, radial_offset, z_radius;
435 	bool got_azimuths, got_elevations, flip;
436 	enum GMT_enum_zdown z_down;
437 	unsigned int angle_kind;	/* 0 = angle, 4 = longitude, 2 = latitude (for annotation purposes) */
438 
439 	/* PROJ4 variables */
440 	double proj4_x0, proj4_y0, proj4_scl;
441 	bool is_proj4;
442 	bool proj4_is_cart[2];	/* Fist is for origin ref sys and second (if requested) for destiny */
443 };
444 
445 enum GMT_enum_frame {GMT_IS_PLAIN = 0,	/* Plain baseframe */
446 	GMT_IS_INSIDE	= 1,	/* Plain frame ticks/annotations on the inside of boundary */
447 	GMT_IS_GRAPH	= 2,	/* Plain fram with arrow extensions on axes */
448 	GMT_IS_FANCY	= 4,	/* Fancy baseframe */
449 	GMT_IS_ROUNDED	= 12};	/* Fancy baseframe, rounded */
450 
451 /* Define the 6 axis items that each axis can have (some are mutually exclusive: only one ANNOT/INTV for upper and lower) */
452 
453 enum GMT_enum_tick {GMT_ANNOT_UPPER = 0,	/* Tick annotations closest to the axis */
454 	GMT_ANNOT_LOWER,	/* Tick annotations farthest from the axis*/
455 	GMT_TICK_UPPER,		/* Frame tick marks closest to the axis */
456 	GMT_TICK_LOWER,		/* Frame tick marks farthest to the axis */
457 	GMT_GRID_UPPER,		/* Gridline spacing */
458 	GMT_GRID_LOWER};	/* Gridline spacing */
459 
460 /* Some convenient macros for axis routines */
461 
462 
463 /* The array side in GMT_PLOT_FRAME follows the order south, east, north, west (CCW loop) + z.
464  * Ro avoid using confusing indices 0-4 we define very brief constants S_SIDE, E_SIDE, N_SIDE
465  * W_SIDE and Z_SIDE that should be used instead. */
466 
467 #ifndef S_SIDE
468 #define S_SIDE 0
469 #endif
470 #ifndef E_SIDE
471 #define E_SIDE 1
472 #endif
473 #ifndef N_SIDE
474 #define N_SIDE 2
475 #endif
476 #ifndef W_SIDE
477 #define W_SIDE 3
478 #endif
479 #ifndef Z_SIDE
480 #define Z_SIDE 4
481 #endif
482 
483 struct GMT_PLOT_AXIS_ITEM {		/* Information for one type of tick/annotation */
484 	double interval;		/* Distance between ticks in user units */
485 	unsigned int parent;		/* Id of axis this item belongs to (0,1,2) */
486 	bool active;			/* true if we want to use this item */
487 	bool generated;			/* true if this is an auto-generated interval */
488 	bool special;			/* true if custom interval annotations */
489 	unsigned int flavor;		/* Index into month/day name abbreviation array (0-2) */
490 	bool upper_case;		/* true if we want upper case text (used with flavor) */
491 	char type;			/* One of a, A, i, I, f, F, g, G */
492 	char unit;			/* User's interval unit (y, M, u, d, h, m, c) */
493 };
494 
495 struct GMT_PLOT_AXIS {		/* Information for one time axis */
496 	unsigned int id;		/* 0 (x), 1(y), or 2(z) */
497 	unsigned int type;		/* GMT_LINEAR, GMT_LOG10, GMT_POW, GMT_TIME */
498 	unsigned int special;		/* See gmt_enum_annot values */
499 	unsigned int label_mode;	/* 0 = parallel to all axes, 1 = always horizontal on map */
500 	bool substitute_pi;		/* True if we need to plot fractions of pi on this axis */
501 	bool use_angle;			/* True if we got +a<angle>|n|p for this axis */
502 	bool skip[2];			/* Determines if we skip annotations at the lower or upper bounds of an axis [false/false] */
503 	struct GMT_PLOT_AXIS_ITEM item[8];	/* see above defines for which is which */
504 	double phase;			/* Phase offset for strides: (knot-phase)%interval = 0  */
505 	double angle;			/* Annotations angle set by user */
506 	char label[GMT_LEN256];		/* Label of the axis */
507 	char secondary_label[GMT_LEN256];	/* Optionally use this label when axis is right or top */
508 	char unit[GMT_LEN64];		/* Axis unit appended to annotations */
509 	char prefix[GMT_LEN64];		/* Axis prefix starting all annotations */
510 	char *file_custom;		/* File with custom annotations */
511 };
512 
513 struct GMT_PLOT_FRAME {		/* Various parameters for plotting of time axis boundaries */
514 	struct GMT_PLOT_AXIS axis[3];	/* One each for x, y, and z */
515 	char header[GMT_LEN256];	/* Plot title */
516 	char sub_header[GMT_LEN256];	/* Plot subtitle */
517 	struct GMT_FILL fill[3];		/* Fill for the basemap inside for planes x,y,z, if paint == true */
518 	struct GMT_PEN pen;		/* Pen for the 3-D back wall outlines */
519 	bool plotted_header;		/* true if header has been plotted */
520 	bool init;			/* true if -B was used at all */
521 	bool set[3];		/* true if -B was used to set any x,y,z increments */
522 	bool draw;			/* true if -B<int> was used, even -B0, as sign to draw axes */
523 	bool drawz;			/* true if -B<int> was used, even -Bz0, as sign to draw z axes */
524 	bool paint[3];			/* true if -B +x[<fill>], +y[<fill>], +g<fill> was used */
525 	bool no_frame;			/* true if we just want gridlines but no frame, i.e +n was used */
526 	bool check_side;		/* true if lon and lat annotations should be on x and y axis only */
527 	bool primary;			/* true if current axis is primary, false if secondary */
528 	bool set_both;			/* true if -B argument applies to both x and y axes */
529 	bool obl_grid;			/* true if +o was given to draw oblique gridlines */
530 	bool draw_wall;			/* true if +w was given to draw backwall outline */
531 	bool gridline_plotted;	/* true if we already have plotted the gridlines or gridticks */
532 	unsigned int draw_box;			/* 0 = no 3-D frame. 1 if 3-D Z-box is desired [default], 2 if no -Z box lines covering up the plot */
533 	unsigned int internal_annot;	/* 1 (longitude) or 2 (latitude or radius) if +i was given to draw internal annotations */
534 	unsigned int set_frame[2];	/* 1 if a -B<WESNframe> setting was given */
535 	unsigned int horizontal;	/* 1 is S/N annotations should be parallel to axes, 2 if forced */
536 	unsigned int side[5];		/* Which sides (0-3 in plane; 4 = z) to plot. 2 is annot/draw, 1 is draw, 0 is not */
537 	unsigned int z_axis[4];		/* Which axes to use for the 3-D z-axis [auto] */
538 	unsigned int order;			/* 0: We are plotting before data, 1 we are plotting after data have been plotted */
539 	unsigned int basemap_flag;	/* Bit flag determining if frame, gridlines, and annotations+ticks are plotted before or after data */
540 	double internal_arg;		/* Internal annotation latitude or longitude location set via +i<val> */
541 };
542 
543 #endif /* GMT_PROJECT_H */
544