/*-------------------------------------------------------------------- * $Id: psscale.c,v 1.4.4.3 2002/02/27 17:41:10 pwessel Exp $ * * Copyright (c) 1991-2002 by P. Wessel and W. H. F. Smith * See COPYING file for copying and redistribution conditions. * * 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; version 2 of the License. * * 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. * * Contact info: gmt.soest.hawaii.edu *--------------------------------------------------------------------*/ /* * psscale draws a grayscale or colorscale either vertically or * horizontally. psscale will interpolate colors if the lower * and upper rgb values for an interval are different. The * resolution for this interpolation can be set on the command line. * If the scale is to be used with illumninated 2-D and 3-D plots * then options for intensities are available. * * Author: Paul Wessel * Created: 10-MAY-1991 * Modified: 01-AUG-1998 * 3.3 13-APR-1999. PW: Fixed bad -X -Y behavior * 3.3.2 15-SEP-1999. PW: Fixed bad loop for -Z * 3.3.4 21-JAN-2000. PW: Now paint rectangles for discrete cpt files * 08-FEB-2000. PW: Also understand patterns for discrete cpt files * Version: 3.4.1 * */ #include "gmt.h" int bit_dpi = 300; BOOLEAN B_set = FALSE; void GMT_draw_colorbar (double length, double width, double *z_width, BOOLEAN horizontal, BOOLEAN intens, double max_intens, BOOLEAN skip_lines, BOOLEAN extend, double e_length, BOOLEAN monochrome); void fix_format (char *unit, char *format); main(int argc, char **argv) { int i, n; BOOLEAN horizontal = FALSE, equi = FALSE, intens = FALSE, error = FALSE; BOOLEAN skip_lines = FALSE, extend = FALSE, must_shift_back = FALSE, monochrome = FALSE; double xpos, ypos, length, width, max_intens = 1.0, dz; double *z_width, e_length = 0.0, x_origin, y_origin; char flag, *cpt_file = NULL, *z_file = NULL, line[BUFSIZ]; char txt_a[32], txt_b[32], txt_c[32], txt_d[32], text[128]; FILE *fp = NULL; argc = GMT_begin (argc, argv); length = width = xpos = ypos = x_origin = y_origin = 0.0; /* Check and interpret the command line arguments */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch(argv[i][1]) { /* Common parameters */ case 'B': if (! (argv[i][2] == ':' || argv[i][2] == '/')) B_set = TRUE; case 'K': case 'O': case 'P': case 'U': case 'V': case 'X': case 'x': case 'Y': case 'y': case 'c': case '\0': error += GMT_get_common_args (argv[i], 0, 0, 0, 0); break; /* Supplemental parameters */ case 'C': cpt_file = &argv[i][2]; break; case 'D': n = strlen(argv[i]) - 1; flag = argv[i][n]; if (flag == 'h' || flag == 'H') { horizontal = TRUE; argv[i][n] = 0; } sscanf (&argv[i][2], "%[^/]/%[^/]/%[^/]/%s", txt_a, txt_b, txt_c, txt_d); xpos = GMT_convert_units (txt_a, GMT_INCH); ypos = GMT_convert_units (txt_b, GMT_INCH); length = GMT_convert_units (txt_c, GMT_INCH); width = GMT_convert_units (txt_d, GMT_INCH); break; case 'E': if (argv[i][2]) e_length = GMT_convert_units (&argv[i][2], GMT_INCH); extend = TRUE; break; case 'I': intens = TRUE; if (argv[i][2]) max_intens = atof (&argv[i][2]); break; case 'M': monochrome = TRUE; break; case 'N': if (argv[i][2]) bit_dpi = atoi (&argv[i][2]); break; case 'L': equi = TRUE; break; case 'S': skip_lines = TRUE; break; case 'Z': z_file = &argv[i][2]; break; /* Options not recognized */ default: error = TRUE; GMT_default_error (argv[i][1]); break; } } } if (argc == 1 || GMT_quick) { fprintf (stderr, "%s %s - To create grayscale or colorscale for maps\n\n", GMT_program, GMT_VERSION); fprintf(stderr, "usage: psscale -D [-C] [-E[]] [-B] [-I[]\n"); fprintf(stderr, "\t[-K] [-L] [-M] [-N] [-O] [-P] [-S] [-U] [-V] [-X] [-Y] [-Z] [-c]\n\n"); if (GMT_quick) exit (EXIT_FAILURE); fprintf (stderr, "\t-D set mid-point position and length/width for scale.\n"); fprintf (stderr, "\t Give negative length to reverse the scalebar\n"); fprintf (stderr, "\t Append h for horizontal scale\n"); fprintf (stderr, "\n\tOPTIONS:\n"); fprintf (stderr, "\t-B Set scale anotation interval and label. Use y-label to set unit label\n"); fprintf (stderr, "\t If no anotation interval is set it is taken from the cpt file\n"); fprintf (stderr, "\t-C Color palette file. If not set, stdin is read.\n"); fprintf (stderr, "\t By default all color changes are anotated (but see -B). To use a subset,\n"); fprintf (stderr, "\t add an extra column to the cpt-file with a L, U, or B\n"); fprintf (stderr, "\t to anotate Lower, Upper, or Both color segment boundaries\n"); fprintf (stderr, "\t-E add sidebar triangles for back- and forground colors.\n"); fprintf (stderr, "\t Optionally, append triangle height [Default scales with barwidth]\n"); fprintf (stderr, "\t-I add illumination for +- [1.0]\n"); GMT_explain_option ('K'); fprintf (stderr, "\t-L For equal-sized color rectangles\n"); fprintf (stderr, "\t-M force monochrome colorbar using YIQ transformation\n"); fprintf (stderr, "\t-N effective dots-per-inch for color scale [300]\n"); GMT_explain_option ('O'); GMT_explain_option ('P'); fprintf (stderr, "\t-S Skip drawing color boundary lines on color scale [Default draws lines]\n"); GMT_explain_option ('U'); GMT_explain_option ('V'); GMT_explain_option ('X'); fprintf (stderr, "\t-Z give colorbar-width (in %s) per color entry\n", GMT_unit_names[gmtdefs.measure_unit]); fprintf (stderr, "\t By default, width of entry is scaled to color range\n"); fprintf (stderr, "\t i.e., z = 0-100 gives twice the width as z = 100-150.\n"); GMT_explain_option ('c'); GMT_explain_option ('.'); exit (EXIT_FAILURE); } /* Check that the options selected are mutually consistant */ if (z_project.view_azimuth > 360.0 || z_project.view_elevation <= 0.0 || z_project.view_elevation > 90.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -E option: Enter azimuth in 0-360 range, elevation in 0-90 range\n", GMT_program); error++; } if (fabs (length) < SMALL ) { fprintf (stderr, "%s: GMT SYNTAX ERROR -D option: scale length must be nonzero\n", GMT_program); error++; } if (width <= 0.0) { fprintf (stderr, "%s: GMT SYNTAX ERROR -D option: scale width must be positive\n", GMT_program); error++; } if (bit_dpi < 1) { fprintf (stderr, "%s: GMT SYNTAX ERROR -N option: dpi must be > 0\n", GMT_program); error++; } if (error) exit (EXIT_FAILURE); GMT_put_history (argc, argv); /* Update .gmtcommands */ if (gmtdefs.verbose) { if (cpt_file) fprintf (stderr, "%s: Reading CPT file %s.", GMT_program, cpt_file); else fprintf (stderr, "%s: Reading standard input.", GMT_program); } GMT_read_cpt (cpt_file); if (gmtdefs.verbose) fprintf (stderr, " CPT range from %lg to %lg\n", GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high); if (extend && e_length == 0.0) e_length = width * 0.5; z_width = (double *) GMT_memory (VNULL, (size_t)GMT_n_colors, sizeof (double), GMT_program); if (z_file && (fp = fopen (z_file, "r")) == NULL) { fprintf (stderr, "%s: Unable to open file %s\n", GMT_program, z_file); exit (EXIT_FAILURE); } else if (z_file) { /* Opened successfully, now read */ i = 0; while (fgets (line, BUFSIZ, fp)) { if (i == GMT_n_colors) { fprintf (stderr, "%s: -Z file %s has more slices than -C file %s!\n", GMT_program, z_file, cpt_file); exit (EXIT_FAILURE); } if (line[0] == '#' || line[0] == '\n') continue; /* Skip comments and blank lines */ n = sscanf (line, "%lf", &z_width[i++]); if (n != 1) { fprintf (stderr, "%s: Error reading file %s near line %d\n", GMT_program, z_file, i); exit (EXIT_FAILURE); } } fclose (fp); if (i < GMT_n_colors) { fprintf (stderr, "%s: -Z file %s has fewer slices than -C file %s!\n", GMT_program, z_file, cpt_file); exit (EXIT_FAILURE); } } else if (equi) { dz = fabs (length) / GMT_n_colors; for (i = 0; i < GMT_n_colors; i++) z_width[i] = dz; } else { for (i = 0; i < GMT_n_colors; i++) z_width[i] = fabs (length) * (GMT_lut[i].z_high - GMT_lut[i].z_low) / (GMT_lut[GMT_n_colors-1].z_high - GMT_lut[0].z_low); } /*-----------------start of kludge-------------------------------------------*/ /* Because psscale uses -D to position things we need to make some * changes so that BoundingBox and others are set ~correctly */ sprintf (text, "X%lgi/%lgi", length, width); GMT_map_getproject (text); /* Fake linear projection */ GMT_map_setup (GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high, 0.0, width); /* We must do any origin translation manually in psscale */ if (! (gmtdefs.x_origin == 0.0 && gmtdefs.y_origin == 0.0)) { /* Must shift */ must_shift_back = (gmtdefs.page_orientation & 8); /* TRUE if absolute */ x_origin = gmtdefs.x_origin; y_origin = gmtdefs.y_origin; } if (horizontal) { gmtdefs.x_origin = xpos - 0.5 * fabs (length); gmtdefs.y_origin = ypos - width; frame_info.side[1] = frame_info.side[2] = frame_info.side[3] = 0; } else { gmtdefs.x_origin = xpos; gmtdefs.y_origin = ypos - 0.5 * fabs (length); frame_info.side[0] = frame_info.side[2] = frame_info.side[3] = 0; d_swap (z_project.xmin, z_project.ymin); d_swap (z_project.xmax, z_project.ymax); } if (frame_info.anot_int[0] == 0.0) frame_info.plot = TRUE; gmtdefs.page_orientation |= 8; /* Ensure absolute coordinates */ /*-----------------end of kludge-------------------------------------------*/ ps_plotinit (CNULL, gmtdefs.overlay, gmtdefs.page_orientation, gmtdefs.x_origin, gmtdefs.y_origin, gmtdefs.global_x_scale, gmtdefs.global_y_scale, gmtdefs.n_copies, gmtdefs.dpi, GMT_INCH, gmtdefs.paper_width, gmtdefs.page_rgb, GMT_epsinfo (argv[0])); GMT_echo_command (argc, argv); ps_transrotate (x_origin, y_origin, 0.0); ps_setpaint (gmtdefs.basemap_frame_rgb); if (gmtdefs.unix_time) { /* Extra shift/unshift since psscale does things differently */ ps_transrotate (-gmtdefs.x_origin, -gmtdefs.y_origin, 0.0); GMT_timestamp (argc, argv); ps_transrotate (gmtdefs.x_origin, gmtdefs.y_origin, 0.0); } GMT_draw_colorbar (length, width, z_width, horizontal, intens, max_intens, skip_lines, extend, e_length, monochrome); if (must_shift_back) ps_transrotate (-x_origin, -y_origin, 0.0); ps_plotend (gmtdefs.last_page); GMT_free ((void *)z_width); GMT_end (argc, argv); } void GMT_draw_colorbar (double length, double width, double *z_width, BOOLEAN horizontal, BOOLEAN intens, double max_intens, BOOLEAN skip_lines, BOOLEAN extend, double e_length, BOOLEAN monochrome) { int i, ii, j, ndec = -1, dec, rgb[3], rrggbb[3]; int nx, ny, nm, barmem, k; BOOLEAN reverse, all = TRUE, use_image; char format[64], text[64], test[64]; unsigned char *bar; double off, anot_off, label_off, len, len2, size, x0, x1, dx, xx; double z, xleft, xright, inc_i, inc_j; double get_z (double x, double *width, int n); double xp[4], yp[4]; struct GMT_FILL *f; ps_setfont (gmtdefs.anot_font); gmtdefs.anot_offset = fabs (gmtdefs.anot_offset); /* No 'inside' anotations allowed in colorbar */ /* Find max decimals needed */ if (B_set) { ndec = GMT_get_format (frame_info.anot_int[0], frame_info.unit[0], format); } else { for (i = 0; i < GMT_n_colors; i++) { if (GMT_lut[i].anot & 1) { if ((dec = GMT_get_format (GMT_lut[i].z_low, CNULL, text)) > ndec) { strcpy (format, text); ndec = dec; } } if (GMT_lut[i].anot & 2) { if ((dec = GMT_get_format (GMT_lut[i].z_high, CNULL, text)) > ndec) { strcpy (format, text); ndec = dec; } } if (GMT_lut[i].anot) all = FALSE; } } if (ndec == 0) { /* Not -B and no decimals are needed */ strcpy (format, gmtdefs.d_format); fix_format (frame_info.unit[0], format); /* Add units if needed */ } len = gmtdefs.tick_length; /* +ve means draw on the outside of bar */ len2 = 0.5 * len; xleft = x0 = 0.0; reverse = (length < 0.0); length = fabs (length); xright = length; use_image = (GMT_continuous || intens); if (use_image) { /* Make bitimage for colorbar using bit_dpi */ nx = irint (length * bit_dpi); ny = irint (width * bit_dpi); nm = nx * ny; inc_i = 1.0 / bit_dpi; inc_j = (intens) ? 2.0 * max_intens / (ny - 1) : 0.0; barmem = (monochrome || GMT_gray) ? nm : 3 * nm; bar = (unsigned char *) GMT_memory (VNULL, (size_t)barmem, sizeof (char), GMT_program); /* Load bar image */ for (i = 0; i < nx; i++) { z = get_z (i * inc_i, z_width, GMT_n_colors); GMT_get_rgb24 (z, rrggbb); ii = (reverse) ? nx - i - 1 : i; for (j = 0; j < ny; j++) { for (k = 0; k < 3; k++) rgb[k] = rrggbb[k]; k = j * nx + ii; if (intens) GMT_illuminate (max_intens - j * inc_j, rgb); if (GMT_gray) /* All gray, pick red */ bar[k] = (unsigned char) rgb[0]; else if (monochrome) /* Convert to gray using the YIQ transformation */ bar[k] = (unsigned char) YIQ (rgb); else { k *= 3; bar[k++] = (unsigned char) rgb[0]; bar[k++] = (unsigned char) rgb[1]; bar[k++] = (unsigned char) rgb[2]; } } } } GMT_setpen (&gmtdefs.frame_pen); /* Current point (0,0) is now at lower left location of bar */ if (horizontal) { if (use_image) { /* Must plot as image */ if (monochrome || GMT_gray) ps_image (0.0, 0.0, length, width, bar, nx, ny, 8); else GMT_color_image (0.0, 0.0, length, width, bar, nx, ny); } else { /* Plot as rectangles */ x0 = x1 = 0.0; yp[0] = yp[1] = 0.0; yp[2] = yp[3] = width; for (i = 0; i < GMT_n_colors; i++) { x1 += z_width[i]; if ((f = GMT_lut[i].fill)) { /* Using pattern fills */ xp[0] = xp[3] = x0; xp[1] = xp[2] = x1; ps_imagefill (xp, yp, 4, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ } else ps_rect (x0, 0.0, x1, width, GMT_lut[i].rgb_low, FALSE); x0 = x1; } } if (extend) { /* Add color triangles for fore- and background */ xp[0] = xp[1] = xleft; xp[2] = xp[0] - e_length; yp[0] = width; yp[1] = 0.0; yp[2] = 0.5 * width; if ((f = GMT_bfn.fill[1])) ps_imagefill (xp, yp, 3, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ else ps_polygon (xp, yp, 3, GMT_bfn.background_rgb, FALSE); ps_polygon (xp, yp, 3, GMT_no_rgb, 1); xp[0] = xp[1] = xright; xp[2] = xp[0] + e_length; yp[0] = width; yp[1] = 0.0; yp[2] = 0.5 * width; if ((f = GMT_bfn.fill[0])) ps_imagefill (xp, yp, 3, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ else ps_polygon (xp, yp, 3, GMT_bfn.foreground_rgb, FALSE); ps_polygon (xp, yp, 3, GMT_no_rgb, 1); } ps_plot (xleft, 0.0, 3); ps_plotr (length, 0.0, 2); ps_plot (xleft, width, 3); ps_plotr (length, 0.0, 2); ps_plot (xleft, 0.0, 3); ps_plotr (0.0, width, 2); ps_plot (xright, 0.0, 3); ps_plotr (0.0, width, 2); if (B_set) { /* Used -B */ GMT_x_axis (xleft, 0.0, length, GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high, frame_info.anot_int[0], frame_info.frame_int[0], frame_info.label[0], frame_info.unit[0], LINEAR, 0, TRUE, frame_info.side[0]-1); dx = fabs (frame_info.grid_int[0]); if (dx > 0.0) GMT_linearx_grid (GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high, 0.0, width, dx); } else { anot_off = (((len > 0.0) ? len : 0.0) + gmtdefs.anot_offset); label_off = -(anot_off + 1.5 * gmtdefs.anot_offset + (gmtdefs.anot_font_size * GMT_u2u[GMT_PT][GMT_INCH]) * GMT_font_height[gmtdefs.anot_font]); /* First draw gridlines, unless skip_lines is TRUE */ if (!skip_lines) { GMT_setpen (&gmtdefs.grid_pen); x1 = xleft; for (i = 0; i < GMT_n_colors; i++) { xx = (reverse) ? xright - x1 : x1; ps_plot (xx, 0.0, 3); ps_plotr (0.0, width, 2); x1 += z_width[i]; } xx = (reverse) ? xleft : xright; ps_plot (xx, 0.0, 3); ps_plotr (0.0, width, 2); } /* Then anotate and draw tickmarks */ GMT_setpen (&gmtdefs.tick_pen); x1 = xleft; for (i = 0; i < GMT_n_colors; i++) { xx = (reverse) ? xright - x1 : x1; ps_plot (xx, 0.0, 3); if (all || (GMT_lut[i].anot & 1)) { /* Anotate this */ ps_plotr (0.0, -len, 2); sprintf (text, format, GMT_lut[i].z_low); ps_text (xx, -anot_off, gmtdefs.anot_font_size, text, 0.0, 10, 0); } else ps_plotr (0.0, -len2, 2); x1 += z_width[i]; } xx = (reverse) ? xleft : xright; ps_plot (xx, 0.0, 3); if (all || (GMT_lut[GMT_n_colors-1].anot & 2)) { ps_plotr (0.0, -len, 2); sprintf (text, format, GMT_lut[GMT_n_colors-1].z_high); ps_text (xx, -anot_off, gmtdefs.anot_font_size, text, 0.0, 10, 0); } else ps_plotr (0.0, -len2, 2); if (frame_info.label[0][0]) { ps_setfont (gmtdefs.label_font); ps_text (xleft+0.5*length, label_off, gmtdefs.label_font_size, frame_info.label[0], 0.0, 10, 0); } } if (frame_info.label[1][0]) { /* Add unit label */ ps_setfont (gmtdefs.anot_font); ps_text (xright+e_length+gmtdefs.anot_offset, 0.5*width, gmtdefs.anot_font_size, frame_info.label[1], 0.0, 5, 0); } } else { /* Vertical scale */ ps_transrotate (width, 0.0, 90.0); if (use_image) { /* Must plot with image */ if (monochrome || GMT_gray) ps_image (0.0, 0.0, length, width, bar, nx, ny, 8); else GMT_color_image (0.0, 0.0, length, width, bar, nx, ny); } else { /* Plot as rectangles */ x0 = x1 = 0.0; yp[0] = yp[1] = 0.0; yp[2] = yp[3] = width; for (i = 0; i < GMT_n_colors; i++) { x1 += z_width[i]; if ((f = GMT_lut[i].fill)) { /* Using pattern fills */ xp[0] = xp[3] = x0; xp[1] = xp[2] = x1; ps_imagefill (xp, yp, 4, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ } else ps_rect (x0, 0.0, x1, width, GMT_lut[i].rgb_low, FALSE); x0 = x1; } } sprintf (text, "%d", (int)fabs (floor (GMT_lut[0].z_low))); sprintf (test, "%d", (int)fabs (ceil (GMT_lut[GMT_n_colors-1].z_high))); off = ((MAX ((int)strlen (text), (int)strlen (test)) + ndec) * 0.49 + ((ndec > 0) ? 0.3 : 0.0) + ((GMT_lut[0].z_low < 0.0) ? 0.3 : 0.0)) * gmtdefs.anot_font_size * GMT_u2u[GMT_PT][GMT_INCH]; anot_off = -(((len > 0.0) ? len : 0.0) + gmtdefs.anot_offset + off); label_off = anot_off - 0.7 * gmtdefs.anot_font_size * GMT_u2u[GMT_PT][GMT_INCH] - 1.5 * gmtdefs.anot_offset; if (extend) { /* Add color triangles for fore- and background */ xp[0] = xp[1] = xleft; xp[2] = xp[0] - e_length; yp[0] = width; yp[1] = 0.0; yp[2] = 0.5 * width; if ((f = GMT_bfn.fill[1])) ps_imagefill (xp, yp, 3, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ else ps_polygon (xp, yp, 3, GMT_bfn.background_rgb, FALSE); ps_polygon (xp, yp, 3, GMT_no_rgb, 1); xp[0] = xp[1] = xright; xp[2] = xp[0] + e_length; yp[0] = width; yp[1] = 0.0; yp[2] = 0.5 * width; if ((f = GMT_bfn.fill[0])) ps_imagefill (xp, yp, 3, f->pattern_no, f->pattern, f->inverse, f->dpi, FALSE, f->colorize, f->f_rgb, f->b_rgb); /* Contours drawn separately below if desired */ else ps_polygon (xp, yp, 3, GMT_bfn.foreground_rgb, FALSE); ps_polygon (xp, yp, 3, GMT_no_rgb, 1); } ps_plot (xleft, 0.0, 3); ps_plotr (length, 0.0, 2); ps_plot (xleft, width, 3); ps_plotr (length, 0.0, 2); ps_plot (xleft, 0.0, 3); ps_plotr (0.0, width, 2); ps_plot (xright, 0.0, 3); ps_plotr (0.0, width, 2); if (B_set) { /* Used -B */ dx = fabs (frame_info.grid_int[0]); if (dx > 0.0) GMT_linearx_grid (GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high, 0.0, width, dx); ps_transrotate (0.0, 0.0, -90.0); GMT_y_axis (0.0, 0.0, length, GMT_lut[0].z_low, GMT_lut[GMT_n_colors-1].z_high, frame_info.anot_int[0], frame_info.frame_int[0], CNULL, CNULL, LINEAR, 0, FALSE, frame_info.side[0]-1); ps_rotatetrans (0.0, 0.0, 90.0); } else { if (!skip_lines) { /* First draw gridlines */ GMT_setpen (&gmtdefs.grid_pen); x1 = xleft; for (i = 0; i < GMT_n_colors; i++) { xx = (reverse) ? xright - x1 : x1; ps_plot (xx, 0.0, 3); ps_plotr (0.0, width, 2); x1 += z_width[i]; } xx = (reverse) ? xleft : xright; ps_plot (xx, 0.0, 3); ps_plotr (0.0, width, 2); } /* Then anotate and draw tickmarks */ GMT_setpen (&gmtdefs.tick_pen); x1 = xleft; for (i = 0; i < GMT_n_colors; i++) { xx = (reverse) ? xright - x1 : x1; ps_plot (xx, 0.0, 3); if (all || (GMT_lut[i].anot & 1)) { ps_plotr (0.0, -len, 2); sprintf (text, format, GMT_lut[i].z_low); ps_text (xx, anot_off, gmtdefs.anot_font_size, text, -90.0, 7, 0); } else ps_plotr (0.0, -len2, 2); x1 += z_width[i]; } xx = (reverse) ? xleft : xright; ps_plot (xx, 0.0, 3); if (all || (GMT_lut[GMT_n_colors-1].anot & 2)) { ps_plotr (0.0, -len, 2); sprintf (text, format, GMT_lut[GMT_n_colors-1].z_high); ps_text (xx, anot_off, gmtdefs.anot_font_size, text, -90.0, 7, 0); } else ps_plotr (0.0, -len2, 2); } if (frame_info.label[0][0]) { ps_setfont (gmtdefs.label_font); size = 0.9 * gmtdefs.label_font_size * GMT_u2u[GMT_PT][GMT_INCH]; x0 = 0.5 * (length + ((int)strlen (frame_info.label[0]) -1) * size); text[1] = 0; for (i = 0; i < (int)strlen (frame_info.label[0]); i++) { x1 = x0 - i * size; text[0] = frame_info.label[0][i]; ps_text (x1, label_off, gmtdefs.label_font_size, text, -90.0, 6, 0); } } if (frame_info.label[1][0]) { /* Add unit label */ ps_setfont (gmtdefs.anot_font); ps_text (xright + gmtdefs.anot_offset + e_length, 0.5 * width, gmtdefs.anot_font_size, frame_info.label[1], -90.0, 2, 0); } ps_rotatetrans (-width, 0.0, -90.0); } if (use_image) GMT_free ((void *)bar); } double get_z (double x, double *width, int n) { int i = 0; double tmp; tmp = width[0]; while (i < n && x > tmp) tmp += width[++i]; if (i == n) return (GMT_lut[GMT_n_colors-1].z_high); return (GMT_lut[i].z_low + (x - tmp + width[i]) * (GMT_lut[i].z_high - GMT_lut[i].z_low) / width[i]); } void fix_format (char *unit, char *format) { int i, j; char text[80], new_format[BUFSIZ]; /* Check if anotation units should be added */ if (unit && unit[0]) { /* Must append the unit string */ if (!strchr (unit, '%')) /* No percent signs */ strncpy (text, unit, 80); else { for (i = j = 0; i < (int)strlen (unit); i++) { text[j++] = unit[i]; if (unit[i] == '%') text[j++] = unit[i]; } text[j] = 0; } if (text[0] == '-') /* No space between anotation and unit */ sprintf (new_format, "%s%s", format, &text[1]); else /* 1 space between anotation and unit */ sprintf (new_format, "%s %s", format, text); strcpy (format, new_format); } }