home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Science / Science.zip / gmt_os2.zip / src / gmt_map.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-20  |  175.7 KB  |  5,329 lines

  1. /*--------------------------------------------------------------------
  2.  *    The GMT-system:    @(#)gmt_map.c    2.56  09 Aug 1995    
  3.  *
  4.  *    Copyright (c) 1991-1995 by P. Wessel and W. H. F. Smith
  5.  *    See README file for copying and redistribution conditions.
  6.  *--------------------------------------------------------------------*/
  7.  
  8. /*
  9.  *
  10.  *            G M T _ M A P . C
  11.  *
  12.  *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  13.  * gmt_map.c contains code related to coordinate transformation
  14.  *
  15.  *     Map Transformation Setup Routines
  16.  *    These routines initializes the selected map transformation
  17.  *    The names and main function are listed below
  18.  *    NB! Note that the transformation function does not check that they are
  19.  *    passed valid lon,lat numbers. I.e asking for log10 scaling using values
  20.  *    <= 0 results in problems.
  21.  *
  22.  * Map_projections include functions that will set up the transformation
  23.  * between xy and latlon for several map projections.
  24.  *
  25.  * A few of the core coordinate transformation functions are based on similar
  26.  * FORTRAN routines written by Pat Manley, Doug Shearer, and Bill Haxby, and
  27.  * have been rewritten in C and subsequently streamlined.  The rest is based
  28.  * on P. Snyder, "Map Projections - a working manual", USGS Prof paper 1395.
  29.  *
  30.  * Transformations supported (both forward and inverse):
  31.  *    Linear x/y[/z] scaling
  32.  *    Polar (theta, r) scaling
  33.  *    Mercator
  34.  *    Stereographic
  35.  *    Albers Equal-Area Conic
  36.  *    Lambert Conformal Conic
  37.  *    Cassini Cylindrical
  38.  *    Oblique Mercator
  39.  *    TM Transverse Mercator
  40.  *    UTM Universal Transverse Mercator
  41.  *    Lambert Azimuthal Equal-Area
  42.  *    Mollweide Equal-Area
  43.  *    Hammer-Aitoff Equal-Area
  44.  *    Sinusoidal Equal-Area
  45.  *    Winkel Tripel
  46.  *    Orthographic
  47.  *    Azimuthal Equidistant
  48.  *    Robinson
  49.  *    Eckert IV
  50.  *    Cylindrical Equal-area (e.g., Peters, Gall, Behrmann)
  51.  *    Cylindrical Equidistant (Plate Carree)
  52.  *
  53.  * The ellipsoid used is selectable by editing the .gmtdefaults in your
  54.  * home directory.  If no such file, create one by running gmtdefaults.
  55.  *
  56.  * Usage: Initialize system by calling map_setup (separate module), and
  57.  * then just use geo_to_xy() and xy_to_geo() functions.
  58.  *
  59.  * Author:    Paul Wessel
  60.  * Date:    27-JUL-1992
  61.  * Version:    v2.1
  62.  *
  63.  *
  64.  * Functions include:
  65.  *
  66.  *    azim_2_angle :        Converts azimuth to angle on the map
  67.  *    break_through :        Checks if we cross a map boundary
  68.  *    clip_to_map :        Force polygon points to be inside map
  69.  *    compact_line :        Remove redundant pen movements
  70.  *    geo_to_xy :        Generic lon/lat to x/y
  71.  *    geo_to_xy_line :    Same for polygons
  72.  *    geoz_to_xy :        Generic 3-D lon/lat/z to x/y
  73.  *    get_origin :        Find origin of projection based on pole and 2nd point
  74.  *    get_rotate_pole :    Find rotation pole based on two points on great circle
  75.  *    grd_forward :        Forward map-transform grid matrix from lon/lat to x/y
  76.  *    grd_inverse :        Inversely transform grid matrix from x/y to lon/lat
  77.  *    grdproject_init :    Initialize parameters for grid transformations
  78.  *    great_circle_dist :    Returns great circle distance in degrees
  79.  *    hammer :        Hammer-Aitoff equal area projection
  80.  *    ihammer :        Inverse Hammer-Aitoff equal area projection
  81.  *    ilamb :            Inverse Lambert conformal conic projection
  82.  *    ilambeq :        Inverse Lambert azimuthal equal area projection
  83.  *    ilinearxy :        Inverse linear projection
  84.  *    imerc :            Inverse Mercator projection
  85.  *    imollweide :        Inverse Mollweide projection
  86.  *    init_three_D :        Initializes parameters needed for 3-D plots
  87.  *    ioblmrc :        Inverse oblique Mercator projection, spherical only
  88.  *    iortho :        Inverse orthographic projection
  89.  *    iplrs :            Inverse Polar stereographic projection
  90.  *    itranslin :        Inverse linear x projection
  91.  *    itranslog10 :        Inverse log10 x projection
  92.  *    itranspowx :        Inverse pow x projection
  93.  *    itranspowy :        Inverse pow y projection
  94.  *    itm :            Inverse TM projection
  95.  *    lamb :            Lambert conformal conic projection
  96.  *    lambeq :        Lambert azimuthal equal area projection
  97.  *    radial_crossing :    Determine map crossing in the Lambert azimuthal equal area projection
  98.  *    latpath :        Return path between 2 points of equal latitide
  99.  *    left_boundary :        Return left boundary in x-inches
  100.  *    linearxy :        Linear xy projection
  101.  *    lon_inside :        Accounts for wrap-around in longitudes and checks for inside    
  102.  *    lonpath :        Return path between 2 points of equal longitude
  103.  *    map_crossing :        Generic function finds crossings between line and map boundary
  104.  *    map_outside :        Generic function determines if we're outside map boundary
  105.  *    map_path :        Return latpat or lonpath
  106.  *    map_setup :        Initialize map projection
  107.  *    merc :            Mercator projection
  108.  *    mollweide :        Mollweide projection
  109.  *    ellipse_crossing :    Find map crossings in the Mollweide projection
  110.  *    move_to_rect :        Move an outside point straight in to nearest edge
  111.  *    oblmrc :        Spherical oblique Mercator projection
  112.  *    ortho :            Orthographic projection
  113.  *    pen_status :        Determines if pen is up or down
  114.  *    plrs :            Polar stereographic projection
  115.  *    polar_outside :        Determines if a point is outside polar projection region
  116.  *    pole_rotate_forward :    Compute positions from oblique coordinates
  117.  *    pole_rotate_inverse :    Compute oblique coordinates
  118.  *    project3D :        Convert lon/lat/z to xx/yy/zz
  119.  *    radial_clip :        Clip path outside radial region
  120.  *    radial_outside :    Determine if point is outside radial region
  121.  *    radial_overlap :    Determine overlap, always TRUE for his projection
  122.  *    rect_clip :        Clip to rectangular region
  123.  *    rect_crossing :        Find crossling between line and rect region
  124.  *    rect_outside :        Determine if point is outside rect region
  125.  *    rect_outside2 :        Determine if point is outside rect region (azimuthal proj only)
  126.  *    rect_overlap :        Determine overlap between rect regions
  127.  *    right_boundary :    Return x value of right map boundary
  128.  *    translin :        Linear x projection
  129.  *    translog10 :        Log10 x projection
  130.  *    transpowx :        Linear pow x projection
  131.  *    transpowy :        Linear pow y projection
  132.  *    tm :            TM projection
  133.  *    xy_search :        Find xy map boundary
  134.  *    two_d_to_three_d :    Convert xyz to xy for entire array
  135.  *    vhammer :        Initialize Hammer-Aitoff equal area projection
  136.  *    vlamb :            Initialize Lambert conformal conic projection
  137.  *    vlambeq :        Initialize Lambert azimuthal equal area projection
  138.  *    vmerc :            Initialize Mercator projection
  139.  *    vmollweide :        Initialize Mollweide projection
  140.  *    vortho :        Initialize Orthographic projection
  141.  *    vplrs :            Initialize Polar stereographic projection
  142.  *    vtm :            Initialize TM projection
  143.  *    wesn_clip:        Clip polygon to wesn boundaries
  144.  *    wesn_crossing :        Find crossing between line and lon/lat rectangle
  145.  *    wesn_outside :        Determine if a point is outside a lon/lat rectangle
  146.  *    wesn_overlap :        Determine overlap between lon/lat rectangles
  147.  *    wesn_search :        Search for extreme coordinates    
  148.  *    wrap_around_check :    Check if line wraps around due to Greenwich
  149.  *    x_to_xx :        Generic linear x projection
  150.  *    xx_to_x :        Generic inverse linear x projection
  151.  *    xy_to_geo :        Generic inverse x/y to lon/lat projection
  152.  *    xyz_to_xy :        Generic xyz to xy projection
  153.  *    y_to_yy :        Generic linear y projection
  154.  *    yy_to_y :        Generic inverse linear y projection
  155.  *    z_to_zz :        Generic linear z projection
  156.  *    zz_to_z :        Generic inverse linear z projection
  157.  */
  158.  
  159. #include "gmt.h"
  160.  
  161. #define PI_2 (2.0 * M_PI)
  162.  
  163. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  164.  *
  165.  *    S E C T I O N  1 :    M A P  - T R A N S F O R M A T I O N S
  166.  *
  167.  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  168.  
  169. /*
  170.  * map_setup sets up the transformations for the chosen map projection.
  171.  * The user must pass:
  172.  *   w,e,s,n,parameters[0] - parameters[np-1] (np = number of parameters), and project:
  173.  *   w,e,s,n defines the area in degrees.
  174.  *   project == LINEAR, POLAR, MERCATOR, STEREO, LAMBERT, OBLIQUE_MERC,
  175.  *    TM, ORTHO, AZ_EQDIST, LAMB_AZ_EQ, WINKEL, ROBINSON, CASSINI, ALBERS. ECKERT, CYL_EQ, CYL_EQDIST
  176.  *    For LINEAR, we may have LINEAR, LOG10, or POW
  177.  *
  178.  * parameters[0] through parameters[np-1] mean different things to the various
  179.  * projections, as explained below. (np also varies, of course)
  180.  *
  181.  * LINEAR projection:
  182.  *    parameters[0] is inch (or cm)/x_user_unit.
  183.  *    parameters[1] is inch (or cm)/y_user_unit. If 0, then yscale = xscale.
  184.  *    parameters[2] is pow for x^pow (if POW is on).
  185.  *    parameters[3] is pow for y^pow (if POW is on).
  186.  *
  187.  * POLAR (r,theta) projection:
  188.  *    parameters[0] is inch (or cm)/x_user_unit (radius)
  189.  *
  190.  * MERCATOR projection:
  191.  *    parameters[0] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  192.  *
  193.  * STEREOgraphic projection:
  194.  *    parameters[0] is longitude of pole
  195.  *    parameters[1] is latitude of pole
  196.  *    parameters[2] is radius in inches (or cm) from pole to the latitude specified
  197.  *       by parameters[3] OR 1:xxxxx OR map-width.
  198.  *
  199.  * LAMBERT projection (Conic):
  200.  *    parameters[0] is first standard parallell
  201.  *    parameters[1] is second standard parallell
  202.  *    parameters[2] is scale in inch (or cm)/degree along parallells OR 1:xxxxx OR map-width
  203.  *
  204.  * OBLIQUE MERCATOR projection:
  205.  *    parameters[0] is longitude of origin
  206.  *    parameters[1] is latitude of origin
  207.  *    Definition a:
  208.  *        parameters[2] is longitude of second point along oblique equator
  209.  *        parameters[3] is latitude of second point along oblique equator
  210.  *        parameters[4] is scale in inch (or cm)/degree along oblique equator OR 1:xxxxx OR map-width
  211.  *    Definition b:
  212.  *        parameters[2] is azimuth along oblique equator at origin
  213.  *        parameters[3] is scale in inch (or cm)/degree along oblique equator OR 1:xxxxx OR map-width
  214.  *    Definition c:
  215.  *        parameters[2] is longitude of pole of projection
  216.  *        parameters[3] is latitude of pole of projection
  217.  *        parameters[4] is scale in inch (cm)/degree along oblique equator OR 1:xxxxx OR map-width
  218.  *
  219.  * TRANSVERSE MERCATOR (TM) projection
  220.  *    parameters[0] is central meridian
  221.  *    parameters[1] is scale in inch (cm)/degree along this meridian OR 1:xxxxx OR map-width
  222.  *
  223.  * UNIVERSAL TRANSVERSE MERCATOR (UTM) projection
  224.  *    parameters[0] is UTM zone (0-60, use negative for S hemisphere)
  225.  *    parameters[1] is scale in inch (cm)/degree along this meridian OR 1:xxxxx OR map-width
  226.  *
  227.  * LAMBERT AZIMUTHAL EQUAL AREA projection:
  228.  *    parameters[0] is longitude of origin
  229.  *    parameters[1] is latitude of origin
  230.  *    parameters[2] is radius in inches (or cm) from pole to the latitude specified
  231.  *       by parameters[3] OR 1:xxxxx OR map-width.
  232.  *
  233.  * ORTHOGRAPHIC AZIMUTHAL projection:
  234.  *    parameters[0] is longitude of origin
  235.  *    parameters[1] is latitude of origin
  236.  *    parameters[2] is radius in inches (or cm) from pole to the latitude specified
  237.  *       by parameters[3] OR 1:xxxxx OR map-width.
  238.  *
  239.  * AZIMUTHAL EQUIDISTANCE projection:
  240.  *    parameters[0] is longitude of origin
  241.  *    parameters[1] is latitude of origin
  242.  *    parameters[2] is radius in inches (or cm) from pole to the latitude specified
  243.  *       by parameters[3] OR 1:xxxxx OR map-width.
  244.  *
  245.  * MOLLWEIDE EQUAL-AREA projection
  246.  *    parameters[0] is longitude of origin
  247.  *    parametres[1] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  248.  *
  249.  * HAMMER-AITOFF EQUAL-AREA projection
  250.  *    parameters[0] is longitude of origin
  251.  *    parametres[1] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  252.  *
  253.  * SINUSOIDAL EQUAL-AREA projection
  254.  *    parameters[0] is longitude of origin
  255.  *    parameters[1] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  256.  *
  257.  * WINKEL TRIPEL MODIFIED AZIMUTHAL projection
  258.  *    parameters[0] is longitude of origin
  259.  *    parametres[1] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  260.  *
  261.  * ROBINSON PSEUDOCYLINDRICAL projection
  262.  *    parameters[0] is longitude of origin
  263.  *    parametres[1] is in inch (or cm)/degree_longitude @ equator OR 1:xxxxx OR map-width
  264.  *
  265.  * CASSINI projection
  266.  *    parameters[0] is longitude of origin
  267.  *    parameters[1] is latitude of origin
  268.  *    parametres[2] is scale in inch (cm)/degree along this meridian OR 1:xxxxx OR map-width
  269.  *
  270.  * ALBERS projection (Conic):
  271.  *    parameters[0] is first standard parallell
  272.  *    parameters[1] is second standard parallell
  273.  *    parameters[2] is scale in inch (or cm)/degree along parallells OR 1:xxxxx OR map-width
  274.  *
  275.  * ECKERT IV projection:
  276.  *    parameters[0] is longitude of origin
  277.  *    parameters[1] is scale in inch (or cm)/degree along parallells OR 1:xxxxx OR map-width
  278.  *
  279.  * CYLINDRICAL EQUAL-AREA projections (Behrmann, Gall, Peters):
  280.  *    parameters[0] is longitude of origin
  281.  *    parameters[1] is the standard parallell
  282.  *    parameters[2] is scale in inch (or cm)/degree along parallells OR 1:xxxxx OR map-width
  283.  *
  284.  * Pointers to the correct map transformation fuctions will be set up so that
  285.  * there are no if tests to determine which routine to call. These pointers
  286.  * are forward and inverse, and are called from geo_to_xy and xy_to_geo.
  287.  *
  288.  */
  289.  
  290. int map_setup (west, east, south, north)
  291. double west, east, south, north; {
  292.     int i, search;
  293.     double f;
  294.     
  295.     if (!project_info.region) d_swap (south, east);  /* Got w/s/e/n, make into w/e/s/n */
  296.  
  297.     if (west == east && south == north) {
  298.         fprintf (stderr, "%s: GMT Fatal Error: No region selected - Aborts!\n", gmt_program);
  299.         exit (-1);
  300.     }
  301.  
  302.     if (east < west) east += 360.0;
  303.     project_info.w = west;    project_info.e = east;    project_info.s = south;    project_info.n = north;
  304.     if (project_info.gave_map_width) project_info.units_pr_degree = FALSE;
  305.     
  306.     /* Set up ellipse parameters for the selected ellipsoid */
  307.     
  308.     frame_info.check_side = frame_info.horizontal = FALSE;
  309.     EQ_RAD = gmtdefs.ellipse[gmtdefs.ellipsoid].eq_radius;
  310.     f = gmtdefs.ellipse[gmtdefs.ellipsoid].flattening;
  311.     ECC2 = 2 * f - f * f;
  312.     ECC4 = ECC2 * ECC2;
  313.     ECC6 = ECC2 * ECC4;
  314.     ECC = d_sqrt (ECC2);
  315.     M_PR_DEG = PI_2 * EQ_RAD / 360.0;
  316.     if (!z_forward) z_forward = (PFI) translin;
  317.     if (!z_inverse) z_inverse = (PFI) itranslin;
  318.     gmtdefs.n_lon_nodes = gmtdefs.n_lat_nodes = 0;
  319.     
  320.     switch (project_info.projection) {
  321.     
  322.         case LINEAR:    /* Linear transformations */
  323.         
  324.             search = map_init_linear ();
  325.             break;
  326.             
  327.         case POLAR:    /* Both lon/lat are actually theta, radius */
  328.     
  329.             search = map_init_polar ();
  330.             break;
  331.             
  332.         case MERCATOR:    /* Standard Mercator projection */
  333.     
  334.             search = map_init_merc ();
  335.             break;
  336.                         
  337.         case STEREO:    /* Stereographic projection */
  338.  
  339.             search = map_init_stereo ();
  340.             break;
  341.             
  342.         case LAMBERT:    /* Lambert Conformal Conic */
  343.  
  344.             search = map_init_lambert();
  345.             break;
  346.             
  347.         case OBLIQUE_MERC:    /* Oblique Mercator */
  348.  
  349.             search = map_init_oblique ();
  350.             break;
  351.             
  352.         case TM:    /* Transverse Mercator */
  353.  
  354.             search = map_init_tm ();
  355.             break;
  356.             
  357.         case UTM:    /* Universal Transverse Mercator */
  358.  
  359.             search = map_init_utm ();
  360.             break;
  361.             
  362.         case LAMB_AZ_EQ:    /* Lambert Azimuthal Equal-Area */
  363.  
  364.             search = map_init_lambeq ();
  365.             break;
  366.             
  367.         case ORTHO:    /* Orthographic Projection */
  368.  
  369.             search = map_init_ortho ();
  370.             break;
  371.             
  372.         case AZ_EQDIST:    /* Azimuthal Equal-Distance Projection */
  373.  
  374.             search = map_init_azeqdist ();
  375.             break;
  376.             
  377.         case MOLLWEIDE:    /* Mollweide Equal-Area */
  378.  
  379.             search = map_init_mollweide ();
  380.             break;
  381.             
  382.         case HAMMER:    /* Hammer-Aitoff Equal-Area */
  383.  
  384.             search = map_init_hammer ();
  385.             break;
  386.  
  387.         case WINKEL:    /* Winkel Tripel */
  388.  
  389.             search = map_init_winkel ();
  390.             break;
  391.             
  392.         case ECKERT:    /* Eckert VI */
  393.  
  394.             search = map_init_eckert ();
  395.             break;
  396.             
  397.         case CYL_EQ:    /* Cylindrical Equal-Area */
  398.  
  399.             search = map_init_cyleq ();
  400.             break;
  401.             
  402.         case CYL_EQDIST:    /* Cylindrical Equaidistant */
  403.  
  404.             search = map_init_cyleqdist ();
  405.             break;
  406.             
  407.         case ROBINSON:    /* Robinson */
  408.  
  409.             search = map_init_robinson ();
  410.             break;
  411.             
  412.         case SINUSOIDAL:    /* Sinusoidal Equal-Area */
  413.  
  414.             search = map_init_sinusoidal ();
  415.             break;
  416.  
  417.         case CASSINI:    /* Cassini cylindrical */
  418.  
  419.             search = map_init_cassini ();
  420.             break;
  421.             
  422.         case ALBERS:    /* Albers Equal-Area Conic */
  423.  
  424.             search = map_init_albers ();
  425.             break;
  426.             
  427.         default:    /* No projection selected, die */
  428.             fprintf (stderr, "%s: GMT Fatal Error: No projection selected - Aborts!\n", gmt_program);
  429.             exit (-1);
  430.             break;
  431.     }
  432.     
  433.     gmt_map_width = fabs (project_info.xmax - project_info.xmin);
  434.     gmt_map_height = fabs (project_info.ymax - project_info.ymin);
  435.     gmt_half_map_size = 0.5 * gmt_map_width;
  436.     
  437.     if (!gmtdefs.n_lon_nodes) gmtdefs.n_lon_nodes = rint (gmt_map_width / gmtdefs.line_step);
  438.     if (!gmtdefs.n_lat_nodes) gmtdefs.n_lat_nodes = rint (gmt_map_height / gmtdefs.line_step);
  439.     
  440.     gmtdefs.dlon = (project_info.e - project_info.w) / gmtdefs.n_lon_nodes;
  441.     gmtdefs.dlat = (project_info.n - project_info.s) / gmtdefs.n_lat_nodes;
  442.         
  443.     if (search) {
  444.         wesn_search ();
  445.         gmtdefs.dlon = (project_info.e - project_info.w) / gmtdefs.n_lon_nodes;
  446.         gmtdefs.dlat = (project_info.n - project_info.s) / gmtdefs.n_lat_nodes;
  447.     }
  448.  
  449.     for (i = 0; i < 3; i++) {
  450.         if (!project_info.xyz_pos[i]) {    /* Max intervals negative */
  451.             frame_info.anot_int[i]  = -frame_info.anot_int[i];
  452.             frame_info.frame_int[i] = -frame_info.frame_int[i];
  453.             frame_info.grid_int[i]  = -frame_info.grid_int[i];
  454.         }
  455.     }
  456.     
  457.     init_three_D ();
  458.     
  459.     /* Default for overlay plots is no shifting */
  460.     
  461.     if (!project_info.x_off_supplied && gmtdefs.overlay) gmtdefs.x_origin = 0.0;
  462.     if (!project_info.y_off_supplied && gmtdefs.overlay) gmtdefs.y_origin = 0.0;
  463.  
  464.     return (0);
  465. }
  466.  
  467. int init_three_D () {
  468.     int i, easy;
  469.     double tilt_angle, x, y, x0, x1, x2, y0, y1, y2, zmin, zmax;
  470.     
  471.     project_info.three_D = (z_project.view_azimuth != 180.0 || z_project.view_elevation != 90.0);
  472.     if (project_info.three_D) gmtdefs.basemap_type = 1;    /* Only plain frame for 3-D */
  473.     
  474.     project_info.z_scale = project_info.z_pars[0];
  475.     if (project_info.z_scale < 0.0) project_info.xyz_pos[2] = FALSE;    /* User wants z to increase down */
  476.     if (project_info.z_level == MAXDOUBLE) project_info.z_level = (project_info.xyz_pos[2]) ? project_info.z_bottom : project_info.z_top;
  477.     
  478.     switch (project_info.xyz_projection[2]) {
  479.         case LINEAR:    /* Regular scaling */
  480.             zmin = (project_info.xyz_pos[2]) ? project_info.z_bottom : project_info.z_top;
  481.             zmax = (project_info.xyz_pos[2]) ? project_info.z_top : project_info.z_bottom;
  482.             z_forward = (PFI) translin;
  483.             z_inverse = (PFI) itranslin;
  484.             break;
  485.         case LOG10:    /* Log10 transformation */
  486.             if (project_info.z_bottom <= 0.0 || project_info.z_top <= 0.0) {
  487.                 fprintf (stderr, "%s: GMT SYNTAX ERROR for -Jz -JZ option: limits must be positive for log10 projection\n", gmt_program);
  488.                 exit (-1);
  489.             }
  490.             zmin = (project_info.xyz_pos[2]) ? d_log10 (project_info.z_bottom) : d_log10 (project_info.z_top);
  491.             zmax = (project_info.xyz_pos[2]) ? d_log10 (project_info.z_top) : d_log10 (project_info.z_bottom);
  492.             z_forward = (PFI) translog10;
  493.             z_inverse = (PFI) itranslog10;
  494.             break;
  495.         case POW:    /* x^y transformation */
  496.             project_info.xyz_pow[2] = project_info.z_pars[1];
  497.             zmin = (project_info.xyz_pos[2]) ? pow (project_info.z_bottom, project_info.xyz_pow[2]) : pow (project_info.z_top, project_info.xyz_pow[2]);
  498.             zmax = (project_info.xyz_pos[2]) ? pow (project_info.z_top, project_info.xyz_pow[2]) : pow (project_info.z_bottom, project_info.xyz_pow[2]);
  499.             z_forward = (PFI) transpowz;
  500.             z_inverse = (PFI) itranspowz;
  501.     }
  502.     if (project_info.compute_scale[2]) project_info.z_scale /= fabs (zmin - zmax);
  503.     project_info.zmax = (zmax - zmin) * project_info.z_scale;
  504.     project_info.z0 = -zmin * project_info.z_scale;
  505.     
  506.     if (z_project.view_azimuth >= 360.0) z_project.view_azimuth -= 360.0;
  507.     z_project.quadrant = ceil (z_project.view_azimuth / 90.0);
  508.     z_project.view_azimuth -= 180.0;    /* Turn into direction instead */
  509.     if (z_project.view_azimuth < 0.0) z_project.view_azimuth += 360.0;
  510.     z_project.view_azimuth *= D2R;
  511.     z_project.view_elevation *= D2R;
  512.     z_project.cos_az = cos (z_project.view_azimuth);
  513.     z_project.sin_az = sin (z_project.view_azimuth);
  514.     z_project.cos_el = cos (z_project.view_elevation);
  515.     z_project.sin_el = sin (z_project.view_elevation);
  516.     geoz_to_xy (project_info.w, project_info.s, project_info.z_bottom, &x0, &y0);
  517.     geoz_to_xy (project_info.e, project_info.s, project_info.z_bottom, &x1, &y1);
  518.     geoz_to_xy (project_info.w, project_info.n, project_info.z_bottom, &x2, &y2);
  519.     z_project.phi[0] = d_atan2 (y1 - y0, x1 - x0) * R2D;
  520.     z_project.phi[1] = d_atan2 (y2 - y0, x2 - x0) * R2D;
  521.     z_project.phi[2] = 90.0;
  522.     tilt_angle = (z_project.phi[0] + 90.0 - z_project.phi[1]) * D2R;
  523.     z_project.k = (fabs (z_project.cos_az) > fabs (z_project.sin_az)) ? 0 : 1;
  524.     z_project.xshrink[0] = hypot (z_project.cos_az, z_project.sin_az * z_project.sin_el);
  525.     z_project.yshrink[0] = hypot (z_project.sin_az, z_project.cos_az * z_project.sin_el);
  526.     z_project.xshrink[1] = z_project.yshrink[0];
  527.     z_project.yshrink[1] = z_project.xshrink[0];
  528.     z_project.yshrink[0] *= fabs (cos (tilt_angle));    /* New */
  529.     z_project.yshrink[1] *= fabs (cos (tilt_angle));
  530.     z_project.xshrink[2] = fabs (z_project.cos_el);
  531.     z_project.yshrink[2] = (fabs (z_project.cos_az) > fabs (z_project.sin_az)) ? fabs (z_project.cos_az) : fabs (z_project.sin_az);
  532.     z_project.tilt[0] = tan (tilt_angle);
  533.     z_project.tilt[1] = -z_project.tilt[0];
  534.     z_project.tilt[2] = (fabs (z_project.cos_az) > fabs (z_project.sin_az)) ? tan (-z_project.phi[0] * D2R) : tan (-z_project.phi[1] * D2R);
  535.     
  536.     /* Determine min/max y of plot */
  537.     
  538.     /* easy = TRUE means we can use 4 corner points to find min x and y, FALSE
  539.        measn we must search along wesn perimeter the hard way */
  540.        
  541.     switch (project_info.projection) {
  542.         case LINEAR:
  543.         case POLAR:
  544.         case MERCATOR:
  545.         case OBLIQUE_MERC:
  546.         case CYL_EQ:
  547.         case CYL_EQDIST:
  548.             easy = TRUE;
  549.             break;
  550.         case LAMBERT:
  551.         case TM:
  552.         case UTM:
  553.         case CASSINI:
  554.         case STEREO:
  555.         case ALBERS:
  556.         case LAMB_AZ_EQ:
  557.         case ORTHO:
  558.         case AZ_EQDIST:
  559.         case SINUSOIDAL:
  560.         case MOLLWEIDE:
  561.         case HAMMER:
  562.         case WINKEL:
  563.         case ECKERT:
  564.         case ROBINSON:
  565.             easy = (!project_info.region);
  566.             break;
  567.         default:
  568.             easy = FALSE;
  569.             break;
  570.     }
  571.     
  572.     if (!project_info.three_D) easy = TRUE;
  573.     
  574.     z_project.corner_x[0] = z_project.corner_x[3] = (project_info.xyz_pos[0]) ? project_info.w : project_info.e;
  575.     z_project.corner_x[1] = z_project.corner_x[2] = (project_info.xyz_pos[0]) ? project_info.e : project_info.w;
  576.     z_project.corner_y[0] = z_project.corner_y[1] = (project_info.xyz_pos[1]) ? project_info.s : project_info.n;
  577.     z_project.corner_y[2] = z_project.corner_y[3] = (project_info.xyz_pos[1]) ? project_info.n : project_info.s;
  578.     z_project.xmin = z_project.ymin = MAXDOUBLE;    z_project.xmax = z_project.ymax = -MAXDOUBLE;
  579.     
  580.     if (easy) {
  581.         double xx[4], yy[4];
  582.         
  583.         xx[0] = xx[3] = project_info.xmin; xx[1] = xx[2] = project_info.xmax;
  584.         yy[0] = yy[1] = project_info.ymin; yy[2] = yy[3] = project_info.ymax;
  585.         
  586.         for (i = 0; i < 4; i++) {
  587.             xy_do_z_to_xy (xx[i], yy[i], project_info.z_bottom, &x, &y);
  588.             z_project.ymin = MIN (z_project.ymin, y);
  589.             z_project.ymax = MAX (z_project.ymax, y);
  590.             z_project.xmin = MIN (z_project.xmin, x);
  591.             z_project.xmax = MAX (z_project.xmax, x);
  592.             xy_do_z_to_xy (xx[i], yy[i], project_info.z_top, &x, &y);
  593.             z_project.ymin = MIN (z_project.ymin, y);
  594.             z_project.ymax = MAX (z_project.ymax, y);
  595.             z_project.xmin = MIN (z_project.xmin, x);
  596.             z_project.xmax = MAX (z_project.xmax, x);
  597.         }
  598.     }
  599.     else {
  600.         for (i = 0; i < gmtdefs.n_lon_nodes; i++) {    /* S and N */
  601.             geoz_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, project_info.z_bottom, &x, &y);
  602.             z_project.ymin = MIN (z_project.ymin, y);
  603.             z_project.ymax = MAX (z_project.ymax, y);
  604.             z_project.xmin = MIN (z_project.xmin, x);
  605.             z_project.xmax = MAX (z_project.xmax, x);
  606.             if (project_info.z_top != project_info.z_bottom) {    
  607.                 geoz_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, project_info.z_top, &x, &y);
  608.                 z_project.ymin = MIN (z_project.ymin, y);
  609.                 z_project.ymax = MAX (z_project.ymax, y);
  610.                 z_project.xmin = MIN (z_project.xmin, x);
  611.                 z_project.xmax = MAX (z_project.xmax, x);
  612.             }            
  613.             geoz_to_xy (project_info.w + i * gmtdefs.dlon, project_info.n, project_info.z_bottom, &x, &y);
  614.             z_project.ymin = MIN (z_project.ymin, y);
  615.             z_project.ymax = MAX (z_project.ymax, y);
  616.             z_project.xmin = MIN (z_project.xmin, x);
  617.             z_project.xmax = MAX (z_project.xmax, x);            
  618.             if (project_info.z_top != project_info.z_bottom) {    
  619.                 geoz_to_xy (project_info.w + i * gmtdefs.dlon, project_info.n, project_info.z_top, &x, &y);
  620.                 z_project.ymin = MIN (z_project.ymin, y);
  621.                 z_project.ymax = MAX (z_project.ymax, y);
  622.                 z_project.xmin = MIN (z_project.xmin, x);
  623.                 z_project.xmax = MAX (z_project.xmax, x);
  624.             }        
  625.         }
  626.         for (i = 0; i < gmtdefs.n_lat_nodes; i++) {    /* W and E */
  627.             geoz_to_xy (project_info.w, project_info.s + i * gmtdefs.dlat, project_info.z_bottom, &x, &y);
  628.             z_project.ymin = MIN (z_project.ymin, y);
  629.             z_project.ymax = MAX (z_project.ymax, y);
  630.             z_project.xmin = MIN (z_project.xmin, x);
  631.             z_project.xmax = MAX (z_project.xmax, x);            
  632.             if (project_info.z_top != project_info.z_bottom) {    
  633.                 geoz_to_xy (project_info.w, project_info.s + i * gmtdefs.dlat, project_info.z_top, &x, &y);
  634.                 z_project.ymin = MIN (z_project.ymin, y);
  635.                 z_project.ymax = MAX (z_project.ymax, y);
  636.                 z_project.xmin = MIN (z_project.xmin, x);
  637.                 z_project.xmax = MAX (z_project.xmax, x);
  638.             }            
  639.             geoz_to_xy (project_info.e, project_info.s + i * gmtdefs.dlat, project_info.z_bottom, &x, &y);
  640.             z_project.ymin = MIN (z_project.ymin, y);
  641.             z_project.ymax = MAX (z_project.ymax, y);
  642.             z_project.xmin = MIN (z_project.xmin, x);
  643.             z_project.xmax = MAX (z_project.xmax, x);            
  644.             if (project_info.z_top != project_info.z_bottom) {    
  645.                 geoz_to_xy (project_info.e, project_info.s + i * gmtdefs.dlat, project_info.z_top, &x, &y);
  646.                 z_project.ymin = MIN (z_project.ymin, y);
  647.                 z_project.ymax = MAX (z_project.ymax, y);
  648.                 z_project.xmin = MIN (z_project.xmin, x);
  649.                 z_project.xmax = MAX (z_project.xmax, x);
  650.             }        
  651.         }
  652.     }
  653.     
  654.     z_project.face[0] = (z_project.quadrant == 1 || z_project.quadrant == 2) ? 0 : 1;
  655.     z_project.face[1] = (z_project.quadrant == 1 || z_project.quadrant == 4) ? 2 : 3;
  656.     z_project.face[2] = (z_project.view_elevation >= 0.0) ? 4 : 5;
  657.     z_project.draw[0] = (z_project.quadrant == 1 || z_project.quadrant == 4) ? TRUE : FALSE;
  658.     z_project.draw[1] = (z_project.quadrant == 3 || z_project.quadrant == 4) ? TRUE : FALSE;
  659.     z_project.draw[2] = (z_project.quadrant == 2 || z_project.quadrant == 3) ? TRUE : FALSE;
  660.     z_project.draw[3] = (z_project.quadrant == 1 || z_project.quadrant == 2) ? TRUE : FALSE;
  661.     z_project.sign[0] = z_project.sign[3] = -1.0;
  662.     z_project.sign[1] = z_project.sign[2] = 1.0;
  663.     z_project.z_axis = (z_project.quadrant%2) ? z_project.quadrant : z_project.quadrant - 2;
  664. }
  665.  
  666. /*
  667.  *    GENERIC TRANSFORMATION ROUTINES FOR THE LINEAR PROJECTION
  668.  */
  669.  
  670. int x_to_xx (x, xx)
  671. double x, *xx; {
  672.     /* Converts x to xx using the current linear projection */
  673.     
  674.     (*x_forward) (x, xx);
  675.     (*xx) = (*xx) * project_info.x_scale + project_info.x0;
  676. }
  677.  
  678. int y_to_yy (y, yy)
  679. double y, *yy; {
  680.     /* Converts y to yy using the current linear projection */
  681.     
  682.     (*y_forward) (y, yy);
  683.     (*yy) = (*yy) * project_info.y_scale + project_info.y0;
  684. }
  685.  
  686. int z_to_zz (z, zz)
  687. double z, *zz; {
  688.     /* Converts z to zz using the current linear projection */
  689.     
  690.     (*z_forward) (z, zz);
  691.     (*zz) = (*zz) * project_info.z_scale + project_info.z0;
  692. }
  693.  
  694. int xx_to_x (x, xx)
  695. double *x, xx; {
  696.     /* Converts xx back to x using the current linear projection */
  697.     
  698.     xx = (xx - project_info.x0) / project_info.x_scale;
  699.     
  700.     (*x_inverse) (x, xx);
  701. }
  702.  
  703. int yy_to_y (y, yy)
  704. double *y, yy; {
  705.     /* Converts yy back to y using the current linear projection */
  706.     
  707.     yy = (yy - project_info.y0) / project_info.y_scale;
  708.     
  709.     (*y_inverse) (y, yy);
  710. }
  711.  
  712. int zz_to_z (z, zz)
  713. double *z, zz; {
  714.     /* Converts zz back to z using the current linear projection */
  715.     
  716.     zz = (zz - project_info.z0) / project_info.z_scale;
  717.     
  718.     (*z_inverse) (z, zz);
  719. }
  720.  
  721. int geo_to_xy (lon, lat, x, y)
  722. double lon, lat, *x, *y; {
  723.     /* Converts lon/lat to x/y using the current projection */
  724.     
  725.     (*forward) (lon, lat, x, y);
  726.     (*x) = (*x) * project_info.x_scale + project_info.x0;
  727.     (*y) = (*y) * project_info.y_scale + project_info.y0;
  728. }
  729.  
  730. int xy_to_geo (lon, lat, x, y)
  731. double *lon, *lat, x, y; {
  732.     /* Converts x/y to lon/lat using the current projection */
  733.     
  734.     x = (x - project_info.x0) / project_info.x_scale;
  735.     y = (y - project_info.y0) / project_info.y_scale;
  736.     
  737.     (*inverse) (lon, lat, x, y);
  738. }
  739.  
  740. int geoz_to_xy (x, y, z, x_out, y_out)
  741. double x, y, z;
  742. double *x_out, *y_out; {    /* Map-projects xy first, the projects xyz onto xy plane */
  743.     double x0, y0, z0;
  744.     geo_to_xy (x, y, &x0, &y0);
  745.     z_to_zz (z, &z0);
  746.     *x_out = x0 * z_project.cos_az - y0 * z_project.sin_az;
  747.     *y_out = (x0 * z_project.sin_az + y0 * z_project.cos_az) * z_project.sin_el + z0 * z_project.cos_el;
  748. }
  749.  
  750. int xyz_to_xy (x, y, z, x_out, y_out)
  751. double x, y, z;
  752. double *x_out, *y_out; {    /* projects xyz onto xy plane */
  753.     *x_out = x * z_project.cos_az - y * z_project.sin_az;
  754.     *y_out = (x * z_project.sin_az + y * z_project.cos_az) * z_project.sin_el + z * z_project.cos_el;
  755. }
  756.  
  757. int xy_do_z_to_xy (x, y, z, x_out, y_out)
  758. double x, y, z;
  759. double *x_out, *y_out; {    /* projects xy (inches) z (z-value) onto xy plane */
  760.     double z_out;
  761.     
  762.     z_to_zz (z, &z_out);
  763.     *x_out = x * z_project.cos_az - y * z_project.sin_az;
  764.     *y_out = (x * z_project.sin_az + y * z_project.cos_az) * z_project.sin_el + z_out * z_project.cos_el;
  765. }
  766.  
  767. int project3D (x, y, z, x_out, y_out, z_out)
  768. double x, y, z, *x_out, *y_out, *z_out; {
  769.     geo_to_xy (x, y, x_out, y_out);
  770.     z_to_zz (z, z_out);
  771. }
  772.  
  773. /*
  774.  *    TRANSFORMATION ROUTINES FOR THE LINEAR PROJECTION
  775.  */
  776.  
  777. int map_init_linear () {
  778.     BOOLEAN degree;
  779.     double xmin, xmax, ymin, ymax;
  780.  
  781.     left_edge = (PFD) left_rect;
  782.     right_edge = (PFD) right_rect;
  783.     forward  = (PFI) linearxy;
  784.     inverse  = (PFI) ilinearxy;
  785.     degree = (project_info.pars[4] == 1.0);
  786.     if (degree) {
  787.         project_info.central_meridian = 0.5 * (project_info.w + project_info.e);
  788.         gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  789.     }
  790.     project_info.x_scale = project_info.pars[0];
  791.     project_info.y_scale = project_info.pars[1];
  792.     if (project_info.x_scale < 0.0) project_info.xyz_pos[0] = FALSE;    /* User wants x to increase left */
  793.     if (project_info.y_scale < 0.0) project_info.xyz_pos[1] = FALSE;    /* User wants y to increase down */
  794.             
  795.     switch (project_info.xyz_projection[0]) {
  796.         case LINEAR:    /* Regular scaling */
  797.             x_forward = (PFI) ((degree) ? translind : translin);
  798.             x_inverse = (PFI) itranslin;
  799.             if (project_info.xyz_pos[0]) {
  800.                 (*x_forward) (project_info.w, &xmin);
  801.                 (*x_forward) (project_info.e, &xmax);
  802.             }
  803.             else {
  804.                 (*x_forward) (project_info.e, &xmin);
  805.                 (*x_forward) (project_info.w, &xmax);
  806.             }
  807.             break;
  808.         case LOG10:    /* Log10 transformation */
  809.             if (project_info.w <= 0.0 || project_info.e <= 0.0) {
  810.                 fprintf (stderr, "%s: GMT SYNTAX ERROR -Jx option:  Limits must be positive for log10 option\n", gmt_program);
  811.                 exit (-1);
  812.             }
  813.             xmin = (project_info.xyz_pos[0]) ? d_log10 (project_info.w) : d_log10 (project_info.e);
  814.             xmax = (project_info.xyz_pos[0]) ? d_log10 (project_info.e) : d_log10 (project_info.w);
  815.             x_forward = (PFI) translog10;
  816.             x_inverse = (PFI) itranslog10;
  817.             break;
  818.         case POW:    /* x^y transformation */
  819.             project_info.xyz_pow[0] = project_info.pars[2];
  820.             project_info.xyz_ipow[0] = 1.0 / project_info.pars[2];
  821.             xmin = (project_info.xyz_pos[0]) ? pow (project_info.w, project_info.xyz_pow[0]) : pow (project_info.e, project_info.xyz_pow[0]);
  822.             xmax = (project_info.xyz_pos[0]) ? pow (project_info.e, project_info.xyz_pow[0]) : pow (project_info.w, project_info.xyz_pow[0]);
  823.             x_forward = (PFI) transpowx;
  824.             x_inverse = (PFI) itranspowx;
  825.             break;
  826.     }
  827.     switch (project_info.xyz_projection[1]) {
  828.         case LINEAR:    /* Regular scaling */
  829.             ymin = (project_info.xyz_pos[1]) ? project_info.s : project_info.n;
  830.             ymax = (project_info.xyz_pos[1]) ? project_info.n : project_info.s;
  831.             y_forward = (PFI) translin;
  832.             y_inverse = (PFI) itranslin;
  833.             break;
  834.         case LOG10:    /* Log10 transformation */
  835.             if (project_info.s <= 0.0 || project_info.n <= 0.0) {
  836.                 fprintf (stderr, "%s: GMT SYNTAX ERROR -Jx option:  Limits must be positive for log10 option\n", gmt_program);
  837.                 exit (-1);
  838.             }
  839.             ymin = (project_info.xyz_pos[1]) ? d_log10 (project_info.s) : d_log10 (project_info.n);
  840.             ymax = (project_info.xyz_pos[1]) ? d_log10 (project_info.n) : d_log10 (project_info.s);
  841.             y_forward = (PFI) translog10;
  842.             y_inverse = (PFI) itranslog10;
  843.             break;
  844.         case POW:    /* x^y transformation */
  845.             project_info.xyz_pow[1] = project_info.pars[3];
  846.             project_info.xyz_ipow[1] = 1.0 / project_info.pars[3];
  847.             ymin = (project_info.xyz_pos[1]) ? pow (project_info.s, project_info.xyz_pow[1]) : pow (project_info.n, project_info.xyz_pow[1]);
  848.             ymax = (project_info.xyz_pos[1]) ? pow (project_info.n, project_info.xyz_pow[1]) : pow (project_info.s, project_info.xyz_pow[1]);
  849.             y_forward = (PFI) transpowy;
  850.             y_inverse = (PFI) itranspowy;
  851.     }
  852.             
  853.     /* Was given axes length instead of scale? */
  854.             
  855.     if (project_info.compute_scale[0]) project_info.x_scale /= fabs (xmin - xmax);
  856.     if (project_info.compute_scale[1]) project_info.y_scale /= fabs (ymin - ymax);
  857.  
  858.     map_setxy (xmin, xmax, ymin, ymax);
  859.     outside = (PFI) rect_outside;
  860.     crossing = (PFI) rect_crossing;
  861.     overlap = (PFI) rect_overlap;
  862.     map_clip = (PFI) rect_clip;
  863.     frame_info.horizontal = TRUE;
  864.     
  865.     return (FALSE);
  866. }
  867.  
  868. int linearxy (x, y, x_i, y_i)
  869. double x, y, *x_i, *y_i; {    /* Transform both x and y linearly */
  870.     (*x_forward) (x, x_i);
  871.     (*y_forward) (y, y_i);
  872. }
  873.  
  874. int ilinearxy (x, y, x_i, y_i)
  875. double *x, *y, x_i, y_i; {    /* Inversely transform both x and y linearly */
  876.     (*x_inverse) (x, x_i);
  877.     (*y_inverse) (y, y_i);
  878. }
  879.  
  880. int translin (forw, inv)    /* Linear forward */
  881. double forw, *inv; {
  882.     *inv = forw;
  883. }
  884.  
  885. int translind (forw, inv)    /* Linear forward, but with degrees*/
  886. double forw, *inv; {
  887.     while ((forw - project_info.central_meridian) < -180.0) forw += 360.0;
  888.     while ((forw - project_info.central_meridian) > 180.0) forw -= 360.0;
  889.     *inv = forw - project_info.central_meridian;
  890. }
  891.  
  892. int itranslin (forw, inv)    /* Linear inverse */
  893. double *forw, inv; {
  894.     *forw = inv;
  895. }
  896.  
  897. int translog10 (forw, inv)    /* Log10 forward */
  898. double forw, *inv; {
  899.     *inv = d_log10 (forw);
  900. }
  901.  
  902. int itranslog10 (forw, inv) /* Log10 inverse */
  903. double *forw, inv; {
  904.     *forw = pow (10.0, inv);
  905. }
  906.  
  907. int transpowx (x, x_in)    /* pow x forward */
  908. double x, *x_in; {
  909.     *x_in = pow (x, project_info.xyz_pow[0]);
  910. }
  911.  
  912. int itranspowx (x, x_in) /* pow x inverse */
  913. double *x, x_in; {
  914.     *x = pow (x_in, project_info.xyz_ipow[0]);
  915. }
  916.  
  917. int transpowy (y, y_in)    /* pow y forward */
  918. double y, *y_in; {
  919.     *y_in = pow (y, project_info.xyz_pow[1]);
  920. }
  921.  
  922. int itranspowy (y, y_in) /* pow y inverse */
  923. double *y, y_in; {
  924.     *y = pow (y_in, project_info.xyz_ipow[1]);
  925. }
  926.  
  927. int transpowz (z, z_in)    /* pow z forward */
  928. double z, *z_in; {
  929.     *z_in = pow (z, project_info.xyz_pow[2]);
  930. }
  931.  
  932. int itranspowz (z, z_in) /* pow z inverse */
  933. double *z, z_in; {
  934.     *z = pow (z_in, project_info.xyz_ipow[2]);
  935. }
  936.  
  937. /*
  938.  *    TRANSFORMATION ROUTINES FOR POLAR (theta,r) PROJECTION
  939.  */
  940.  
  941. int map_init_polar () {
  942.     double xmin, xmax, ymin, ymax;
  943.     
  944.     vpolar (0.5 * (project_info.w + project_info.e));
  945.     /* project_info.w = 0.0;    project_info.e = 360.0; */
  946.     /* if (project_info.gave_map_width) project_info.pars[0] *= 0.5 / project_info.n; */    /* north is max radius */
  947.     if (project_info.s == 0.0) project_info.edge[0] = FALSE;
  948.     if (fabs (project_info.e - project_info.w) == 360.0) project_info.edge[1] = project_info.edge[3] = FALSE;
  949.     left_edge = (PFD) left_circle;
  950.     right_edge = (PFD) right_circle;
  951.     forward  = (PFI) polar;
  952.     inverse  = (PFI) ipolar;
  953.     gmt_world_map = TRUE;
  954.     xy_search (&xmin, &xmax, &ymin, &ymax);
  955.     project_info.x_scale = project_info.y_scale = project_info.pars[0];
  956.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[0]);
  957.     /* xmin = ymin = -project_info.n;    xmax = ymax = project_info.n;
  958.     project_info.x_scale = project_info.y_scale = project_info.pars[0]; */
  959.  
  960.     /* project_info.r = 0.5 * project_info.xmax; */
  961.     project_info.r = project_info.y_scale * project_info.n;
  962.     outside = (PFI) polar_outside;
  963.     crossing = (PFI) wesn_crossing;
  964.     overlap = (PFI) wesn_overlap;
  965.     map_clip = (PFI) wesn_clip;
  966.     frame_info.horizontal = TRUE;
  967.     gmtdefs.degree_format = 6;    /* Special labeling case */
  968.     
  969.     return (FALSE);
  970. }
  971.  
  972. int vpolar (lon0)
  973. double lon0; {
  974.     /* Set up a Polar (theta,r) transformation */
  975.     
  976.     project_info.central_meridian = lon0;
  977.     project_info.north_pole = FALSE;
  978.     return (0);
  979. }
  980.  
  981. int polar (x, y, x_i, y_i)
  982. double x, y, *x_i, *y_i; {    /* Transform both x and y linearly */
  983.     *x_i = y * cosd (x);
  984.     *y_i = y * sind (x);
  985. }
  986.  
  987. int ipolar (x, y, x_i, y_i)
  988. double *x, *y, x_i, y_i; {    /* Inversely transform both x and y linearly */
  989.     *x = R2D * d_atan2 (y_i, x_i);
  990.     *y = hypot (x_i, y_i);
  991. }
  992.  
  993. /*
  994.  *    TRANSFORMATION ROUTINES FOR THE MERCATOR PROJECTION
  995.  */
  996.  
  997. int map_init_merc () {
  998.     double xmin, xmax, ymin, ymax;
  999.     
  1000.     if (project_info.s == -90.0 || project_info.n == 90.0) {
  1001.         fprintf (stderr, "%s: GMT SYNTAX ERROR -R option:  Cannot include south/north poles with Mercator projection!\n", gmt_program);
  1002.         exit (-1);
  1003.     }
  1004.     
  1005.     vmerc (0.5 * (project_info.w + project_info.e));
  1006.     merc (project_info.w, project_info.s, &xmin, &ymin);
  1007.     merc (project_info.e, project_info.n, &xmax, &ymax);
  1008.     if (project_info.gave_map_width) project_info.pars[0] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  1009.     if (project_info.units_pr_degree) project_info.pars[0] /= M_PR_DEG;
  1010.     project_info.x_scale = project_info.y_scale = project_info.pars[0];
  1011.     map_setxy (xmin, xmax, ymin, ymax);
  1012.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  1013.     gmtdefs.n_lat_nodes = 2;
  1014.     gmtdefs.n_lon_nodes = 3;    /* > 2 to avoid map-jumps */
  1015.     forward = (PFI)merc;        inverse = (PFI)imerc;
  1016.     outside = (PFI) wesn_outside;
  1017.     crossing = (PFI) wesn_crossing;
  1018.     overlap = (PFI) wesn_overlap;
  1019.     map_clip = (PFI) wesn_clip;
  1020.     left_edge = (PFD) left_rect;
  1021.     right_edge = (PFD) right_rect;
  1022.     frame_info.horizontal = TRUE;
  1023.     return (FALSE);    /* No need to search for wesn */
  1024. }
  1025.  
  1026. int vmerc (cmerid)
  1027. double cmerid; {
  1028.     /* Set up a Mercator transformation */
  1029.     
  1030.     project_info.central_meridian = cmerid;
  1031.     return (0);
  1032. }
  1033.  
  1034. int merc (lon, lat, x, y)
  1035. double lon, lat, *x, *y; {
  1036.     double tmp;
  1037.     /* Convert lon/lat to Mercator x/y */
  1038.  
  1039.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  1040.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  1041.     *x = (lon - project_info.central_meridian) * D2R * EQ_RAD;
  1042.     
  1043.     if (fabs (lat) < 90.0) {
  1044.         tmp = pow ((1.0 - ECC * sin (lat * D2R)) / (1.0 + ECC * sin (lat * D2R)), 0.5 * ECC);
  1045.         *y =  d_log (tan ((45.0 + 0.5 * lat) * D2R) * tmp) * EQ_RAD;
  1046.     }
  1047.     else
  1048.         *y = copysign (1.0e100, lat);
  1049. }
  1050.  
  1051. int imerc (lon, lat, x, y)
  1052. double *lon, *lat, x, y; {
  1053.     int i;
  1054.     double t, t_phi, delta, tmp, phi, pw, pow();
  1055.  
  1056.     /* Convert Mercator x/y to lon/lat */
  1057.     
  1058.     *lon = (x / EQ_RAD) * R2D + project_info.central_meridian;
  1059.     
  1060.     t = exp (-y / EQ_RAD);
  1061.     t_phi = 90.0 - 2.0 * atan(t) * R2D;
  1062.     for (delta = 1.0, i = 0; delta > 0.0000001 && i < 100; i++) {
  1063.         tmp = (1.0 - ECC * sin (t_phi * D2R)) / (1.0 + ECC * sin (t_phi * D2R));
  1064.         pw = pow (tmp, 0.5 * ECC);
  1065.         phi = 90.0 - 2.0 * atan (t * pw) * R2D;
  1066.         delta = fabs (fabs (phi) - fabs (t_phi));
  1067.         t_phi = phi;
  1068.     }
  1069.     *lat = phi;
  1070. }
  1071.  
  1072. /*
  1073.  *    TRANSFORMATION ROUTINES FOR CYLIDNDRICAL EQUAL-AREA PROJECTIONS (CYL_EQ)
  1074.  */
  1075.  
  1076. int map_init_cyleq () {
  1077.     double xmin, xmax, ymin, ymax;
  1078.     
  1079.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  1080.     vcyleq (project_info.pars[0], project_info.pars[1]);
  1081.     cyleq (project_info.w, project_info.s, &xmin, &ymin);
  1082.     cyleq (project_info.e, project_info.n, &xmax, &ymax);
  1083.     if (project_info.gave_map_width) project_info.pars[2] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  1084.     if (project_info.units_pr_degree) project_info.pars[2] /= M_PR_DEG;
  1085.     project_info.x_scale = project_info.y_scale = project_info.pars[2];
  1086.     map_setxy (xmin, xmax, ymin, ymax);
  1087.     gmtdefs.n_lat_nodes = 2;
  1088.     gmtdefs.n_lon_nodes = 3;    /* > 2 to avoid map-jumps */
  1089.     forward = (PFI)cyleq;        inverse = (PFI)icyleq;
  1090.     outside = (PFI) wesn_outside;
  1091.     crossing = (PFI) wesn_crossing;
  1092.     overlap = (PFI) wesn_overlap;
  1093.     map_clip = (PFI) wesn_clip;
  1094.     left_edge = (PFD) left_rect;
  1095.     right_edge = (PFD) right_rect;
  1096.     frame_info.horizontal = TRUE;
  1097.     return (FALSE);    /* No need to search for wesn */
  1098. }
  1099.  
  1100. int vcyleq (lon0, slat)
  1101. double lon0, slat; {
  1102.     /* Set up a Cylindrical equal-area transformation */
  1103.     
  1104.     gmt_check_R_J (&lon0);
  1105.     project_info.central_meridian = lon0;
  1106.     project_info.y_rx = EQ_RAD * D2R * cos (D2R * slat);
  1107.     project_info.y_ry = EQ_RAD / cos (D2R * slat);
  1108.     return (0);
  1109. }
  1110.  
  1111. int cyleq (lon, lat, x, y)
  1112. double lon, lat, *x, *y; {
  1113.     /* Convert lon/lat to Cylindrical equal-area x/y */
  1114.  
  1115.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  1116.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  1117.     *x = (lon - project_info.central_meridian) * project_info.y_rx;
  1118.     *y = project_info.y_ry * sind (lat);
  1119. }
  1120.  
  1121. int icyleq (lon, lat, x, y)
  1122. double *lon, *lat, x, y; {
  1123.  
  1124.     /* Convert Cylindrical equal-area x/y to lon/lat */
  1125.     
  1126.     *lon = (x / project_info.y_rx) + project_info.central_meridian;
  1127.     *lat = R2D * d_asin (y / project_info.y_ry);
  1128. }
  1129.  
  1130. /*
  1131.  *    TRANSFORMATION ROUTINES FOR CYLINDRICAL EQIDISTANT PROJECTION (CYL_EQDIST)
  1132.  */
  1133.  
  1134. int map_init_cyleqdist () {
  1135.     double xmin, xmax, ymin, ymax;
  1136.     
  1137.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  1138.     vcyleqdist (project_info.pars[0]);
  1139.     cyleqdist (project_info.w, project_info.s, &xmin, &ymin);
  1140.     cyleqdist (project_info.e, project_info.n, &xmax, &ymax);
  1141.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  1142.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  1143.     project_info.x_scale = project_info.y_scale = project_info.pars[1];
  1144.     map_setxy (xmin, xmax, ymin, ymax);
  1145.     gmtdefs.n_lat_nodes = 2;
  1146.     gmtdefs.n_lon_nodes = 3;    /* > 2 to avoid map-jumps */
  1147.     forward = (PFI)cyleqdist;        inverse = (PFI)icyleqdist;
  1148.     outside = (PFI) wesn_outside;
  1149.     crossing = (PFI) wesn_crossing;
  1150.     overlap = (PFI) wesn_overlap;
  1151.     map_clip = (PFI) wesn_clip;
  1152.     left_edge = (PFD) left_rect;
  1153.     right_edge = (PFD) right_rect;
  1154.     frame_info.horizontal = TRUE;
  1155.     return (FALSE);    /* No need to search for wesn */
  1156. }
  1157.  
  1158. int vcyleqdist (lon0)
  1159. double lon0; {
  1160.     /* Set up a Cylindrical equidistant transformation */
  1161.     
  1162.     gmt_check_R_J (&lon0);
  1163.     project_info.central_meridian = lon0;
  1164.     return (0);
  1165. }
  1166.  
  1167. int cyleqdist (lon, lat, x, y)
  1168. double lon, lat, *x, *y; {
  1169.     /* Convert lon/lat to Cylindrical equidistant x/y */
  1170.  
  1171.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  1172.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  1173.     *x = (lon - project_info.central_meridian) * D2R * EQ_RAD;
  1174.     *y = lat * D2R * EQ_RAD;
  1175. }
  1176.  
  1177. int icyleqdist (lon, lat, x, y)
  1178. double *lon, *lat, x, y; {
  1179.  
  1180.     /* Convert Cylindrical equal-area x/y to lon/lat */
  1181.     
  1182.     *lon = R2D * (x / EQ_RAD) + project_info.central_meridian;
  1183.     *lat = R2D * y / EQ_RAD;
  1184. }
  1185.  
  1186. /*
  1187.  *    TRANSFORMATION ROUTINES FOR THE POLAR STEREOGRAPHIC PROJECTION
  1188.  */
  1189.  
  1190. int map_init_stereo () {
  1191.     BOOLEAN search;
  1192.     double xmin, xmax, ymin, ymax, dummy, radius;
  1193.     
  1194.     if (fabs (project_info.pars[1]) == 90.0) {    /* Polar aspect */
  1195.         project_info.polar = TRUE;
  1196.         forward = (PFI)plrs;        inverse = (PFI)iplrs;
  1197.         vplrs (project_info.pars[0], project_info.pars[1]);
  1198.         if (project_info.units_pr_degree) {
  1199.             plrs (project_info.pars[0], project_info.pars[3], &dummy, &radius);
  1200.             project_info.x_scale = project_info.y_scale = fabs (project_info.pars[2] / radius);
  1201.         }
  1202.         else
  1203.             project_info.x_scale = project_info.y_scale = project_info.pars[2];
  1204.     }
  1205.     else {
  1206.         vstereo (project_info.pars[0], project_info.pars[1]);
  1207.         project_info.polar = FALSE;
  1208.         forward = (project_info.pole == 0.0) ? (PFI)stereo2 : (PFI)stereo1;
  1209.         inverse = (PFI)istereo;
  1210.         if (project_info.units_pr_degree) {
  1211.             vplrs (0.0, 90.0);
  1212.             plrs (0.0, fabs(project_info.pars[3]), &dummy, &radius);
  1213.             project_info.x_scale = project_info.y_scale = fabs (project_info.pars[2] / radius);
  1214.         }
  1215.         else
  1216.             project_info.x_scale = project_info.y_scale = project_info.pars[2];
  1217.                 
  1218.         vstereo (project_info.pars[0], project_info.pars[1]);
  1219.     }
  1220.     
  1221.     if (!project_info.region) {    /* Rectangular box given */
  1222.         (*forward) (project_info.w, project_info.s, &xmin, &ymin);
  1223.         (*forward) (project_info.e, project_info.n, &xmax, &ymax);
  1224.                 
  1225.         outside = (PFI) rect_outside2;
  1226.         crossing = (PFI) rect_crossing;
  1227.         overlap = (PFI) rect_overlap;
  1228.         map_clip = (PFI) rect_clip;
  1229.         left_edge = (PFD) left_rect;
  1230.         right_edge = (PFD) right_rect;
  1231.         frame_info.check_side = !gmtdefs.oblique_anotation;
  1232.         frame_info.horizontal = (fabs (project_info.pars[1]) < 30.0 && fabs (project_info.n - project_info.s) < 30.0);
  1233.         search = TRUE;
  1234.     }
  1235.     else {
  1236.         if (fabs (project_info.pars[1]) == 90.0) {    /* Polar aspect */
  1237.             if (!project_info.north_pole && project_info.s == -90.0) project_info.edge[0] = FALSE;
  1238.             if (project_info.north_pole && project_info.n == 90.0) project_info.edge[2] = FALSE;
  1239.             if ((fabs (project_info.w - project_info.e) == 360.0 || project_info.w == project_info.e)) project_info.edge[1] = project_info.edge[3] = FALSE;
  1240.             outside = (PFI) polar_outside;
  1241.             crossing = (PFI) wesn_crossing;
  1242.             overlap = (PFI) wesn_overlap;
  1243.             map_clip = (PFI) wesn_clip;
  1244.             frame_info.horizontal = TRUE;
  1245.             gmtdefs.n_lat_nodes = 2;
  1246.             xy_search (&xmin, &xmax, &ymin, &ymax);
  1247.         }
  1248.         else {    /* Global view only */
  1249.             frame_info.anot_int[0] = frame_info.anot_int[1] = 0.0;    /* No annotations for global mode */
  1250.             frame_info.frame_int[0] = frame_info.frame_int[1] = 0.0;    /* No tickmarks for global mode */
  1251.             project_info.w = 0.0;
  1252.             project_info.e = 360.0;
  1253.             project_info.s = -90.0;
  1254.             project_info.n = 90.0;
  1255.             xmin = ymin = -2.0 * EQ_RAD;
  1256.             xmax = ymax = -xmin;
  1257.             outside = (PFI) radial_outside;
  1258.             crossing = (PFI) radial_crossing;
  1259.             overlap = (PFI) radial_overlap;
  1260.             map_clip = (PFI) radial_clip;
  1261.             gmtdefs.basemap_type = 1;
  1262.         }
  1263.         search = FALSE;
  1264.         left_edge = (PFD) left_circle;
  1265.         right_edge = (PFD) right_circle;
  1266.     }
  1267.                 
  1268.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[2]);
  1269.     project_info.r = 0.5 * project_info.xmax;
  1270.         
  1271.     return (search);
  1272. }
  1273.     
  1274. int vplrs (rlong0, plat)
  1275. double rlong0, plat; {
  1276.     /* Set up a polar stereographic transformation (spherical) */
  1277.     
  1278.     project_info.central_meridian = rlong0;
  1279.     project_info.pole = plat;
  1280.     project_info.north_pole = (plat > 0.0);
  1281.     project_info.s_c = 2.0 * EQ_RAD * gmtdefs.map_scale_factor / d_sqrt (pow (1.0 + ECC, 1.0 + ECC) * pow (1.0 - ECC, 1.0 - ECC));
  1282.     return (0);
  1283. }
  1284.  
  1285. int plrs (lon, lat, x, y)
  1286. double lon, lat, *x, *y; {
  1287.     /* Convert lon/lat to x/y using polar projection */
  1288.     double t, rho, lambda, phi;
  1289.     
  1290.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  1291.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  1292.  
  1293.     lambda = (lon - project_info.central_meridian) * D2R;
  1294.     lat *= D2R;
  1295.     phi = (project_info.north_pole) ? lat : -lat;
  1296.     t = tan (M_PI_4 - 0.5 * phi) / pow ((1.0 - ECC * sin (phi)) / (1.0 + ECC * sin (phi)), 0.5 * ECC);
  1297.     rho = project_info.s_c * t;
  1298.     
  1299.     *x = rho * sin (lambda);
  1300.     *y = (project_info.north_pole) ? -rho * cos (lambda) : rho * cos (lambda);
  1301. }
  1302.  
  1303. int iplrs (lon, lat, x, y)
  1304. double *lon, *lat, x, y; {
  1305.     int i;
  1306.     double rho, temp, tphi, t, delta, phi;
  1307.  
  1308.     /* Convert polar x/y to lon/lat */
  1309.     
  1310.     if (x == 0.0 && y == 0.0) {
  1311.         *lon = project_info.central_meridian;
  1312.         *lat = project_info.pole;
  1313.     }
  1314.     else {
  1315.         *lon = project_info.central_meridian + ((project_info.north_pole) ? d_atan2 (x, -y) : d_atan2 (x, y)) * R2D;        
  1316.         rho = hypot (x, y);
  1317.         t = rho / project_info.s_c;
  1318.         tphi = M_PI_2 - 2.0 * atan (t);
  1319.         delta = 1.0;
  1320.         for (i = 0; i < 100 && delta > 1.0e-8; i++) {
  1321.             temp = (1.0 - ECC * sin (tphi)) / (1.0 + ECC * sin (tphi));
  1322.             phi = M_PI_2 - 2.0 * atan (t * pow (temp, 0.5 * ECC));
  1323.             delta = fabs (fabs (tphi) - fabs (phi));
  1324.             tphi = phi;
  1325.         }
  1326.         *lat = (project_info.north_pole) ? phi * R2D : -phi * R2D;
  1327.     }
  1328. }
  1329.  
  1330. /* STEREO: For general oblique view */
  1331.  
  1332. int vstereo (rlong0, plat)
  1333. double rlong0, plat; {
  1334.     double s, m1, z1;
  1335.     /* Set up a polar stereographic transformation (spherical) */
  1336.     
  1337.     project_info.central_meridian = rlong0;
  1338.     project_info.pole = plat;
  1339.     project_info.sinp = sind (plat);
  1340.     project_info.cosp = cosd (plat);
  1341.     project_info.north_pole = (plat > 0.0);
  1342.     m1 = cosd (plat) / sqrt (1.0 - ECC2 * pow (sind (plat), 2.0));
  1343.     s = sind (plat);
  1344.     z1 = 2.0 * atan (sqrt (pow ((1.0 - ECC * s) / (1.0 + ECC * s), ECC) * (1.0 + s) / (1.0 - s))) - M_PI_2;
  1345.     project_info.s_cosz1 = cos (z1);
  1346.     project_info.s_sinz1 = sin (z1);
  1347.     project_info.s_c = 2.0 * EQ_RAD * gmtdefs.map_scale_factor * m1;
  1348.     return (0);
  1349. }
  1350.  
  1351. int stereo1 (lon, lat, x, y)
  1352. double lon, lat, *x, *y; {
  1353.     double dlon, s, z, A;
  1354.     
  1355.     /* Convert lon/lat to x/y using stereographic projection, oblique view */
  1356.  
  1357.     dlon = lon - project_info.central_meridian;
  1358.     s = sind (lat);
  1359.     z = 2.0 * atan (sqrt (pow ((1.0 - ECC * s) / (1.0 + ECC * s), ECC) * (1.0 + s) / (1.0 - s))) - M_PI_2;
  1360.     A = project_info.s_c / (project_info.s_cosz1 * (1.0 + project_info.s_sinz1 * sin (z) +
  1361.         project_info.s_cosz1 * cos (z) * cosd (dlon)));
  1362.     *x = A * cos (z) * sind (dlon);
  1363.     *y = A * (project_info.s_cosz1 * sin (z) - project_info.s_sinz1 * cos (z) * cosd (dlon));
  1364. }
  1365.  
  1366. int istereo (lon, lat, x, y)
  1367. double *lon, *lat, x, y; {
  1368.     int i;
  1369.     double rho, s, z, delta, ce, tphi, phi;
  1370.     
  1371.     if (x == 0.0 && y == 0.0) {
  1372.         *lon = project_info.central_meridian;
  1373.         *lat = project_info.pole;
  1374.     }
  1375.     else {
  1376.         rho = hypot (x, y);
  1377.         ce = 2.0 * atan (rho * project_info.s_cosz1 / project_info.s_c);
  1378.         z = d_asin (cos (ce) * project_info.s_sinz1 + (y * sin (ce) * project_info.s_cosz1 / rho));
  1379.         delta = 1.0;
  1380.         s = sin (z);
  1381.         tphi = 2.0 * atan (tan (M_PI_4 + 0.5 * z) * pow ((1.0 + ECC * s)/(1.0 - ECC * s), 0.5 * ECC)) - M_PI_2;
  1382.         for (i = 0; i < 100 && delta > 1.0e-8; i++) {
  1383.             s = sin (tphi);
  1384.             phi = 2.0 * atan (tan (M_PI_4 + 0.5 * z) * pow ((1.0 + ECC * s)/(1.0 - ECC * s), 0.5 * ECC)) - M_PI_2;
  1385.             delta = fabs (fabs (tphi) - fabs (phi));
  1386.             tphi = phi;
  1387.         }
  1388.         *lat = phi * R2D;
  1389.         *lon = project_info.central_meridian +
  1390.             R2D * atan (x * sin (ce) / (rho * project_info.s_cosz1 * cos (ce) -
  1391.             y * project_info.s_sinz1 * sin (ce)));
  1392.     }
  1393. }
  1394.     
  1395. /* For equatorial view */
  1396.  
  1397. int stereo2 (lon, lat, x, y)
  1398. double lon, lat, *x, *y; {
  1399.     double dlon, s, z, A;
  1400.     
  1401.     /* Convert lon/lat to x/y using stereographic projection, equatorial view */
  1402.  
  1403.     dlon = lon - project_info.central_meridian;
  1404.     s = sind (lat);
  1405.     z = 2.0 * atan (sqrt (pow ((1.0 - ECC * s) / (1.0 + ECC * s), ECC) * (1.0 + s) / (1.0 - s))) - M_PI_2;
  1406.     A = project_info.s_c / (project_info.s_cosz1 * (1.0 + project_info.s_sinz1 * sin (z) +
  1407.         project_info.s_cosz1 * cos (z) * cosd (dlon)));
  1408.     *x = A * cos (z) * sind (dlon);
  1409.     *y = A * sin (z);
  1410. }
  1411.  
  1412. /*
  1413.  *    TRANSFORMATION ROUTINES FOR THE LAMBERT CONFORMAL CONIC PROJECTION
  1414.  */
  1415.  
  1416. int map_init_lambert () {
  1417.     BOOLEAN search;
  1418.     double xmin, xmax, ymin, ymax;
  1419.     
  1420.     vlamb (project_info.pars[0], project_info.pars[1], project_info.pars[2], project_info.pars[3]);
  1421.     if (project_info.units_pr_degree) project_info.pars[4] /= M_PR_DEG;
  1422.     project_info.x_scale = project_info.y_scale = project_info.pars[4];
  1423.     forward = (PFI)lamb;        inverse = (PFI)ilamb;
  1424.             
  1425.     if (!project_info.region) {    /* Rectangular box given*/
  1426.         lamb (project_info.w, project_info.s, &xmin, &ymin);
  1427.         lamb (project_info.e, project_info.n, &xmax, &ymax);
  1428.                 
  1429.         outside = (PFI) rect_outside;
  1430.         crossing = (PFI) rect_crossing;
  1431.         overlap = (PFI) rect_overlap;
  1432.         map_clip = (PFI) rect_clip;
  1433.         left_edge = (PFD) left_rect;
  1434.         right_edge = (PFD) right_rect;
  1435.         search = TRUE;
  1436.         frame_info.check_side = !gmtdefs.oblique_anotation;
  1437.     }
  1438.     else {
  1439.         xy_search (&xmin, &xmax, &ymin, &ymax);
  1440.         outside = (PFI) wesn_outside;
  1441.         crossing = (PFI) wesn_crossing;
  1442.         overlap = (PFI) wesn_overlap;
  1443.         map_clip = (PFI) wesn_clip;
  1444.         left_edge = (PFD) left_lambert;
  1445.         right_edge = (PFD) right_lambert;
  1446.         search = FALSE;
  1447.     }
  1448.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[4]);
  1449.     gmtdefs.n_lat_nodes = 2;
  1450.     frame_info.horizontal = TRUE;
  1451.     return (search);
  1452. }
  1453.  
  1454. int vlamb (rlong0, rlat0, pha, phb)
  1455. double rlong0, rlat0, pha, phb; {
  1456.     /* Set up a Lambert Conformal Conic projection */
  1457.     
  1458.     double t_pha, m_pha, t_phb, m_phb, t_rlat0;
  1459.     
  1460.     project_info.north_pole = (rlat0 > 0.0);
  1461.     project_info.pole = (project_info.north_pole) ? 90.0 : -90.0;
  1462.     pha *= D2R;
  1463.     phb *= D2R;
  1464.     
  1465.     t_pha = tan (45.0 * D2R - 0.5 * pha) / pow ((1.0 - ECC * 
  1466.         sin (pha)) / (1.0 + ECC * sin (pha)), 0.5 * ECC);
  1467.     m_pha = cos (pha) / d_sqrt (1.0 - ECC2 
  1468.         * pow (sin (pha), 2.0));
  1469.     t_phb = tan (45.0 * D2R - 0.5 * phb) / pow ((1.0 - ECC *
  1470.         sin (phb)) / (1.0 + ECC * sin (phb)), 0.5 * ECC);
  1471.     m_phb = cos (phb) / d_sqrt (1.0 - ECC2 
  1472.         * pow (sin (phb), 2.0));
  1473.     t_rlat0 = tan (45.0 * D2R - 0.5 * rlat0 * D2R) /
  1474.         pow ((1.0 - ECC * sin (rlat0 * D2R)) /
  1475.         (1.0 + ECC * sin (rlat0 * D2R)), 0.5 * ECC);
  1476.     
  1477.     if(pha != phb)
  1478.         project_info.l_N = (d_log(m_pha) - d_log(m_phb))/(d_log(t_pha) - d_log(t_phb));
  1479.     else
  1480.         project_info.l_N = sin(pha);
  1481.     
  1482.     project_info.l_F = m_pha/(project_info.l_N * pow(t_pha,project_info.l_N));
  1483.     project_info.central_meridian = rlong0;
  1484.     project_info.l_rho0 = EQ_RAD * project_info.l_F * pow(t_rlat0,project_info.l_N);
  1485. }
  1486.  
  1487. int lamb (lon, lat, x, y)
  1488. double lon, lat, *x, *y; {
  1489.     double rho,theta,hold1,hold2,hold3;
  1490.     
  1491.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  1492.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  1493.     lat *= D2R;
  1494.  
  1495.     hold2 = pow (((1.0 - ECC * sin (lat)) / (1.0 + ECC * sin (lat))), 0.5 * ECC);
  1496.     hold3 = tan (45.0 * D2R - 0.5 * lat);
  1497.     if (fabs (hold3) < SMALL) hold3 = 0.0;
  1498.     hold1 = (hold3 == 0.0) ? 0.0 : pow (hold3 / hold2, project_info.l_N);
  1499.     rho = EQ_RAD * project_info.l_F * hold1;
  1500.     theta = project_info.l_N * (lon - project_info.central_meridian) * D2R;
  1501.  
  1502.     *x = rho * sin (theta);
  1503.     *y = project_info.l_rho0 - rho * cos (theta);
  1504. }
  1505.  
  1506. int ilamb (lon, lat, x, y)
  1507. double *lon, *lat, x, y; {
  1508.     int i;
  1509.     double theta, temp, rho, t, tphi, phi, delta;
  1510.     
  1511.     theta = atan (x / (project_info.l_rho0 - y));
  1512.     *lon = (theta /project_info.l_N) * R2D + project_info.central_meridian;
  1513.     
  1514.     temp = x * x + (project_info.l_rho0 - y) * (project_info.l_rho0 - y);
  1515.     rho = copysign (d_sqrt (temp), project_info.l_N);
  1516.     t = pow ((rho / (EQ_RAD * project_info.l_F)), 1./project_info.l_N);
  1517.     tphi = 90.0 * D2R - 2.0 * atan (t);
  1518.     delta = 1.0;
  1519.     for (i = 0; i < 100 && delta > 1.0e-8; i++) {
  1520.         temp = (1.0 - ECC * sin (tphi)) / (1.0 + ECC * sin (tphi));
  1521.         phi = 90.0 * D2R - 2.0 * atan (t * pow (temp, 0.5 * ECC));
  1522.         delta = fabs (fabs (tphi) - fabs (phi));
  1523.         tphi = phi;
  1524.     }
  1525.     *lat = phi * R2D;
  1526. }
  1527.  
  1528. /*
  1529.  *    TRANSFORMATION ROUTINES FOR THE OBLIQUE MERCATOR PROJECTION
  1530.  */
  1531.  
  1532. int map_init_oblique () {
  1533.     double xmin, xmax, ymin, ymax;
  1534.     double o_x, o_y, p_x, p_y, c, az, b_x, b_y, w, e, s, n;
  1535.  
  1536.     gmt_set_spherical ();    /* PW: Force spherical for now */
  1537.  
  1538.     if (project_info.units_pr_degree) project_info.pars[4] /= M_PR_DEG;    /* To get plot-units / m */
  1539.             
  1540.     o_x = project_info.pars[0];    o_y = project_info.pars[1];
  1541.             
  1542.     if (project_info.pars[6] == 1.0) {    /* Must get correct origin, then get second point */
  1543.         p_x = project_info.pars[2];    p_y = project_info.pars[3];
  1544.                 
  1545.          project_info.o_pole_lon = D2R * p_x;
  1546.          project_info.o_sin_pole_lat = sind (p_y);
  1547.          project_info.o_cos_pole_lat = cosd (p_y);
  1548.          
  1549.          /* Find azimuth to pole, add 90, and compute second point 10 degrees away */
  1550.          
  1551.         get_origin (o_x, o_y, p_x, p_y, &o_x, &o_y);
  1552.          az = R2D * atan (cosd (p_y) * sind (p_x - o_x) / (cosd (o_y) * sind (p_y) - sind (o_y) * cosd (p_y) * cosd (p_x - o_x))) + 90.0;
  1553.          c = 10.0;    /* compute point 10 degrees from origin along azimuth */
  1554.          b_x = o_x + R2D * atan (sind (c) * sind (az) / (cosd (o_y) * cosd (c) - sind (o_y) * sind (c) * cosd (az)));
  1555.          b_y = R2D * d_asin (sind (o_y) * cosd (c) + cosd (o_y) * sind (c) * cosd (az));
  1556.          project_info.pars[0] = o_x;    project_info.pars[1] = o_y;
  1557.          project_info.pars[2] = b_x;    project_info.pars[3] = b_y;
  1558.      }
  1559.      else {    /* Just find pole */
  1560.         b_x = project_info.pars[2];    b_y = project_info.pars[3];
  1561.          get_rotate_pole (o_x, o_y, b_x, b_y);
  1562.     }
  1563.             
  1564.     vmerc (0.0);    /* Because origin will have 0 degree oblique */
  1565.             
  1566.     if (project_info.region) {
  1567.         /* Convert oblique wesn in degrees to meters using regular Mercator */
  1568.         if (fabs (project_info.w - project_info.e) == 360.0) {
  1569.             project_info.w = -180.0;
  1570.             project_info.e = 180.0;
  1571.         }
  1572.         merc (project_info.w, project_info.s, &xmin, &ymin);
  1573.         merc (project_info.e, project_info.n, &xmax, &ymax);
  1574.         vmerc (0.0);
  1575.         project_info.region = FALSE;    /* Since wesn was oblique, not geographical wesn */
  1576.     }
  1577.     else {
  1578.         /* wesn is lower left and upper right corners in normal lon/lats */
  1579.                 
  1580.         oblmrc (project_info.w, project_info.s, &xmin, &ymin);
  1581.         oblmrc (project_info.e, project_info.n, &xmax, &ymax);
  1582.     }
  1583.     
  1584.     imerc (&w, &s, xmin, ymin);    /* Get oblique wesn boundaries */
  1585.     imerc (&e, &n, xmax, ymax);
  1586.     project_info.x_scale = project_info.y_scale = project_info.pars[4];
  1587.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[4]);
  1588.                 
  1589.     forward = (PFI)oblmrc;        inverse = (PFI)ioblmrc;
  1590.     outside = (PFI) rect_outside;
  1591.     crossing = (PFI) rect_crossing;
  1592.     overlap = (PFI) rect_overlap;
  1593.     map_clip = (PFI) rect_clip;
  1594.     left_edge = (PFD) left_rect;
  1595.     right_edge = (PFD) right_rect;
  1596.             
  1597.     gmt_world_map = (fabs (fabs (w - e) - 360.0) < SMALL);
  1598.     gmtdefs.basemap_type = 1;
  1599.     frame_info.check_side = !gmtdefs.oblique_anotation;
  1600.     
  1601.     return (TRUE);
  1602. }
  1603.  
  1604. int oblmrc (lon, lat, x, y)
  1605. double lon, lat;
  1606. double *x, *y; {
  1607.     /* Convert a longitude/latitude point to Oblique Mercator coordinates 
  1608.      * by way of rotation coordinates and then using regular Mercator */
  1609.     double tlon, tlat;
  1610.     
  1611.     pole_rotate_forward (lon, lat, &tlon, &tlat);
  1612.     merc (tlon, tlat, x, y);
  1613. }
  1614.  
  1615. int ioblmrc (lon, lat, x, y)
  1616. double *lon, *lat;
  1617. double x, y; {
  1618.     /* Convert a longitude/latitude point from Oblique Mercator coordinates 
  1619.      * by way of regular Mercator and then rotate coordinates */
  1620.     double tlon, tlat;
  1621.     
  1622.     imerc (&tlon, &tlat, x, y);
  1623.     pole_rotate_inverse (lon, lat, tlon, tlat);
  1624. }
  1625.  
  1626. int pole_rotate_forward (lon, lat, tlon, tlat)
  1627. double lon, lat, *tlon, *tlat; {
  1628.     /* Given the pole position in project_info, geographical coordinates
  1629.      * are computed from oblique coordinates assuming a spherical earth.
  1630.      */
  1631.      
  1632.      double dlon, x, y, test;
  1633.      
  1634.      lon *= D2R;    lat *= D2R;
  1635.      dlon = lon - project_info.o_pole_lon;
  1636.      test = project_info.o_sin_pole_lat * sin (lat) + project_info.o_cos_pole_lat * cos (lat) * cos (dlon);
  1637.      y = d_asin (test);
  1638.      x = project_info.o_beta + d_atan2 (cos (lat) * sin (dlon), project_info.o_sin_pole_lat * cos (lat) * cos (dlon)
  1639.          - project_info.o_cos_pole_lat * sin (lat));
  1640.      
  1641.      *tlon = R2D * x;    *tlat = R2D * y;
  1642. }
  1643.      
  1644. int pole_rotate_inverse (lon, lat, tlon, tlat)
  1645. double *lon, *lat, tlon, tlat; {
  1646.     /* Given the pole position in project_info, geographical coordinates 
  1647.      * are computed from oblique coordinates assuming a spherical earth.
  1648.      */
  1649.      
  1650.      double dlon, x, y, test;
  1651.      
  1652.      tlon *= D2R;    tlat *= D2R;
  1653.      dlon = tlon - project_info.o_beta;
  1654.      test = project_info.o_sin_pole_lat * sin (tlat) - project_info.o_cos_pole_lat * cos (tlat) * cos (dlon);
  1655.      y = d_asin (test);
  1656.      x = project_info.o_pole_lon + d_atan2 (cos (tlat) * sin (dlon), project_info.o_sin_pole_lat * cos (tlat) * cos (dlon)
  1657.          + project_info.o_cos_pole_lat * sin (tlat));
  1658.      
  1659.      *lon = R2D * x;    *lat = R2D * y;
  1660. }
  1661.  
  1662. int get_rotate_pole (lon1, lat1, lon2, lat2)
  1663. double lon1, lat1, lon2, lat2; {
  1664.     double plon, plat, beta, dummy;
  1665.     
  1666. #ifdef aix
  1667.     double aix_cpp_sucks1, aix_cpp_sucks2;
  1668.     
  1669.     aix_cpp_sucks1 =  cosd (lat1) * sind (lat2) * cosd (lon1) - sind (lat1) * cosd (lat2) * cosd (lon2);
  1670.     aix_cpp_sucks2 = sind (lat1) * cosd (lat2) * sind (lon2) - cosd (lat1) * sind (lat2) * sind (lon1);
  1671.     plon = R2D * d_atan2 (aix_cpp_sucks1, aix_cpp_sucks2);
  1672. #else
  1673.     plon = R2D * d_atan2 (cosd (lat1) * sind (lat2) * cosd (lon1) - sind (lat1) * cosd (lat2) * cosd (lon2),
  1674.         sind (lat1) * cosd (lat2) * sind (lon2) - cosd (lat1) * sind (lat2) * sind (lon1));
  1675. #endif
  1676.  
  1677.     plat = R2D * atan (-cosd (plon - lon1) / tand (lat1));
  1678.     if (plat < 0.0) {
  1679.         plat = -plat;
  1680.         plon += 180.0;
  1681.         if (plon >= 360.0) plon -= 360.0;
  1682.     }
  1683.     project_info.o_pole_lon = D2R * plon;
  1684.     project_info.o_sin_pole_lat = sind (plat);
  1685.     project_info.o_cos_pole_lat = cosd (plat);
  1686.     pole_rotate_forward (lon1, lat1, &beta, &dummy);
  1687.     project_info.o_beta = -beta * D2R;
  1688. }
  1689.  
  1690. int get_origin (lon1, lat1, lon_p, lat_p, lon2, lat2)
  1691. double lon1, lat1, lon_p, lat_p, *lon2, *lat2; {
  1692.     double beta, dummy, d, az, c;
  1693.     
  1694.     
  1695.     /* Now find origin that is 90 degrees from pole, let oblique lon=0 go through lon1/lat1 */
  1696. #ifdef aix 
  1697.         c = cosd (lat_p) * cosd (lat1) * cosd (lon1-lon_p);
  1698.         c = R2D * d_acos (sind (lat_p) * sind (lat1) + c);
  1699. #else 
  1700.         c = R2D * d_acos (sind (lat_p) * sind (lat1) + cosd (lat_p) * cosd (lat1) * cosd (lon1-lon_p));
  1701. #endif     
  1702.     
  1703.     if (c != 90.0) {    /* Not true origin */
  1704.         d = fabs (90.0 - c);
  1705.         az = R2D * d_asin (sind (lon_p-lon1) * cosd (lat_p) / sind (c));
  1706.         if (c < 90.0) az += 180.0;
  1707.         *lat2 = R2D * d_asin (sind (lat1) * cosd (d) + cosd (lat1) * sind (d) * cosd (az));
  1708.         *lon2 = lon1 + R2D * d_atan2 (sind (d) * sind (az), cosd (lat1) * cosd (d) - sind (lat1) * sind (d) * cosd (az));
  1709.         if (gmtdefs.verbose) fprintf (stderr, "%s: GMT Warning: Correct projection origin = %lg/%lg\n", gmt_program, *lon2, *lat2);
  1710.     }
  1711.     else {
  1712.         *lon2 = lon1;
  1713.         *lat2 = lat1;
  1714.     }
  1715.     
  1716.     pole_rotate_forward (*lon2, *lat2, &beta, &dummy);
  1717.     
  1718.     
  1719.     project_info.o_beta = -beta * D2R;
  1720. }
  1721.  
  1722. /*
  1723.  *    TRANSFORMATION ROUTINES FOR THE TRANSVERSE MERCATOR PROJECTION (TM)
  1724.  */
  1725.  
  1726. int map_init_tm () {
  1727.     BOOLEAN search;
  1728.     double xmin, xmax, ymin, ymax;
  1729.     
  1730.     vtm (project_info.pars[0]);
  1731.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  1732.     project_info.x_scale = project_info.y_scale = project_info.pars[1];
  1733.     forward = (PFI)tm;        inverse = (PFI)itm;
  1734.             
  1735.     if (project_info.region) {
  1736.         xy_search (&xmin, &xmax, &ymin, &ymax);
  1737.         outside = (PFI) wesn_outside;
  1738.         crossing = (PFI) wesn_crossing;
  1739.         overlap = (PFI) wesn_overlap;
  1740.         map_clip = (PFI) wesn_clip;
  1741.         left_edge = (PFD) left_rect;
  1742.         right_edge = (PFD) right_rect;
  1743.         search = FALSE;
  1744.     }
  1745.     else { /* Find min values */
  1746.         (*forward) (project_info.w, project_info.s, &xmin, &ymin);
  1747.         (*forward) (project_info.e, project_info.n, &xmax, &ymax);
  1748.         outside = (PFI) rect_outside;
  1749.         crossing = (PFI) rect_crossing;
  1750.         overlap = (PFI) rect_overlap;
  1751.         map_clip = (PFI) rect_clip;
  1752.         left_edge = (PFD) left_rect;
  1753.         right_edge = (PFD) right_rect;
  1754.         frame_info.check_side = TRUE;
  1755.         search = TRUE;
  1756.     }
  1757.             
  1758.     frame_info.horizontal = TRUE;
  1759.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[1]);
  1760.             
  1761.     gmtdefs.basemap_type = 1;
  1762.     
  1763.     return (search);
  1764. }
  1765.  
  1766. int vtm (lon0)
  1767. double lon0; {
  1768.     /* Set up an TM projection */
  1769.     double e1;
  1770.     
  1771.     e1 = (1.0 - d_sqrt (1.0 - ECC2)) / (1.0 + d_sqrt (1.0 - ECC2));
  1772.     project_info.t_e2 = ECC2 / (1.0 - ECC2);
  1773.     project_info.t_c1 = (1.0 - 0.25 * ECC2 - 3.0 * ECC4 / 64.0 - 5.0 * ECC6 / 256.0);
  1774.     project_info.t_c2 = (3.0 * ECC2 / 8.0 + 3.0 * ECC4 / 32.0 + 45.0 * ECC6 / 1024.0);
  1775.     project_info.t_c3 = (15.0 * ECC4 / 256.0 + 45.0 * ECC6 / 1024.0);
  1776.     project_info.t_c4 = (35.0 * ECC6 / 3072.0);
  1777.     project_info.t_ic1 = (1.5 * e1 - 27.0 * pow (e1, 3.0) / 32.0);
  1778.     project_info.t_ic2 = (21.0 * e1 * e1 / 16.0 - 55.0 * pow (e1, 4.0) / 32.0);
  1779.     project_info.t_ic3 = (151.0 * pow (e1, 3.0) / 96.0);
  1780.     project_info.t_ic4 = (1097.0 * pow (e1, 4.0) / 512.0);
  1781.     project_info.central_meridian = lon0;
  1782. }
  1783.  
  1784. int tm (lon, lat, x, y)
  1785. double lon, lat, *x, *y; {
  1786.     /* Convert lon/lat to TM x/y */
  1787.     double N, T, T2, C, A, M, dlon, tan_lat, cos_lat, A2, A3, A5;
  1788.     
  1789.     dlon = lon - project_info.central_meridian;
  1790.     if (fabs (dlon) > 360.0) dlon += copysign (360.0, -dlon);
  1791.     if (fabs (dlon) > 180.0) dlon = copysign (360.0 - fabs (dlon), -dlon);
  1792.     lat *= D2R;
  1793.     M = EQ_RAD * (project_info.t_c1 * lat - project_info.t_c2 * sin (2.0 * lat)
  1794.         + project_info.t_c3 * sin (4.0 * lat) - project_info.t_c4 * sin (6.0 * lat));
  1795.     if (fabs (lat) == M_PI_2) {
  1796.         *x = 0.0;
  1797.         *y = gmtdefs.map_scale_factor * M;
  1798.     }
  1799.     else {
  1800.         N = EQ_RAD / d_sqrt (1.0 - ECC2 * pow (sin (lat), 2.0));
  1801.         tan_lat = tan (lat);
  1802.         cos_lat = cos (lat);
  1803.         T = tan_lat * tan_lat;
  1804.         T2 = T * T;
  1805.         C = project_info.t_e2 * cos_lat * cos_lat;
  1806.         A = dlon * D2R * cos_lat;
  1807.         A2 = A * A;    A3 = A2 * A;    A5 = A3 * A2;
  1808.         *x = gmtdefs.map_scale_factor * N * (A + (1.0 - T + C) * (A3 * 0.16666666666666666667)
  1809.             + (5.0 - 18.0 * T + T2 + 72.0 * C - 58.0 * project_info.t_e2) * (A5 * 0.00833333333333333333));
  1810.         A3 *= A;    A5 *= A;
  1811.         *y = gmtdefs.map_scale_factor * (M + N * tan (lat) * (0.5 * A2 + (5.0 - T + 9.0 * C + 4.0 * C * C) * (A3 * 0.04166666666666666667)
  1812.             + (61.0 - 58.0 * T + T2 + 600.0 * C - 330.0 * project_info.t_e2) * (A5 * 0.00138888888888888889)));
  1813.     }
  1814. }
  1815.  
  1816. int itm (lon, lat, x, y)
  1817. double *lon, *lat, x, y; {
  1818.     /* Convert TM x/y to lon/lat */
  1819.     double M, mu, phi1, C1, C12, T1, T12, tmp, tmp2, N1, R1, D, D2, D3, D5, cos_phi1, tan_phi1;
  1820.     
  1821.     M = y / gmtdefs.map_scale_factor;
  1822.     mu = M / (EQ_RAD * project_info.t_c1);
  1823.     phi1 = mu + project_info.t_ic1 * sin (2.0 * mu) + project_info.t_ic2 * sin (4.0 * mu)
  1824.         + project_info.t_ic3 * sin (6.0 * mu) + project_info.t_ic4 * sin (8.0 * mu);
  1825.     cos_phi1 = cos (phi1);
  1826.     tan_phi1 = tan (phi1);
  1827.     C1 = project_info.t_e2 * cos_phi1 * cos_phi1;
  1828.     C12 = C1 * C1;
  1829.     T1 = tan_phi1 * tan_phi1;
  1830.     T12 = T1 * T1;
  1831.     tmp = 1.0 - ECC2 * (1.0 - cos_phi1 * cos_phi1);
  1832.     tmp2 = d_sqrt (tmp);
  1833.     N1 = EQ_RAD / tmp2;
  1834.     R1 = EQ_RAD * (1.0 - ECC2) / (tmp * tmp2);
  1835.     D = x / (N1 * gmtdefs.map_scale_factor);
  1836.     D2 = D * D;    D3 = D2 * D;    D5 = D3 * D2;
  1837.     
  1838.     *lon = project_info.central_meridian + R2D * (D - (1.0 + 2.0 * T1 + C1) * (D3 * 0.16666666666666666667) 
  1839.         + (5.0 - 2.0 * C1 + 28.0 * T1 - 3.0 * C12 + 8.0 * project_info.t_e2 + 24.0 * T12)
  1840.         * (D5 * 0.00833333333333333333)) / cos (phi1);
  1841.     D3 *= D;    D5 *= D;
  1842.     *lat = phi1 - (N1 * tan (phi1) / R1) * (0.5 * D2 -
  1843.         (5.0 + 3.0 * T1 + 10.0 * C1 - 4.0 * C12 - 9.0 * project_info.t_e2) * (D3 * 0.04166666666666666667)
  1844.         + (61.0 + 90.0 * T1 + 298 * C1 + 45.0 * T12 - 252.0 * project_info.t_e2 - 3.0 * C12) * (D5 * 0.00138888888888888889));
  1845.     (*lat) *= R2D;
  1846. }
  1847.  
  1848. /*
  1849.  *    TRANSFORMATION ROUTINES FOR THE UNIVERSAL TRANSVERSE MERCATOR PROJECTION (UTM)
  1850.  */
  1851.  
  1852. int map_init_utm () {
  1853.     BOOLEAN search;
  1854.     double xmin, xmax, ymin, ymax, lon0;
  1855.     
  1856.     lon0 = 180.0 + 6.0 * project_info.pars[0] - 3.0;
  1857.     if (lon0 >= 360.0) lon0 -= 360.0;
  1858.     vtm (lon0);    /* Central meridian for this zone */
  1859.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  1860.     project_info.x_scale = project_info.y_scale = project_info.pars[1];
  1861.     forward = (PFI)utm;        inverse = (PFI)iutm;
  1862.             
  1863.     if (fabs (project_info.w - project_info.e) > 360.0) {    /* -R in UTM meters */
  1864.         iutm (&project_info.w, &project_info.s, project_info.w, project_info.s);
  1865.         iutm (&project_info.e, &project_info.n, project_info.e, project_info.n);
  1866.         project_info.region = FALSE;
  1867.     }
  1868.     if (project_info.region) {
  1869.         xy_search (&xmin, &xmax, &ymin, &ymax);
  1870.         outside = (PFI) wesn_outside;
  1871.         crossing = (PFI) wesn_crossing;
  1872.         overlap = (PFI) wesn_overlap;
  1873.         map_clip = (PFI) wesn_clip;
  1874.         left_edge = (PFD) left_rect;
  1875.         right_edge = (PFD) right_rect;
  1876.         search = FALSE;
  1877.     }
  1878.     else {
  1879.         utm (project_info.w, project_info.s, &xmin, &ymin);
  1880.         utm (project_info.e, project_info.n, &xmax, &ymax);
  1881.         outside = (PFI) rect_outside;
  1882.         crossing = (PFI) rect_crossing;
  1883.         overlap = (PFI) rect_overlap;
  1884.         map_clip = (PFI) rect_clip;
  1885.         left_edge = (PFD) left_rect;
  1886.         right_edge = (PFD) right_rect;
  1887.         frame_info.check_side = TRUE;
  1888.         search = TRUE;
  1889.     }
  1890.  
  1891.     frame_info.horizontal = TRUE;
  1892.     map_setxy (xmin, xmax, ymin, ymax);
  1893.             
  1894.     gmtdefs.basemap_type = 1;
  1895.     
  1896.     return (search);
  1897. }
  1898.  
  1899. int utm (lon, lat, x, y)
  1900. double lon, lat, *x, *y; {
  1901.     /* Convert lon/lat to UTM x/y */
  1902.  
  1903.     if (lon < 0.0) lon += 360.0;
  1904.     tm (lon, lat, x, y);
  1905.     (*x) += 500000.0;
  1906.     if (!project_info.north_pole) (*y) += 10000000.0;    /* For S hemisphere, add 10^6 m */
  1907. }
  1908.  
  1909. int iutm (lon, lat, x, y)
  1910. double *lon, *lat, x, y; {
  1911.     /* Convert UTM x/y to lon/lat */
  1912.  
  1913.     x -= 500000.0;
  1914.     if (!project_info.north_pole) y -= 10000000.0;
  1915.     itm (lon, lat, x, y);
  1916. }
  1917.  
  1918. /*
  1919.  *    TRANSFORMATION ROUTINES FOR THE LAMBERT AZIMUTHAL EQUAL AREA PROJECTION
  1920.  */
  1921.  
  1922. int map_init_lambeq () {
  1923.     BOOLEAN search;
  1924.     double xmin, xmax, ymin, ymax, dummy, radius;
  1925.  
  1926.     gmt_set_spherical ();    /* PW: Force spherical for now */
  1927.  
  1928.     forward = (PFI)lambeq;        inverse = (PFI)ilambeq;
  1929.     if (project_info.units_pr_degree) {
  1930.         vlambeq (0.0, 90.0);
  1931.         lambeq (0.0, fabs(project_info.pars[3]), &dummy, &radius);
  1932.         project_info.x_scale = project_info.y_scale = fabs (project_info.pars[2] / radius);
  1933.     }
  1934.     else
  1935.         project_info.x_scale = project_info.y_scale = project_info.pars[2];
  1936.     vlambeq (project_info.pars[0], project_info.pars[1]);
  1937.  
  1938.     if (fabs (project_info.pars[1]) == 90.0) {
  1939.         project_info.polar = TRUE;
  1940.         project_info.north_pole    = (project_info.pars[1] == 90.0);
  1941.     }
  1942.     if (!project_info.region) {    /* Rectangular box given */
  1943.         (*forward) (project_info.w, project_info.s, &xmin, &ymin);
  1944.         (*forward) (project_info.e, project_info.n, &xmax, &ymax);
  1945.                 
  1946.         outside = (PFI) rect_outside2;
  1947.         crossing = (PFI) rect_crossing;
  1948.         overlap = (PFI) rect_overlap;
  1949.         map_clip = (PFI) rect_clip;
  1950.         left_edge = (PFD) left_rect;
  1951.         right_edge = (PFD) right_rect;
  1952.         frame_info.check_side = !gmtdefs.oblique_anotation;
  1953.         frame_info.horizontal = (fabs (project_info.pars[1]) < 30.0 && fabs (project_info.n - project_info.s) < 30.0);
  1954.         search = TRUE;
  1955.     }
  1956.     else {
  1957.         if (project_info.polar && (project_info.n - project_info.s) < 180.0) {    /* Polar aspect */
  1958.             if (!project_info.north_pole && project_info.s == -90.0) project_info.edge[0] = FALSE;
  1959.             if (project_info.north_pole && project_info.n == 90.0) project_info.edge[2] = FALSE;
  1960.             if ((fabs (project_info.w - project_info.e) == 360.0 || project_info.w == project_info.e)) project_info.edge[1] = project_info.edge[3] = FALSE;
  1961.             outside = (PFI) polar_outside;
  1962.             crossing = (PFI) wesn_crossing;
  1963.             overlap = (PFI) wesn_overlap;
  1964.             map_clip = (PFI) wesn_clip;
  1965.             frame_info.horizontal = TRUE;
  1966.             gmtdefs.n_lat_nodes = 2;
  1967.             xy_search (&xmin, &xmax, &ymin, &ymax);
  1968.         }
  1969.         else {    /* Global view only */
  1970.             frame_info.anot_int[0] = frame_info.anot_int[1] = 0.0;    /* No annotations for global mode */
  1971.             frame_info.frame_int[0] = frame_info.frame_int[1] = 0.0;    /* No tickmarks for global mode */
  1972.             project_info.w = 0.0;
  1973.             project_info.e = 360.0;
  1974.             project_info.s = -90.0;
  1975.             project_info.n = 90.0;
  1976.             xmin = ymin = -d_sqrt (2.0) * EQ_RAD;
  1977.             xmax = ymax = -xmin;
  1978.             outside = (PFI) radial_outside;
  1979.             crossing = (PFI) radial_crossing;
  1980.             overlap = (PFI) radial_overlap;
  1981.             map_clip = (PFI) radial_clip;
  1982.             gmtdefs.basemap_type = 1;
  1983.         }
  1984.         search = FALSE;
  1985.         left_edge = (PFD) left_circle;
  1986.         right_edge = (PFD) right_circle;
  1987.     }
  1988.                 
  1989.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[2]);
  1990.     project_info.r = 0.5 * project_info.xmax;
  1991.         
  1992.     return (search);
  1993. }
  1994.  
  1995. int vlambeq (lon0, lat0)
  1996. double lon0, lat0; {
  1997.     /* Set up Lambert Azimuthal Equal-Area projection */
  1998.     
  1999.     project_info.central_meridian = lon0;
  2000.     project_info.pole = lat0;
  2001.     project_info.sinp = sin (lat0 * D2R);
  2002.     project_info.cosp = cos (lat0 * D2R);
  2003. }
  2004.  
  2005. int lambeq (lon, lat, x, y)
  2006. double lon, lat, *x, *y; {
  2007.     /* Convert lon/lat to Lambert Azimuthal Equal-Area x/y */
  2008.     double k, dlon, tmp;
  2009.     
  2010.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2011.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2012.     dlon = (lon - project_info.central_meridian) * D2R;
  2013.     lat *= D2R;
  2014.     
  2015.     tmp = 1.0 + project_info.sinp * sin (lat) + project_info.cosp * cos (lat) * cos (dlon);
  2016.     if (tmp > 0.0) {
  2017.         k = d_sqrt (2.0 / tmp);
  2018.         *x = EQ_RAD * k * cos (lat) * sin (dlon);
  2019.         *y = EQ_RAD * k * (project_info.cosp * sin (lat) - project_info.sinp * cos (lat) * cos (dlon));
  2020.     }
  2021.     else
  2022.         *x = *y = -MAXDOUBLE;
  2023. }
  2024.  
  2025. int ilambeq (lon, lat, x, y)
  2026. double *lon, *lat, x, y; {
  2027.     /* Convert Lambert Azimuthal Equal-Area x/yto lon/lat */
  2028.     double rho, c;
  2029.     
  2030.     rho = hypot (x, y);
  2031.     c = 2.0 * d_asin (0.5 * rho / EQ_RAD);
  2032.     
  2033.     if (rho == 0.0) {
  2034.         *lat = project_info.pole;
  2035.         *lon = project_info.central_meridian;
  2036.     }
  2037.     else {
  2038.         *lat = d_asin (cos (c) * project_info.sinp + (y * sin (c) * project_info.cosp / rho)) * R2D;
  2039.         if (project_info.pole == 90.0)
  2040.             *lon = project_info.central_meridian + R2D * d_atan2 (x, -y);
  2041.         else if (project_info.pole == -90.0)
  2042.             *lon = project_info.central_meridian + R2D * d_atan2 (x, y);
  2043.         else
  2044.             *lon = project_info.central_meridian +
  2045.                 R2D * d_atan2 (x * sin (c), (rho * project_info.cosp * cos (c) - y * project_info.sinp * sin (c)));
  2046.     }
  2047. }
  2048.  
  2049. /*
  2050.  *    TRANSFORMATION ROUTINES FOR THE ORTHOGRAPHIC PROJECTION
  2051.  */
  2052.  
  2053. int map_init_ortho () {
  2054.     BOOLEAN search;
  2055.     double xmin, xmax, ymin, ymax, dummy, radius;
  2056.  
  2057.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2058.  
  2059.     if (project_info.units_pr_degree) {
  2060.         vortho (0.0, 90.0);
  2061.         ortho (0.0, fabs(project_info.pars[3]), &dummy, &radius);
  2062.         project_info.x_scale = project_info.y_scale = fabs (project_info.pars[2] / radius);
  2063.     }
  2064.     else
  2065.         project_info.x_scale = project_info.y_scale = project_info.pars[2];
  2066.                 
  2067.     vortho (project_info.pars[0], project_info.pars[1]);
  2068.     forward = (PFI)ortho;        inverse = (PFI)iortho;
  2069.  
  2070.     if (fabs (project_info.pars[1]) == 90.0) {
  2071.         project_info.polar = TRUE;
  2072.         project_info.north_pole    = (project_info.pars[1] == 90.0);
  2073.     }
  2074.     
  2075.     if (!project_info.region) {    /* Rectangular box given */
  2076.         (*forward) (project_info.w, project_info.s, &xmin, &ymin);
  2077.         (*forward) (project_info.e, project_info.n, &xmax, &ymax);
  2078.                 
  2079.         outside = (PFI) rect_outside2;
  2080.         crossing = (PFI) rect_crossing;
  2081.         overlap = (PFI) rect_overlap;
  2082.         map_clip = (PFI) rect_clip;
  2083.         left_edge = (PFD) left_rect;
  2084.         right_edge = (PFD) right_rect;
  2085.         frame_info.check_side = !gmtdefs.oblique_anotation;
  2086.         frame_info.horizontal = (fabs (project_info.pars[1]) < 30.0 && fabs (project_info.n - project_info.s) < 30.0);
  2087.         search = TRUE;
  2088.     }
  2089.     else {
  2090.         if (project_info.polar) {    /* Polar aspect */
  2091.             if (!project_info.north_pole && project_info.s == -90.0) project_info.edge[0] = FALSE;
  2092.             if (project_info.north_pole && project_info.n == 90.0) project_info.edge[2] = FALSE;
  2093.             if ((fabs (project_info.w - project_info.e) == 360.0 || project_info.w == project_info.e)) project_info.edge[1] = project_info.edge[3] = FALSE;
  2094.             outside = (PFI) polar_outside;
  2095.             crossing = (PFI) wesn_crossing;
  2096.             overlap = (PFI) wesn_overlap;
  2097.             map_clip = (PFI) wesn_clip;
  2098.             frame_info.horizontal = TRUE;
  2099.             gmtdefs.n_lat_nodes = 2;
  2100.             xy_search (&xmin, &xmax, &ymin, &ymax);
  2101.         }
  2102.         else {    /* Global view only */
  2103.             frame_info.anot_int[0] = frame_info.anot_int[1] = 0.0;    /* No annotations for global mode */
  2104.             frame_info.frame_int[0] = frame_info.frame_int[1] = 0.0;    /* No tickmarks for global mode */
  2105.             project_info.w = 0.0;
  2106.             project_info.e = 360.0;
  2107.             project_info.s = -90.0;
  2108.             project_info.n = 90.0;
  2109.             xmin = ymin = -EQ_RAD;
  2110.             xmax = ymax = -xmin;
  2111.             outside = (PFI) radial_outside;
  2112.             crossing = (PFI) radial_crossing;
  2113.             overlap = (PFI) radial_overlap;
  2114.             map_clip = (PFI) radial_clip;
  2115.             gmtdefs.basemap_type = 1;
  2116.         }
  2117.         search = FALSE;
  2118.         left_edge = (PFD) left_circle;
  2119.         right_edge = (PFD) right_circle;
  2120.     }
  2121.                 
  2122.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[2]);
  2123.     project_info.r = 0.5 * project_info.xmax;
  2124.         
  2125.     return (search);
  2126. }
  2127.  
  2128. int vortho (lon0, lat0)
  2129. double lon0, lat0; {
  2130.     /* Set up Orthographic projection */
  2131.     
  2132.     project_info.central_meridian = lon0;
  2133.     project_info.pole = lat0;
  2134.     project_info.sinp = sin (lat0 * D2R);
  2135.     project_info.cosp = cos (lat0 * D2R);
  2136. }
  2137.  
  2138. int ortho (lon, lat, x, y)
  2139. double lon, lat, *x, *y; {
  2140.     /* Convert lon/lat to Orthographic x/y */
  2141.     double dlon;
  2142.     
  2143.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2144.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2145.     dlon = (lon - project_info.central_meridian) * D2R;
  2146.     lat *= D2R;
  2147.     
  2148.     *x = EQ_RAD * cos (lat) * sin (dlon);
  2149.     *y = EQ_RAD * (project_info.cosp * sin (lat) - project_info.sinp * cos (lat) * cos (dlon));
  2150. }
  2151.  
  2152. int iortho (lon, lat, x, y)
  2153. double *lon, *lat, x, y; {
  2154.     /* Convert Orthographic x/yto lon/lat */
  2155.     double rho, c;
  2156.     
  2157.     rho = hypot (x, y);
  2158.     c = d_asin (rho / EQ_RAD);
  2159.     
  2160.     if (rho == 0.0) {
  2161.         *lat = project_info.pole;
  2162.         *lon = project_info.central_meridian;
  2163.     }
  2164.     else {
  2165.         *lat = d_asin (cos (c) * project_info.sinp + (y * sin (c) * project_info.cosp / rho)) * R2D;
  2166.         if (project_info.pole == 90.0)
  2167.             *lon = project_info.central_meridian + R2D * d_atan2 (x, -y);
  2168.         else if (project_info.pole == -90.0)
  2169.             *lon = project_info.central_meridian + R2D * d_atan2 (x, y);
  2170.         else
  2171.             *lon = project_info.central_meridian +
  2172.                 R2D * d_atan2 (x * sin (c), (rho * project_info.cosp * cos (c) - y * project_info.sinp * sin (c)));
  2173.     }
  2174. }
  2175.  
  2176. /*
  2177.  *    TRANSFORMATION ROUTINES FOR THE AZIMUTHAL EQUIDISTANT PROJECTION
  2178.  */
  2179.  
  2180. int map_init_azeqdist () {
  2181.     BOOLEAN search;
  2182.     double xmin, xmax, ymin, ymax, dummy, radius;
  2183.  
  2184.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2185.  
  2186.     if (project_info.units_pr_degree) {
  2187.         vazeqdist (0.0, 90.0);
  2188.         azeqdist (0.0, project_info.pars[3], &dummy, &radius);
  2189.         if (radius == 0.0) radius = M_PI * EQ_RAD;
  2190.         project_info.x_scale = project_info.y_scale = fabs (project_info.pars[2] / radius);
  2191.     }
  2192.     else
  2193.         project_info.x_scale = project_info.y_scale = project_info.pars[2];
  2194.                 
  2195.     vazeqdist (project_info.pars[0], project_info.pars[1]);
  2196.     forward = (PFI)azeqdist;        inverse = (PFI)iazeqdist;
  2197.  
  2198.     if (fabs (project_info.pars[1]) == 90.0) {
  2199.         project_info.polar = TRUE;
  2200.         project_info.north_pole    = (project_info.pars[1] == 90.0);
  2201.     }
  2202.     
  2203.     if (!project_info.region) {    /* Rectangular box given */
  2204.         (*forward) (project_info.w, project_info.s, &xmin, &ymin);
  2205.         (*forward) (project_info.e, project_info.n, &xmax, &ymax);
  2206.                 
  2207.         outside = (PFI) rect_outside;
  2208.         crossing = (PFI) rect_crossing;
  2209.         overlap = (PFI) rect_overlap;
  2210.         map_clip = (PFI) rect_clip;
  2211.         left_edge = (PFD) left_rect;
  2212.         right_edge = (PFD) right_rect;
  2213.         frame_info.check_side = !gmtdefs.oblique_anotation;
  2214.         frame_info.horizontal = (fabs (project_info.pars[1]) < 60.0 && fabs (project_info.n - project_info.s) < 30.0);
  2215.         search = TRUE;
  2216.     }
  2217.     else {
  2218.         if (project_info.polar && (project_info.n - project_info.s) < 180.0) {    /* Polar aspect */
  2219.             if (!project_info.north_pole && project_info.s == -90.0) project_info.edge[0] = FALSE;
  2220.             if (project_info.north_pole && project_info.n == 90.0) project_info.edge[2] = FALSE;
  2221.             if ((fabs (project_info.w - project_info.e) == 360.0 || project_info.w == project_info.e)) project_info.edge[1] = project_info.edge[3] = FALSE;
  2222.             outside = (PFI) polar_outside;
  2223.             crossing = (PFI) wesn_crossing;
  2224.             overlap = (PFI) wesn_overlap;
  2225.             map_clip = (PFI) wesn_clip;
  2226.             frame_info.horizontal = TRUE;
  2227.             gmtdefs.n_lat_nodes = 2;
  2228.             xy_search (&xmin, &xmax, &ymin, &ymax);
  2229.         }
  2230.         else {    /* Global view only, force wesn = 0/360/-90/90  */
  2231.             frame_info.anot_int[0] = frame_info.anot_int[1] = 0.0;        /* No annotations for global mode */
  2232.             frame_info.frame_int[0] = frame_info.frame_int[1] = 0.0;    /* No tickmarks for global mode */
  2233.             project_info.w = 0.0;
  2234.             project_info.e = 360.0;
  2235.             project_info.s = -90.0;
  2236.             project_info.n = 90.0;
  2237.             xmin = ymin = -M_PI * EQ_RAD;
  2238.             xmax = ymax = -xmin;
  2239.             outside = (PFI) eqdist_outside;
  2240.             crossing = (PFI) eqdist_crossing;
  2241.             overlap = (PFI) radial_overlap;
  2242.             map_clip = (PFI) radial_clip;
  2243.             gmtdefs.basemap_type = 1;
  2244.         }
  2245.         search = FALSE;
  2246.         left_edge = (PFD) left_circle;
  2247.         right_edge = (PFD) right_circle;
  2248.     }
  2249.                 
  2250.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[2]);
  2251.     project_info.r = 0.5 * project_info.xmax;
  2252.         
  2253.     return (search);
  2254. }
  2255.  
  2256. int vazeqdist (lon0, lat0)
  2257. double lon0, lat0; {
  2258.     /* Set up azimuthal equidistant projection */
  2259.     
  2260.     project_info.central_meridian = lon0;
  2261.     project_info.pole = lat0;
  2262.     project_info.sinp = sin (lat0 * D2R);
  2263.     project_info.cosp = cos (lat0 * D2R);
  2264. }
  2265.  
  2266. int azeqdist (lon, lat, x, y)
  2267. double lon, lat, *x, *y; {
  2268.     /* Convert lon/lat to azimuthal equidistant x/y */
  2269.     double k, dlon, cc, c, clat, clon, slat;
  2270.     
  2271.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2272.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2273.     dlon = (lon - project_info.central_meridian) * D2R;
  2274.     lat *= D2R;
  2275.     slat = sin (lat);    clat = cos (lat);    clon = cos (dlon);
  2276.     
  2277.     cc = project_info.sinp * slat + project_info.cosp * clat * clon;
  2278.     if (fabs (cc) >= 1.0)
  2279.         *x = *y = 0.0;
  2280.     else {
  2281.         c = d_acos (cc);
  2282.         k = EQ_RAD * c / sin (c);
  2283.         *x = k * clat * sin (dlon);
  2284.         *y = k * (project_info.cosp * slat - project_info.sinp * clat * clon);
  2285.     }
  2286. }
  2287.  
  2288. int iazeqdist (lon, lat, x, y)
  2289. double *lon, *lat, x, y; {
  2290.     /* Convert azimuthal equidistant x/yto lon/lat */
  2291.     double rho, c, sin_c, cos_c;
  2292.     
  2293.     rho = hypot (x, y);
  2294.     
  2295.     if (rho == 0.0) {
  2296.         *lat = project_info.pole;
  2297.         *lon = project_info.central_meridian;
  2298.     }
  2299.     else {
  2300.         c = rho / EQ_RAD;
  2301.         sin_c = sin (c);
  2302.         cos_c = cos (c);
  2303.         *lat = d_asin (cos_c * project_info.sinp + (y * sin_c * project_info.cosp / rho)) * R2D;
  2304.         if (project_info.pole == 90.0)
  2305.             *lon = project_info.central_meridian + R2D * d_atan2 (x, -y);
  2306.         else if (project_info.pole == -90.0)
  2307.             *lon = project_info.central_meridian + R2D * d_atan2 (x, y);
  2308.         else
  2309.             *lon = project_info.central_meridian +
  2310.                 R2D * d_atan2 (x * sin_c, (rho * project_info.cosp * cos_c - y * project_info.sinp * sin_c));
  2311.         if ((*lon) <= -180) (*lon) += 360.0;
  2312.     }
  2313. }
  2314.  
  2315. /*
  2316.  *    TRANSFORMATION ROUTINES FOR THE MOLLWEIDE EQUAL AREA PROJECTION
  2317.  */
  2318.  
  2319. int map_init_mollweide () {
  2320.     int search;
  2321.     double xmin, xmax, ymin, ymax, y, dummy;
  2322.  
  2323.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2324.  
  2325.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2326.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2327.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2328.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2329.     project_info.x_scale = project_info.y_scale = M_PI * project_info.pars[1] / sqrt (8.0);
  2330.     vmollweide (project_info.pars[0], project_info.pars[1]);
  2331.     if (project_info.s == -90.0) project_info.edge[0] = FALSE;
  2332.     if (project_info.n == 90.0) project_info.edge[2] = FALSE;
  2333.     
  2334.     if (project_info.region) {
  2335.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2336.         mollweide (project_info.w, y, &xmin, &dummy);
  2337.         mollweide (project_info.e, y, &xmax, &dummy);
  2338.         mollweide (project_info.central_meridian, project_info.s, &dummy, &ymin);
  2339.         mollweide (project_info.central_meridian, project_info.n, &dummy, &ymax);
  2340.         outside = (PFI) wesn_outside;
  2341.         crossing = (PFI) wesn_crossing;
  2342.         overlap = (PFI) wesn_overlap;
  2343.         map_clip = (PFI) wesn_clip;
  2344.         left_edge = (PFD) left_ellipse;
  2345.         right_edge = (PFD) right_ellipse;
  2346.         frame_info.horizontal = 2;
  2347.         project_info.polar = TRUE;
  2348.         search = FALSE;
  2349.     }
  2350.     else {
  2351.         mollweide (project_info.w, project_info.s, &xmin, &ymin);
  2352.         mollweide (project_info.e, project_info.n, &xmax, &ymax);
  2353.         outside = (PFI) rect_outside;
  2354.         crossing = (PFI) rect_crossing;
  2355.         overlap = (PFI) rect_overlap;
  2356.         map_clip = (PFI) rect_clip;
  2357.         left_edge = (PFD) left_rect;
  2358.         right_edge = (PFD) right_rect;
  2359.         frame_info.check_side = TRUE;
  2360.         search = TRUE;
  2361.     }
  2362.     map_setxy (xmin, xmax, ymin, ymax);
  2363.     forward = (PFI)mollweide;        inverse = (PFI)imollweide;
  2364.     gmtdefs.basemap_type = 1;
  2365.     return (search);
  2366. }
  2367.  
  2368. int vmollweide (lon0, scale)
  2369. double lon0, scale; {
  2370.     /* Set up Mollweide Equal-Area projection */
  2371.     
  2372.     gmt_check_R_J (&lon0);
  2373.     project_info.central_meridian = lon0;
  2374.     project_info.w_x = EQ_RAD * d_sqrt (8.0) / M_PI;
  2375.     project_info.w_y = EQ_RAD * M_SQRT2;
  2376.     project_info.w_r = 0.25 * (scale * M_PR_DEG * 360.0);    /* = Half the minor axis */
  2377. }
  2378.  
  2379. int mollweide (lon, lat, x, y)
  2380. double lon, lat, *x, *y; {
  2381.     /* Convert lon/lat to Mollweide Equal-Area x/y */
  2382.     int i = 0;
  2383.     double phi, delta;
  2384.     
  2385.     if (fabs(lat) == 90.0) {    /* Special case */
  2386.         *x = 0.0;
  2387.         *y = copysign (project_info.w_y, lat);
  2388.         return;
  2389.     }
  2390.     
  2391.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2392.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2393.     lat *= D2R;
  2394.     
  2395.     phi = lat;
  2396.     do {
  2397.         i++;
  2398.         delta = -(phi + sin (phi) - M_PI * sin (lat)) / (1.0 + cos (phi));
  2399.         phi += delta;
  2400.     }
  2401.     while (fabs (delta) > 1.0e-7 && i < 100);
  2402.     phi *= 0.5;
  2403.     *x = project_info.w_x * (lon - project_info.central_meridian) * D2R * cos (phi);
  2404.     *y = project_info.w_y * sin (phi);
  2405. }
  2406.  
  2407. int imollweide (lon, lat, x, y)
  2408. double *lon, *lat, x, y; {
  2409.     /* Convert Mollweide Equal-Area x/y to lon/lat */
  2410.     double phi, phi2;
  2411.     
  2412.     phi = d_asin (y / project_info.w_y);
  2413.     phi2 = 2.0 * phi;
  2414.     *lat = R2D * d_asin ((phi2 + sin (phi2)) / M_PI);
  2415.     *lon = project_info.central_meridian + R2D * (x / (project_info.w_x * cos (phi)));
  2416. }
  2417.  
  2418. /*
  2419.  *    TRANSFORMATION ROUTINES FOR THE HAMMER-AITOFF EQUAL AREA PROJECTION
  2420.  */
  2421.  
  2422. int map_init_hammer () {
  2423.     int search;
  2424.     double xmin, xmax, ymin, ymax, x, y, dummy;
  2425.  
  2426.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2427.  
  2428.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2429.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2430.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2431.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2432.     project_info.x_scale = project_info.y_scale = 0.5 * M_PI * project_info.pars[1] / M_SQRT2;
  2433.     vhammer (project_info.pars[0], project_info.pars[1]);
  2434.     if (project_info.s == -90.0) project_info.edge[0] = FALSE;
  2435.     if (project_info.n == 90.0) project_info.edge[2] = FALSE;
  2436.     
  2437.     if (project_info.region) {
  2438.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2439.         x = (fabs (project_info.w - project_info.central_meridian) > fabs (project_info.e - project_info.central_meridian)) ? project_info.w : project_info.e;
  2440.         hammer (project_info.w, y, &xmin, &dummy);
  2441.         hammer (project_info.e, y, &xmax, &dummy);
  2442.         hammer (x, project_info.s, &dummy, &ymin);
  2443.         hammer (x, project_info.n, &dummy, &ymax);
  2444.         outside = (PFI) wesn_outside;
  2445.         crossing = (PFI) wesn_crossing;
  2446.         overlap = (PFI) wesn_overlap;
  2447.         map_clip = (PFI) wesn_clip;
  2448.         left_edge = (PFD) left_ellipse;
  2449.         right_edge = (PFD) right_ellipse;
  2450.         frame_info.horizontal = 2;
  2451.         project_info.polar = TRUE;
  2452.         search = FALSE;
  2453.     }
  2454.     else {
  2455.         hammer (project_info.w, project_info.s, &xmin, &ymin);
  2456.         hammer (project_info.e, project_info.n, &xmax, &ymax);
  2457.         outside = (PFI) rect_outside;
  2458.         crossing = (PFI) rect_crossing;
  2459.         overlap = (PFI) rect_overlap;
  2460.         map_clip = (PFI) rect_clip;
  2461.         left_edge = (PFD) left_rect;
  2462.         right_edge = (PFD) right_rect;
  2463.         frame_info.check_side = TRUE;
  2464.         search = TRUE;
  2465.     }
  2466.     map_setxy (xmin, xmax, ymin, ymax);
  2467.     forward = (PFI)hammer;        inverse = (PFI)ihammer;
  2468.     gmtdefs.basemap_type = 1;
  2469.     return (search);
  2470. }
  2471.  
  2472. int vhammer (lon0, scale)
  2473. double lon0, scale; {
  2474.     /* Set up Hammer-Aitoff Equal-Area projection */
  2475.     
  2476.     gmt_check_R_J (&lon0);
  2477.     project_info.central_meridian = lon0;
  2478.     project_info.w_r = 0.25 * (scale * M_PR_DEG * 360.0);    /* = Half the minor axis */
  2479. }
  2480.  
  2481. int hammer (lon, lat, x, y)
  2482. double lon, lat, *x, *y; {
  2483.     /* Convert lon/lat to Hammer-Aitoff Equal-Area x/y */
  2484.     double clat, D;
  2485.     
  2486.     if (fabs(lat) == 90.0) {    /* Save time */
  2487.         *x = 0.0;
  2488.         *y = M_SQRT2 * copysign (EQ_RAD, lat);
  2489.         return;
  2490.     }
  2491.     
  2492.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2493.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2494.     lon -= project_info.central_meridian;
  2495.     lat *= D2R;
  2496.     clat = cos (lat);
  2497.     lon *= (0.5 * D2R);
  2498.     
  2499.     D = EQ_RAD * sqrt (2.0 / (1.0 + clat * cos (lon)));
  2500.     *x = 2.0 * D * clat * sin (lon);
  2501.     *y = D * sin (lat);
  2502. }
  2503.  
  2504. int ihammer (lon, lat, x, y)
  2505. double *lon, *lat, x, y; {
  2506.     /* Convert Hammer_Aitoff Equal-Area x/y to lon/lat */
  2507.     double rho, c, angle;
  2508.     
  2509.     x *= 0.5;
  2510.     rho = hypot (x, y);
  2511.     
  2512.     if (rho == 0.0) {
  2513.         *lat = 0.0;
  2514.         *lon = project_info.central_meridian;
  2515.     }
  2516.     else {
  2517.         c = 2.0 * d_asin (0.5 * rho / EQ_RAD);
  2518.         *lat = d_asin (y * sin (c) / rho) * R2D;
  2519.         if (fabs (c - M_PI_2) < SMALL)
  2520.             angle = (x == 0.0) ? 0.0 : copysign (180.0, x);
  2521.         else
  2522.             angle = 2.0 * R2D * atan (x * tan (c) / rho);
  2523.         *lon = project_info.central_meridian + angle;
  2524.     }
  2525. }
  2526.  
  2527. /*
  2528.  *    TRANSFORMATION ROUTINES FOR THE WINKEL-TRIPEL MODIFIED AZIMUTHAL PROJECTION
  2529.  */
  2530.  
  2531. int map_init_winkel () {
  2532.     int search;
  2533.     double xmin, xmax, ymin, ymax, x, y, dummy;
  2534.  
  2535.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2536.  
  2537.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2538.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2539.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2540.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2541.     vwinkel (project_info.pars[0], project_info.pars[1]);
  2542.     project_info.x_scale = project_info.y_scale = 2.0 * project_info.pars[1] / (1.0 + project_info.r_cosphi1);
  2543.     
  2544.     if (project_info.region) {
  2545.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2546.         x = (fabs (project_info.w - project_info.central_meridian) > fabs (project_info.e - project_info.central_meridian)) ? project_info.w : project_info.e;
  2547.         winkel (project_info.w, y, &xmin, &dummy);
  2548.         winkel (project_info.e, y, &xmax, &dummy);
  2549.         winkel (x, project_info.s, &dummy, &ymin);
  2550.         winkel (x, project_info.n, &dummy, &ymax);
  2551.         outside = (PFI) wesn_outside;
  2552.         crossing = (PFI) wesn_crossing;
  2553.         overlap = (PFI) wesn_overlap;
  2554.         map_clip = (PFI) wesn_clip;
  2555.         left_edge = (PFD) left_winkel;
  2556.         right_edge = (PFD) right_winkel;
  2557.         frame_info.horizontal = 2;
  2558.         search = FALSE;
  2559.     }
  2560.     else {
  2561.         winkel (project_info.w, project_info.s, &xmin, &ymin);
  2562.         winkel (project_info.e, project_info.n, &xmax, &ymax);
  2563.         outside = (PFI) rect_outside;
  2564.         crossing = (PFI) rect_crossing;
  2565.         overlap = (PFI) rect_overlap;
  2566.         map_clip = (PFI) rect_clip;
  2567.         left_edge = (PFD) left_rect;
  2568.         right_edge = (PFD) right_rect;
  2569.         frame_info.check_side = TRUE;
  2570.         search = TRUE;
  2571.     }
  2572.     map_setxy (xmin, xmax, ymin, ymax);
  2573.     forward = (PFI)winkel;        inverse = (PFI)iwinkel;
  2574.     gmtdefs.basemap_type = 1;
  2575.     return (search);
  2576. }
  2577.  
  2578. int vwinkel (lon0, scale)
  2579. double lon0, scale; {
  2580.     /* Set up Winkel Tripel projection */
  2581.     
  2582.     gmt_check_R_J (&lon0);
  2583.     project_info.r_cosphi1 = cos (50.467 * D2R);
  2584.     project_info.central_meridian = lon0;
  2585.     project_info.w_r = 0.25 * (scale * M_PR_DEG * 360.0);    /* = Half the minor axis */
  2586. }
  2587.  
  2588. int winkel (lon, lat, x, y)
  2589. double lon, lat, *x, *y; {
  2590.     /* Convert lon/lat to Winkel Tripel x/y */
  2591.     double C, D, x1, x2, y1, y2;
  2592.     
  2593.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2594.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2595.     lon -= project_info.central_meridian;
  2596.     lat *= D2R;
  2597.     lon *= (0.5 * D2R);
  2598.     
  2599.     /* Fist find Aitoff x/y */
  2600.     
  2601.     D = d_acos (cos (lat) * cos (lon));
  2602.     if (D == 0.0)
  2603.         x1 = y1 = 0.0;
  2604.     else {
  2605.         C = sin (lat) / sin (D);
  2606.         D *= EQ_RAD;
  2607.         x1 = copysign (2.0 * D * d_sqrt (1.0 - C * C), lon);
  2608.         y1 = D * C;
  2609.     }
  2610.     
  2611.     /* Then get equirectangular projection */
  2612.     
  2613.     x2 = 2.0 * EQ_RAD * lon * project_info.r_cosphi1;
  2614.     y2 = EQ_RAD * lat;
  2615.     
  2616.     /* Winkler is the average value */
  2617.     
  2618.     *x = 0.5 * (x1 + x2);
  2619.     *y = 0.5 * (y1 + y2);
  2620. }
  2621.  
  2622. int iwinkel (lon, lat, x, y)
  2623. double *lon, *lat, x, y; {
  2624.     /* Convert Winkel Tripel x/y to lon/lat */
  2625.     /* Only works if point is on perimeter */
  2626.     
  2627.     int n_iter = 0;
  2628.     double c, phi, phi0, delta;
  2629.     
  2630.     c = 2.0 * y / EQ_RAD;
  2631.     phi = y / EQ_RAD;
  2632.     do {
  2633.         phi0 = phi;
  2634.         phi = phi0 - (phi0 + M_PI_2 * sin (phi0) - c) / (1.0 + M_PI_2 * cos (phi0));
  2635.         delta = fabs (phi - phi0);
  2636.         n_iter++;
  2637.     }
  2638.     while (delta > SMALL && n_iter < 100);
  2639.     *lat = phi * R2D;
  2640.     *lon = project_info.central_meridian + copysign (180.0, x - gmt_half_map_size);
  2641. }
  2642.  
  2643. /*
  2644.  *    TRANSFORMATION ROUTINES FOR THE ECKERT VI PROJECTION
  2645.  */
  2646.  
  2647. int map_init_eckert () {
  2648.     int search;
  2649.     double xmin, xmax, ymin, ymax, y, dummy;
  2650.  
  2651.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2652.  
  2653.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2654.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2655.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2656.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2657.     veckert (project_info.pars[0]);
  2658.     project_info.x_scale = project_info.y_scale = 0.5 * project_info.pars[1] * sqrt (2.0 + M_PI);
  2659.     
  2660.     if (project_info.region) {
  2661.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2662.         eckert (project_info.w, y, &xmin, &dummy);
  2663.         eckert (project_info.e, y, &xmax, &dummy);
  2664.         eckert (project_info.central_meridian, project_info.s, &dummy, &ymin);
  2665.         eckert (project_info.central_meridian, project_info.n, &dummy, &ymax);
  2666.         outside = (PFI) wesn_outside;
  2667.         crossing = (PFI) wesn_crossing;
  2668.         overlap = (PFI) wesn_overlap;
  2669.         map_clip = (PFI) wesn_clip;
  2670.         left_edge = (PFD) left_eckert;
  2671.         right_edge = (PFD) right_eckert;
  2672.         frame_info.horizontal = 2;
  2673.         search = FALSE;
  2674.     }
  2675.     else {
  2676.         eckert (project_info.w, project_info.s, &xmin, &ymin);
  2677.         eckert (project_info.e, project_info.n, &xmax, &ymax);
  2678.         outside = (PFI) rect_outside;
  2679.         crossing = (PFI) rect_crossing;
  2680.         overlap = (PFI) rect_overlap;
  2681.         map_clip = (PFI) rect_clip;
  2682.         left_edge = (PFD) left_rect;
  2683.         right_edge = (PFD) right_rect;
  2684.         frame_info.check_side = TRUE;
  2685.         search = TRUE;
  2686.     }
  2687.     map_setxy (xmin, xmax, ymin, ymax);
  2688.     forward = (PFI)eckert;        inverse = (PFI)ieckert;
  2689.     gmtdefs.basemap_type = 1;
  2690.     return (search);
  2691. }
  2692.  
  2693. int veckert (lon0)
  2694. double lon0; {
  2695.     /* Set up Eckert VI projection */
  2696.     
  2697.     gmt_check_R_J (&lon0);
  2698.     project_info.k_r = EQ_RAD / sqrt (2.0 + M_PI);
  2699.     project_info.k_ir = 1.0 / project_info.k_r;
  2700.     project_info.central_meridian = lon0;
  2701. }
  2702.  
  2703. int eckert (lon, lat, x, y)
  2704. double lon, lat, *x, *y; {
  2705.     int n_iter = 0;
  2706.     double phi, delta, s_lat;
  2707.     /* Convert lon/lat to Eckert VI x/y */
  2708.     
  2709.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2710.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2711.     lon -= project_info.central_meridian;
  2712.     lat *= D2R;
  2713.     lon *= D2R;
  2714.     phi = lat;
  2715.     s_lat = sin (lat);
  2716.     do {
  2717.         delta = -(phi + sin (phi) - (1.0 + M_PI_2) * s_lat) / (1.0 + cos (phi));
  2718.         phi += delta;
  2719.     }
  2720.     while (delta > SMALL && n_iter < 100);
  2721.     
  2722.     *x = project_info.k_r * lon * (1.0 + cos (phi));
  2723.     *y = 2.0 * project_info.k_r * phi;
  2724. }
  2725.  
  2726. int ieckert (lon, lat, x, y)
  2727. double *lon, *lat, x, y; {
  2728.     /* Convert Eckert VI x/y to lon/lat */
  2729.     
  2730.     double phi;
  2731.     
  2732.     phi = 0.5 * y * project_info.k_ir;
  2733.     *lat = d_asin ((phi + sin (phi)) / (1.0 + M_PI_2)) * R2D;
  2734.     *lon = project_info.central_meridian + R2D * x * project_info.k_ir / (1.0 + cos (phi));
  2735. }
  2736. /*
  2737.  *    TRANSFORMATION ROUTINES FOR THE ROBINSON PSEUDOCYLIDRICAL PROJECTION
  2738.  */
  2739.  
  2740. int map_init_robinson () {
  2741.     int search;
  2742.     double xmin, xmax, ymin, ymax, y, dummy;
  2743.  
  2744.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2745.  
  2746.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2747.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2748.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2749.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2750.     vrobinson (project_info.pars[0]);
  2751.     project_info.x_scale = project_info.y_scale = project_info.pars[1] / 0.8487;
  2752.     
  2753.     if (project_info.region) {
  2754.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2755.         robinson (project_info.w, y, &xmin, &dummy);
  2756.         robinson (project_info.e, y, &xmax, &dummy);
  2757.         robinson (project_info.central_meridian, project_info.s, &dummy, &ymin);
  2758.         robinson (project_info.central_meridian, project_info.n, &dummy, &ymax);
  2759.         outside = (PFI) wesn_outside;
  2760.         crossing = (PFI) wesn_crossing;
  2761.         overlap = (PFI) wesn_overlap;
  2762.         map_clip = (PFI) wesn_clip;
  2763.         left_edge = (PFD) left_robinson;
  2764.         right_edge = (PFD) right_robinson;
  2765.         frame_info.horizontal = 2;
  2766.         search = FALSE;
  2767.     }
  2768.     else {
  2769.         robinson (project_info.w, project_info.s, &xmin, &ymin);
  2770.         robinson (project_info.e, project_info.n, &xmax, &ymax);
  2771.         outside = (PFI) rect_outside;
  2772.         crossing = (PFI) rect_crossing;
  2773.         overlap = (PFI) rect_overlap;
  2774.         map_clip = (PFI) rect_clip;
  2775.         left_edge = (PFD) left_rect;
  2776.         right_edge = (PFD) right_rect;
  2777.         frame_info.check_side = TRUE;
  2778.         search = TRUE;
  2779.     }
  2780.     map_setxy (xmin, xmax, ymin, ymax);
  2781.     forward = (PFI)robinson;        inverse = (PFI)irobinson;
  2782.     gmtdefs.basemap_type = 1;
  2783.     return (search);
  2784. }
  2785.  
  2786. int vrobinson (lon0)
  2787. double lon0; {
  2788.     /* Set up Robinson projection */
  2789.     int i;
  2790.     FILE *fp;
  2791.     char file[512];
  2792.     char *gmt_data_path;
  2793.     
  2794.     gmt_check_R_J (&lon0);
  2795.     project_info.n_cx = 0.8487 * EQ_RAD * D2R;
  2796.     project_info.n_cy = 1.3523 * EQ_RAD;
  2797.     project_info.central_meridian = lon0;
  2798.     
  2799. /*      Modifications made here to permit the use of GMTDATAPATH   */
  2800. /*      an environmental variable, rather than LIBDIR [hardwired]  */
  2801. /*                    Allen Cogbill, 11/96                         */
  2802.  
  2803.     gmt_data_path = getenv (GMTDATAPATH);
  2804.  
  2805. /*     =========    original code is below:    ============        */
  2806. /*                                                                 */
  2807. /*    sprintf (file, "%s/robinson.table\0", LIBDIR);             */
  2808. /*                                                                 */
  2809. /*                                                                 */
  2810.     sprintf (file, "%s/robinson.table\0", gmt_data_path);
  2811.     
  2812.     if ((fp = fopen (file, "r")) == NULL) {
  2813.         fprintf (stderr, "%s: GMT SYNTAX ERROR -Jn -JN OPTION: Could not open interpolation table %s\n", gmt_program, file);
  2814.         exit (-1);
  2815.     }
  2816.     for (i = 0; i < 19; i++) fscanf (fp, "%lf %lf %lf\n", &project_info.n_phi[i], &project_info.n_X[i], &project_info.n_Y[i]);
  2817.     fclose (fp);
  2818. }
  2819.  
  2820. int robinson (lon, lat, x, y)
  2821. double lon, lat, *x, *y; {
  2822.     /* Convert lon/lat to Robinson x/y */
  2823.     double tmp, X, Y;
  2824.     
  2825.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  2826.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  2827.     lon -= project_info.central_meridian;
  2828.     tmp = fabs (lat);
  2829.     
  2830.     intpol (project_info.n_phi, project_info.n_X, 19, 1, &tmp, &X, gmtdefs.interpolant);
  2831.     intpol (project_info.n_phi, project_info.n_Y, 19, 1, &tmp, &Y, gmtdefs.interpolant);
  2832.     *x = project_info.n_cx * X * lon;    /* D2R is in n_cx already */
  2833.     *y = project_info.n_cy * copysign (Y, lat);
  2834. }
  2835.  
  2836. int irobinson (lon, lat, x, y)
  2837. double *lon, *lat, x, y; {
  2838.     /* Convert Robinson x/y to lon/lat */
  2839.     double X, Y;
  2840.     
  2841.     Y = fabs (y / project_info.n_cy);
  2842.     intpol (project_info.n_Y, project_info.n_phi, 19, 1, &Y, lat, gmtdefs.interpolant);
  2843.     intpol (project_info.n_phi, project_info.n_X, 19, 1, lat, &X, gmtdefs.interpolant);
  2844.     
  2845.     *lat = copysign (*lat, y);
  2846.     *lon = x / (project_info.n_cx * X) + project_info.central_meridian;
  2847. }
  2848.  
  2849. /*
  2850.  *    TRANSFORMATION ROUTINES FOR THE SINUSOIDAL EQUAL AREA PROJECTION
  2851.  */
  2852.  
  2853. int map_init_sinusoidal () {
  2854.     int search;
  2855.     double xmin, xmax, ymin, ymax, dummy, y;
  2856.  
  2857.     gmt_set_spherical ();    /* PW: Force spherical for now */
  2858.  
  2859.     if (project_info.pars[0] < 0.0) project_info.pars[0] += 360.0;
  2860.     gmt_world_map = (fabs (project_info.w - project_info.e) == 360.0);
  2861.     if (project_info.gave_map_width) project_info.pars[1] /= (M_PR_DEG * fabs (project_info.w - project_info.e));
  2862.     if (project_info.s == -90.0) project_info.edge[0] = FALSE;
  2863.     if (project_info.n == 90.0) project_info.edge[2] = FALSE;
  2864.     vsinusoidal (project_info.pars[0]);
  2865.     if (project_info.units_pr_degree) project_info.pars[1] /= M_PR_DEG;
  2866.     project_info.x_scale = project_info.y_scale = project_info.pars[1];
  2867.     forward = (PFI)sinusoidal;        inverse = (PFI)isinusoidal;
  2868.     gmtdefs.basemap_type = 1;
  2869.     
  2870.     if (project_info.region) {
  2871.         y = (project_info.s * project_info.n <= 0.0) ? 0.0 : MIN (fabs(project_info.s), fabs(project_info.n));
  2872.         sinusoidal (project_info.central_meridian, project_info.s, &dummy, &ymin);
  2873.         sinusoidal (project_info.central_meridian, project_info.n, &dummy, &ymax);
  2874.         sinusoidal (project_info.w, y, &xmin, &dummy);
  2875.         sinusoidal (project_info.e, y, &xmax, &dummy);
  2876.         outside = (PFI) wesn_outside;
  2877.         crossing = (PFI) wesn_crossing;
  2878.         overlap = (PFI) wesn_overlap;
  2879.         map_clip = (PFI) wesn_clip;
  2880.         left_edge = (PFD) left_sinusoidal;
  2881.         right_edge = (PFD) right_sinusoidal;
  2882.         frame_info.horizontal = 2;
  2883.         project_info.polar = TRUE;
  2884.         search = FALSE;
  2885.     }
  2886.     else {
  2887.         sinusoidal (project_info.w, project_info.s, &xmin, &ymin);
  2888.         sinusoidal (project_info.e, project_info.n, &xmax, &ymax);
  2889.         outside = (PFI) rect_outside;
  2890.         crossing = (PFI) rect_crossing;
  2891.         overlap = (PFI) rect_overlap;
  2892.         map_clip = (PFI) rect_clip;
  2893.         left_edge = (PFD) left_rect;
  2894.         right_edge = (PFD) right_rect;
  2895.         frame_info.check_side = TRUE;
  2896.         search = TRUE;
  2897.     }
  2898.  
  2899.     map_setxy (xmin, xmax, ymin, ymax);
  2900.  
  2901.     return (search);
  2902. }
  2903.  
  2904. int vsinusoidal (lon0)
  2905. double lon0; {
  2906.     /* Set up Sinusiodal projection */
  2907.     
  2908.     gmt_check_R_J (&lon0);
  2909.     project_info.central_meridian = lon0;
  2910. }
  2911.  
  2912. int sinusoidal (lon, lat, x, y)
  2913. double lon, lat, *x, *y; {
  2914.     /* Convert lon/lat to Sinusoidal Equal-Area x/y */
  2915.     
  2916.     lon -= project_info.central_meridian;
  2917.     while (lon < -180.0) lon += 360.0;
  2918.     while (lon > 180.0) lon -= 360.0;
  2919.     
  2920.     lon *= D2R;
  2921.     lat *= D2R;
  2922.     
  2923.     *x = EQ_RAD * lon * cos (lat);
  2924.     *y = EQ_RAD * lat;
  2925. }
  2926.  
  2927. int isinusoidal (lon, lat, x, y)
  2928. double *lon, *lat, x, y; {
  2929.     /* Convert Sinusoidal Equal-Area x/y to lon/lat (not implemented) */
  2930.     *lat = y / EQ_RAD;
  2931.     *lon = ((fabs (fabs (*lat) - M_PI) < SMALL) ? 0.0 : R2D * x / (EQ_RAD * cos (*lat))) + project_info.central_meridian;
  2932.     *lat *= R2D;
  2933. }
  2934.  
  2935. /*
  2936.  *    TRANSFORMATION ROUTINES FOR THE CASSINI PROJECTION
  2937.  */
  2938.  
  2939. int map_init_cassini () {
  2940.     BOOLEAN search;
  2941.     double xmin, xmax, ymin, ymax;
  2942.  
  2943.     vcassini (project_info.pars[0], project_info.pars[1]);
  2944.             
  2945.     forward = (PFI)cassini;        inverse = (PFI)icassini;
  2946.     if (project_info.units_pr_degree) project_info.pars[2] /= M_PR_DEG;
  2947.     project_info.x_scale = project_info.y_scale = project_info.pars[2];
  2948.     gmtdefs.basemap_type = 1;
  2949.  
  2950.     if (project_info.region) {
  2951.         xy_search (&xmin, &xmax, &ymin, &ymax);
  2952.         outside = (PFI) wesn_outside;
  2953.         crossing = (PFI) wesn_crossing;
  2954.         overlap = (PFI) wesn_overlap;
  2955.         map_clip = (PFI) wesn_clip;
  2956.         left_edge = (PFD) left_albers;
  2957.         right_edge = (PFD) right_albers;
  2958.         search = FALSE;
  2959.     }
  2960.     else {
  2961.         cassini (project_info.w, project_info.s, &xmin, &ymin);
  2962.         cassini (project_info.e, project_info.n, &xmax, &ymax);
  2963.         outside = (PFI) rect_outside;
  2964.         crossing = (PFI) rect_crossing;
  2965.         overlap = (PFI) rect_overlap;
  2966.         map_clip = (PFI) rect_clip;
  2967.         left_edge = (PFD) left_rect;
  2968.         right_edge = (PFD) right_rect;
  2969.         frame_info.check_side = TRUE;
  2970.         search = TRUE;
  2971.     }
  2972.                 
  2973.     frame_info.horizontal = TRUE;
  2974.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[2]);
  2975.  
  2976.     return (search);
  2977. }
  2978.  
  2979. int vcassini (lon0, lat0)
  2980. double lon0, lat0; {
  2981.     /* Set up Cassini projection */
  2982.     
  2983.     project_info.central_meridian = lon0;
  2984.     project_info.pole = lat0;
  2985.     lat0 *= D2R;
  2986.     
  2987.     project_info.c_M0 = EQ_RAD  * ((1.0 - 0.25 * ECC2 - 0.046875 * ECC4 - 0.01953125 * ECC6) * lat0
  2988.         - (0.375 * ECC2 + 0.09375 * ECC4 + 0.0439453125 * ECC6) * sin (2.0 * lat0)
  2989.         + (0.05859375 * ECC4 + 0.0439453125 * ECC6) * sin (4.0 * lat0)
  2990.         - 0.0113932292 * ECC6 * sin (6.0 * lat0));
  2991. }
  2992.  
  2993. int cassini (lon, lat, x, y)
  2994. double lon, lat, *x, *y; {
  2995.     /* Convert lon/lat to Cassini x/y */
  2996.     
  2997.     double tany, cosy, N, T, A, C, M;
  2998.     
  2999.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  3000.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  3001.     lon -= project_info.central_meridian;
  3002.     lon *= D2R;
  3003.     lat *= D2R;
  3004.     
  3005.     tany = tan (lat);
  3006.     cosy = cos (lat);
  3007.     N = EQ_RAD / sqrt (1.0 - ECC2 * pow (sin (lat), 2.0));
  3008.     T = tany * tany;
  3009.     A = lon * cosy;
  3010.     C = ECC2 * cosy * cosy / (1.0 - ECC2);
  3011.     M = EQ_RAD  * ((1.0 - 0.25 * ECC2 - 0.046875 * ECC4 - 0.01953125 * ECC6) * lat
  3012.         - (0.375 * ECC2 + 0.09375 * ECC4 + 0.0439453125 * ECC6) * sin (2.0 * lat)
  3013.         + (0.05859375 * ECC4 + 0.0439453125 * ECC6) * sin (4.0 * lat)
  3014.         - 0.0113932292 * ECC6 * sin (6.0 * lat));
  3015.     *x = N * (A - T * pow (A, 3.0) / 6.0 - (8.0 - T + 8 * C) * T * pow (A, 5.0) / 120.0);
  3016.     *y = M - project_info.c_M0 + N * tany * (0.5 * A * A + (5.0 - T + 6.0 * C) * pow (A, 4.0) / 24.0);
  3017. }
  3018.  
  3019. int icassini (lon, lat, x, y)
  3020. double *lon, *lat, x, y; {
  3021.     /* Convert Cassini x/y to lon/lat */
  3022.     
  3023.     double e1, M1, u1, phi1, tany, siny, T1, N1, R1, D;
  3024.     
  3025.     e1 = (1.0 - sqrt (1.0 - ECC2)) / (1.0 + sqrt (1.0 - ECC2));
  3026.     M1 = project_info.c_M0 + y;
  3027.     u1 = M1 / (EQ_RAD * (1.0 - 0.25 * ECC2 - 0.046875 * ECC4 - 0.01953125 * ECC6));
  3028.     phi1 = u1 + (1.5 * e1 - 0.84375 * pow (e1, 3.0)) * sin (2.0 * u1)
  3029.         + (1.3125 * e1 * e1 - 1.71875 * pow (e1, 4.0)) * sin (4.0 * u1)
  3030.         + 1.572916666666 * pow (e1, 3.0) * sin (6.0 * u1)
  3031.         + 2.142578125 * pow (e1, 4.0) * sin (8.0 * u1);
  3032.     if (fabs (fabs (phi1) - M_PI_2) < SMALL) {
  3033.         *lat = copysign (M_PI_2, phi1);
  3034.         *lon = project_info.central_meridian;
  3035.     }
  3036.     else {
  3037.         tany = tan (phi1);
  3038.         siny = sin (phi1);
  3039.         T1 = tany * tany;
  3040.         N1 = EQ_RAD / sqrt (1.0 - ECC2 * siny * siny);
  3041.         R1 = EQ_RAD * (1.0 - ECC2) / pow (1.0 - ECC2 * siny * siny, 1.5);
  3042.         D = x / N1;
  3043.     
  3044.         *lat = R2D * (phi1 - (N1 * tany / R1) * (0.5 * D * D - (1.0 + 3.0 * T1) * pow (D, 4.0) / 24.0));
  3045.         *lon = project_info.central_meridian + R2D * (D - T1 * pow (D, 3.0) / 3.0 + (1.0 + 3.0 * T1) * T1 * pow (D, 5.0)/ 15.0) / cos (phi1);
  3046.     }
  3047. }
  3048.  
  3049. /*
  3050.  *    TRANSFORMATION ROUTINES FOR THE ALBERS PROJECTION
  3051.  */
  3052.  
  3053. int map_init_albers () {
  3054.     BOOLEAN search;
  3055.     double xmin, xmax, ymin, ymax;
  3056.  
  3057.     valbers (project_info.pars[0], project_info.pars[1], project_info.pars[2], project_info.pars[3]);
  3058.     if (project_info.units_pr_degree) project_info.pars[4] /= M_PR_DEG;
  3059.     forward = (PFI)albers;        inverse = (PFI)ialbers;
  3060.     project_info.x_scale = project_info.y_scale = project_info.pars[4];
  3061.             
  3062.     if (project_info.region) {
  3063.         xy_search (&xmin, &xmax, &ymin, &ymax);
  3064.         outside = (PFI) wesn_outside;
  3065.         crossing = (PFI) wesn_crossing;
  3066.         overlap = (PFI) wesn_overlap;
  3067.         map_clip = (PFI) wesn_clip;
  3068.         left_edge = (PFD) left_albers;
  3069.         right_edge = (PFD) right_albers;
  3070.         search = FALSE;
  3071.     }
  3072.     else {
  3073.         albers (project_info.w, project_info.s, &xmin, &ymin);
  3074.         albers (project_info.e, project_info.n, &xmax, &ymax);
  3075.         outside = (PFI) rect_outside;
  3076.         crossing = (PFI) rect_crossing;
  3077.         overlap = (PFI) rect_overlap;
  3078.         map_clip = (PFI) rect_clip;
  3079.         left_edge = (PFD) left_rect;
  3080.         right_edge = (PFD) right_rect;
  3081.         frame_info.check_side = TRUE;
  3082.         search = TRUE;
  3083.     }
  3084.     frame_info.horizontal = TRUE;
  3085.     gmtdefs.n_lat_nodes = 2;
  3086.     map_setinfo (xmin, xmax, ymin, ymax, project_info.pars[4]);
  3087.  
  3088.     return (search);
  3089. }
  3090.  
  3091.  
  3092. int valbers (lon0, lat0, ph1, ph2)
  3093. double lon0, lat0, ph1, ph2; {
  3094.     /* Set up Albers projection */
  3095.     
  3096.     double s0, s1, s2, q0, q1, q2, m1, m2;
  3097.     
  3098.     project_info.central_meridian = lon0;
  3099.     project_info.north_pole = (lat0 > 0.0);
  3100.     project_info.pole = (project_info.north_pole) ? 90.0 : -90.0;
  3101.     lat0 *= D2R;
  3102.     ph1 *= D2R;    ph2 *= D2R;
  3103.     
  3104.     s0 = sin (lat0);    s1 = sin (ph1);        s2 = sin (ph2);
  3105.     m1 = cos (ph1) * cos (ph1) / (1.0 - ECC2 * s1 * s1);    /* Actually m1 and m2 squared */
  3106.     m2 = cos (ph2) * cos (ph2) / (1.0 - ECC2 * s2 * s2);
  3107.     q0 = (1.0 - ECC2) * (s0 / (1.0 - ECC2 * s0 * s0) - (0.5 / ECC) * log ((1.0 - ECC * s0) / (1.0 + ECC * s0)));
  3108.     q1 = (1.0 - ECC2) * (s1 / (1.0 - ECC2 * s1 * s1) - (0.5 / ECC) * log ((1.0 - ECC * s1) / (1.0 + ECC * s1)));
  3109.     q2 = (1.0 - ECC2) * (s2 / (1.0 - ECC2 * s2 * s2) - (0.5 / ECC) * log ((1.0 - ECC * s2) / (1.0 + ECC * s2)));
  3110.     
  3111.     project_info.a_n = (m1 - m2) / (q2 - q1);
  3112.     project_info.a_C = m1 + project_info.a_n * q1;
  3113.     project_info.a_rho0 = EQ_RAD * sqrt (project_info.a_C - project_info.a_n * q0) / project_info.a_n;
  3114. }
  3115.  
  3116. int albers (lon, lat, x, y)
  3117. double lon, lat, *x, *y; {
  3118.     /* Convert lon/lat to Albers x/y */
  3119.     
  3120.     double s, q, theta, rho;
  3121.     
  3122.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  3123.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  3124.     lon -= project_info.central_meridian;
  3125.     lon *= D2R;
  3126.     lat *= D2R;
  3127.     
  3128.     s = sin (lat);
  3129.     q = (1.0 - ECC2) * (s / (1.0 - ECC2 * s * s) - (0.5 / ECC) * log ((1.0 - ECC * s) / (1.0 + ECC * s)));
  3130.     theta = project_info.a_n * lon;
  3131.     rho = EQ_RAD * sqrt (project_info.a_C - project_info.a_n * q) / project_info.a_n;
  3132.     
  3133.     *x = rho * sin (theta);
  3134.     *y = project_info.a_rho0 - rho * cos (theta);
  3135. }
  3136.  
  3137. int ialbers (lon, lat, x, y)
  3138. double *lon, *lat, x, y; {
  3139.     /* Convert ALbers x/y to lon/lat */
  3140.     
  3141.     int n_iter = 0;
  3142.     double theta, rho, q, phi, phi0, s, delta, test;
  3143.     
  3144.     theta = (project_info.a_n < 0.0) ? d_atan2 (-x, y - project_info.a_rho0) : d_atan2 (x, project_info.a_rho0 - y);
  3145.     rho = hypot (x, project_info.a_rho0 - y);
  3146.     q = (project_info.a_C - rho * rho * project_info.a_n * project_info.a_n / (EQ_RAD * EQ_RAD)) / project_info.a_n;
  3147.     
  3148.     test = 1.0 - (0.5 * (1.0 - ECC2) / ECC) * log ((1.0 - ECC) / (1.0 + ECC));
  3149.     if (fabs (fabs (q) - test) < SMALL)
  3150.         *lat = copysign (90.0, q);
  3151.     else {
  3152.         phi = d_asin (0.5 * q);
  3153.         do {
  3154.             phi0 = phi;
  3155.             s = sin (phi0);
  3156.             phi = phi0 + 0.5 * (1.0 - ECC2 * s * s) * ((q / (1.0 - ECC2)) - s / (1.0 - ECC2 * s * s)
  3157.                 + 0.5 * log ((1 - ECC * s) / (1.0 + ECC * s)) / ECC) / cos (phi);
  3158.             delta = fabs (phi - phi0);
  3159.             n_iter++;
  3160.         }
  3161.         while (delta > SMALL && n_iter < 100);
  3162.         *lat = R2D * phi;
  3163.     }
  3164.     *lon = project_info.central_meridian + R2D * theta / project_info.a_n;
  3165. }
  3166.  
  3167. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3168.  *
  3169.  *    S E C T I O N  1.1 :    S U P P O R T I N G   R O U T I N E S
  3170.  *
  3171.  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  3172.  
  3173. int wesn_search () {
  3174.     double dx, dy, w, e, s, n, x, y, lon, lat;
  3175.     int i, j;
  3176.     
  3177.     /* Search for extreme original coordinates lon/lat */
  3178.             
  3179.     dx = project_info.xmax / gmtdefs.n_lon_nodes;
  3180.     dy = project_info.ymax / gmtdefs.n_lat_nodes;
  3181.     w = s = MAXDOUBLE;    e = n = -MAXDOUBLE;
  3182.     for (i = 0; i <= gmtdefs.n_lon_nodes; i++) {
  3183.         x = i * dx;
  3184.         xy_to_geo (&lon, &lat, x, 0.0);
  3185.         if (lon < w) w = lon;
  3186.         if (lon > e) e = lon;
  3187.         if (lat < s) s = lat;
  3188.         if (lat > n) n = lat;
  3189.         xy_to_geo (&lon, &lat, x, project_info.ymax);
  3190.         if (lon < w) w = lon;
  3191.         if (lon > e) e = lon;
  3192.         if (lat < s) s = lat;
  3193.         if (lat > n) n = lat;
  3194.     }
  3195.     for (j = 0; j <= gmtdefs.n_lat_nodes; j++) {
  3196.         y = j * dy;
  3197.         xy_to_geo (&lon, &lat, 0.0, y);
  3198.         if (lon < w) w = lon;
  3199.         if (lon > e) e = lon;
  3200.         if (lat < s) s = lat;
  3201.         if (lat > n) n = lat;
  3202.         xy_to_geo (&lon, &lat, project_info.xmax, y);
  3203.         if (lon < w) w = lon;
  3204.         if (lon > e) e = lon;
  3205.         if (lat < s) s = lat;
  3206.         if (lat > n) n = lat;
  3207.     }
  3208.     
  3209.     /* Then check if one or both poles are inside map; then the above wont be correct */
  3210.     
  3211.     if (!map_outside (project_info.central_meridian, 90.0)) {
  3212.         n = 90.0;
  3213.         w = 0.0;
  3214.         e = 360.0;
  3215.     }
  3216.     /* if (project_info.projection != AZ_EQDIST && !map_outside (project_info.central_meridian, -90.0)) { why was it like this? */
  3217.     if (!map_outside (project_info.central_meridian, -90.0)) {
  3218.         s = -90.0;
  3219.         w = 0.0;
  3220.         e = 360.0;
  3221.     }
  3222.     
  3223.     s -= 0.1;    if (s < -90.0) s = -90.0;    /* Make sure point is not inside area, 0.1 is just a small number */
  3224.     n += 0.1;    if (n > 90.0) n = 90.0;
  3225.     w -= 0.1;    e += 0.1;
  3226.     
  3227.     if (fabs (w - e) > 360.0) {
  3228.         w = 0.0;
  3229.         e = 360.0;
  3230.     }
  3231.     project_info.w = w;
  3232.     project_info.e = e;
  3233.     project_info.s = s;
  3234.     project_info.n = n;
  3235. }
  3236.  
  3237. int xy_search (x0, x1, y0, y1)
  3238. double *x0, *x1, *y0, *y1; {
  3239.     int i, j;
  3240.     double xmin, xmax, ymin, ymax, w, s, x, y;
  3241.     
  3242.     /* Find min/max forward values */
  3243.     
  3244.     xmax = ymax = -MAXDOUBLE;
  3245.     xmin = ymin = MAXDOUBLE;
  3246.     gmtdefs.dlon = fabs (project_info.e - project_info.w) / 500;
  3247.     gmtdefs.dlat = fabs (project_info.n - project_info.s) / 500;
  3248.     
  3249.     for (i = 0; i <= 500; i++) {
  3250.         w = project_info.w + i * gmtdefs.dlon;
  3251.         (*forward) (w, project_info.s, &x, &y);
  3252.         if (x < xmin) xmin = x;
  3253.         if (y < ymin) ymin = y;
  3254.         if (x > xmax) xmax = x;
  3255.         if (y > ymax) ymax = y;
  3256.         (*forward) (w, project_info.n, &x, &y);
  3257.         if (x < xmin) xmin = x;
  3258.         if (y < ymin) ymin = y;
  3259.         if (x > xmax) xmax = x;
  3260.         if (y > ymax) ymax = y;
  3261.     }
  3262.     for (j = 0; j <= 500; j++) {
  3263.         s = project_info.s + j * gmtdefs.dlat;
  3264.         (*forward) (project_info.w, s, &x, &y);
  3265.         if (x < xmin) xmin = x;
  3266.         if (y < ymin) ymin = y;
  3267.         if (x > xmax) xmax = x;
  3268.         if (y > ymax) ymax = y;
  3269.         (*forward) (project_info.e, s, &x, &y);
  3270.         if (x < xmin) xmin = x;
  3271.         if (y < ymin) ymin = y;
  3272.         if (x > xmax) xmax = x;
  3273.         if (y > ymax) ymax = y;
  3274.     }
  3275.     
  3276.     *x0 = xmin;    *x1 = xmax;    *y0 = ymin;    *y1 = ymax;
  3277. }
  3278.  
  3279. int map_crossing (lon1, lat1, lon2, lat2, xlon, xlat, xx, yy, sides)
  3280. double lon1, lat1, lon2, lat2, *xlon, *xlat, *xx, *yy;
  3281. int *sides; {
  3282.     int nx;
  3283.     gmt_corner = -1;
  3284.     nx = (*crossing) (lon1, lat1, lon2, lat2, xlon, xlat, xx, yy, sides);
  3285.     
  3286.     /* nx may be -2, in which case we dont want to check the order */
  3287.     if (nx == 2) {    /* Must see if crossings are in correct order */
  3288.         double da, db;
  3289.  
  3290.         da = great_circle_dist (lon1, lat1, xlon[0], xlat[0]);
  3291.         db = great_circle_dist (lon1, lat1, xlon[1], xlat[1]);
  3292.         if (da > db) { /* Must swap */
  3293.             d_swap (xlon[0], xlon[1]);
  3294.             d_swap (xlat[0], xlat[1]);
  3295.             d_swap (xx[0], xx[1]);
  3296.             d_swap (yy[0], yy[1]);
  3297.             i_swap (sides[0], sides[1]);
  3298.         }
  3299.     }
  3300.     return (abs(nx));
  3301. }
  3302.  
  3303. int map_outside (lon, lat)
  3304. double lon, lat; {
  3305.     gmt_x_status_old = gmt_x_status_new;
  3306.     gmt_y_status_old = gmt_y_status_new;
  3307.     return ((*outside) (lon, lat));
  3308. }
  3309.  
  3310. int break_through (x0, y0, x1, y1)
  3311. double x0, y0, x1, y1; {
  3312.     
  3313.     if (gmt_x_status_old == gmt_x_status_new && gmt_y_status_old == gmt_y_status_new) return (FALSE);
  3314.     if ((gmt_x_status_old == 0 && gmt_y_status_old == 0) || (gmt_x_status_new == 0 && gmt_y_status_new == 0)) return (TRUE);
  3315.     
  3316.     /* Less clearcut case, check for overlap */
  3317.     
  3318.     return ( (*overlap) (x0, y0, x1, y1));
  3319. }
  3320.  
  3321. int rect_overlap (lon0, lat0, lon1, lat1)
  3322. double lon0, lat0, lon1, lat1; {
  3323.     double x0, y0, x1, y1;
  3324.     
  3325.     geo_to_xy (lon0, lat0, &x0, &y0);
  3326.     geo_to_xy (lon1, lat1, &x1, &y1);
  3327.     
  3328.     if (x0 > x1) d_swap (x0, x1);
  3329.     if (y0 > y1) d_swap (y0, y1);
  3330.     if (x1 < project_info.xmin || x0 > project_info.xmax) return (FALSE);
  3331.     if (y1 < project_info.ymin || y0 > project_info.ymax) return (FALSE);
  3332.     return (TRUE);
  3333. }
  3334.  
  3335. int wesn_overlap (lon0, lat0, lon1, lat1)
  3336. double lon0, lat0, lon1, lat1; {
  3337.     if (lon0 > lon1) d_swap (lon0, lon1);
  3338.     if (lat0 > lat1) d_swap (lat0, lat1);
  3339.     if (lon1 < project_info.w) {
  3340.         lon0 += 360.0;
  3341.         lon1 += 360.0;
  3342.     }
  3343.     else if (lon0 > project_info.e) {
  3344.         lon0 -= 360.0;
  3345.         lon1 -= 360.0;
  3346.     }
  3347.     if (lon1 < project_info.w || lon0 > project_info.e) return (FALSE);
  3348.     if (lat1 < project_info.s || lat0 > project_info.n) return (FALSE);
  3349.     return (TRUE);
  3350. }
  3351.  
  3352. int radial_overlap (lon0, lat0, lon1, lat1)
  3353. double lon0, lat0, lon1, lat1; {    /* Dummy routine */
  3354.     return (TRUE);
  3355. }
  3356.  
  3357. int wrap_around_check (angle, last_x, last_y, this_x, this_y, xx, yy, sides, nx)
  3358. double *angle, last_x, last_y, this_x, this_y, *xx, *yy;
  3359. int  *sides, *nx; {
  3360.     int i, wrap = FALSE, skip;
  3361.     double dx, width, jump, gmt_half_map_width();
  3362.     
  3363.     jump = this_x - last_x;
  3364.     width = gmt_half_map_width (this_y);
  3365.     
  3366.     skip = (fabs (jump) < width || (fabs(jump) <= SMALL || fabs(width) <= SMALL));
  3367.              
  3368.     for (i = 0; i < (*nx); i++) {    /* Must check if the crossover found should wrap around */
  3369.         if (skip) continue;
  3370.         
  3371.         if (jump < (-width)) {    /* Crossed right boundary */
  3372.             xx[0] = right_boundary (this_y);    xx[1] = left_boundary (this_y);
  3373.             dx = this_x + gmt_map_width - last_x;
  3374.             yy[0] = yy[1] = last_y + (gmt_map_width - last_x) * (this_y - last_y) / dx;
  3375.             sides[0] = 1;    sides[1] = 3;
  3376.             angle[0] = R2D * d_atan2 (this_y - last_y, dx);
  3377.         }
  3378.         else {    /* Crossed left boundary */
  3379.             xx[0] = left_boundary (this_y);    xx[1] = right_boundary (this_y);
  3380.             dx = last_x + gmt_map_width - this_x;
  3381.             yy[0] = yy[1] = last_y + last_x * (this_y - last_y) / dx;
  3382.             sides[0] = 3;    sides[1] = 1;
  3383.             angle[0] = R2D * d_atan2 (this_y - last_y, -dx);
  3384.         }
  3385.         angle[1] = angle[0] + 180.0;
  3386.         if (yy[0] >= 0.0 && yy[0] <= project_info.ymax) wrap = TRUE;
  3387.     }
  3388.     
  3389.     if (*nx == 0 && !skip) {    /* Must wrap around */
  3390.         if (jump < (-width)) {    /* Crossed right boundary */
  3391.             xx[0] = right_boundary (this_y);    xx[1] = left_boundary (this_y);
  3392.             dx = this_x + gmt_map_width - last_x;
  3393.             yy[0] = yy[1] = last_y + (gmt_map_width - last_x) * (this_y - last_y) / dx;
  3394.             sides[0] = 1;    sides[1] = 3;
  3395.             angle[0] = R2D * d_atan2 (this_y - last_y, dx);
  3396.         }
  3397.         else {    /* Crossed left boundary */
  3398.             xx[0] = left_boundary (this_y);    xx[1] = right_boundary (this_y);
  3399.             dx = last_x + gmt_map_width - this_x;
  3400.             yy[0] = yy[1] = last_y + last_x * (this_y - last_y) / dx;
  3401.             sides[0] = 3;    sides[1] = 1;
  3402.             angle[0] = R2D * d_atan2 (this_y - last_y, -dx);
  3403.         }
  3404.         if (yy[0] >= 0.0 && yy[0] <= project_info.ymax) wrap = TRUE;
  3405.         angle[1] = angle[0] + 180.0;
  3406.     }
  3407.     
  3408.     if (wrap) *nx = 2;
  3409.     return (wrap);
  3410. }
  3411.  
  3412. double left_ellipse (y)
  3413. double y; {
  3414.     y -= project_info.w_r;
  3415.     return (gmt_half_map_size - 2.0 * d_sqrt (project_info.w_r * project_info.w_r - y * y));
  3416. }
  3417.  
  3418. double left_winkel (y)
  3419. double y; {
  3420.     int n_iter = 0;
  3421.     double c, phi, phi0, delta, x, y0;
  3422.     
  3423.     y0 = 0.5 * project_info.ymax;
  3424.     y -= y0;
  3425.     y /= project_info.y_scale;
  3426.     c = 2.0 * y / EQ_RAD;
  3427.     phi = y / EQ_RAD;
  3428.     do {
  3429.         phi0 = phi;
  3430.         phi = phi0 - (phi0 + M_PI_2 * sin (phi0) - c) / (1.0 + M_PI_2 * cos (phi0));
  3431.         delta = fabs (phi - phi0);
  3432.         n_iter++;
  3433.     }
  3434.     while (delta > SMALL && n_iter < 100);
  3435.     geo_to_xy (project_info.central_meridian-180.0, phi * R2D, &x, &c);
  3436.     return (x);
  3437. }
  3438.  
  3439. double left_eckert (y)
  3440. double y; {
  3441.     double x, phi;
  3442.     
  3443.     y -= project_info.y0;
  3444.     y /= project_info.y_scale;
  3445.     phi = 0.5 * y * project_info.k_ir;
  3446.     x = project_info.k_r * D2R * (project_info.w - project_info.central_meridian) * (1.0 + cos (phi));
  3447.     return (x * project_info.x_scale + project_info.x0);
  3448. }
  3449.  
  3450. double left_robinson (y)
  3451. double y; {
  3452.     double x, X, Y;
  3453.     
  3454.     y -= project_info.y0;
  3455.     y /= project_info.y_scale;
  3456.     Y = fabs (y / project_info.n_cy);
  3457.     intpol (project_info.n_Y, project_info.n_X, 19, 1, &Y, &X, gmtdefs.interpolant);
  3458.     
  3459.     x = project_info.n_cx * X * (project_info.w - project_info.central_meridian);
  3460.     return (x * project_info.x_scale + project_info.x0);
  3461. }
  3462.  
  3463. double left_sinusoidal (y)
  3464. double y; {
  3465.     double x, lat;
  3466.     y -= project_info.y0;
  3467.     y /= project_info.y_scale;
  3468.     lat = y / EQ_RAD;
  3469.     x = EQ_RAD * (project_info.w - project_info.central_meridian) * D2R * cos (lat);
  3470.     return (x * project_info.x_scale + project_info.x0);
  3471. }
  3472.  
  3473. double left_circle (y)
  3474. double y; {
  3475.     y -= project_info.r;
  3476.     return (gmt_half_map_size - d_sqrt (project_info.r * project_info.r - y * y));
  3477. }
  3478.  
  3479. double left_lambert (y)
  3480. double y; {
  3481.     fprintf (stderr, "GMT Warning: left_lambert () called which should not occur.  Report to gmt@soest\n");
  3482.     return (0.0);    /* For completeness, but should never be called */
  3483. }
  3484.  
  3485. double left_albers (y)
  3486. double y; {
  3487.     fprintf (stderr, "GMT Warning: left_albers () called which should not occur.  Report to gmt@soest\n");
  3488.     return (0.0);    /* For completeness, but should never be called */
  3489. }
  3490.  
  3491. double left_rect (y)
  3492. double y; {
  3493.     return (0.0);
  3494. }
  3495.  
  3496. double left_boundary (y)
  3497. double y; {
  3498.     return ((*left_edge) (y));
  3499. }
  3500.  
  3501. double right_ellipse (y)
  3502. double y; {
  3503.     y -= project_info.w_r;
  3504.     return (gmt_half_map_size + 2.0 * d_sqrt (project_info.w_r * project_info.w_r - y * y));
  3505. }
  3506.  
  3507. double right_winkel (y)
  3508. double y; {
  3509.     int n_iter = 0;
  3510.     double c, phi, phi0, delta, x, y0;
  3511.     
  3512.     y0 = 0.5 * project_info.ymax;
  3513.     y -= y0;
  3514.     y /= project_info.y_scale;
  3515.     c = 2.0 * y / EQ_RAD;
  3516.     phi = y / EQ_RAD;
  3517.     do {
  3518.         phi0 = phi;
  3519.         phi = phi0 - (phi0 + M_PI_2 * sin (phi0) - c) / (1.0 + M_PI_2 * cos (phi0));
  3520.         delta = fabs (phi - phi0);
  3521.         n_iter++;
  3522.     }
  3523.     while (delta > SMALL && n_iter < 100);
  3524.     geo_to_xy (project_info.central_meridian+180.0, phi * R2D, &x, &c);
  3525.     return (x);
  3526. }
  3527.  
  3528. double right_eckert (y)
  3529. double y; {
  3530.     double x, phi;
  3531.     
  3532.     y -= project_info.y0;
  3533.     y /= project_info.y_scale;
  3534.     phi = 0.5 * y * project_info.k_ir;
  3535.     x = project_info.k_r * D2R * (project_info.e - project_info.central_meridian) * (1.0 + cos (phi));
  3536.     return (x * project_info.x_scale + project_info.x0);
  3537. }
  3538.  
  3539. double right_robinson (y)
  3540. double y; {
  3541.     double x, X, Y;
  3542.     
  3543.     y -= project_info.y0;
  3544.     y /= project_info.y_scale;
  3545.     Y = fabs (y / project_info.n_cy);
  3546.     intpol (project_info.n_Y, project_info.n_X, 19, 1, &Y, &X, gmtdefs.interpolant);
  3547.     
  3548.     x = project_info.n_cx * X * (project_info.e - project_info.central_meridian);
  3549.     return (x * project_info.x_scale + project_info.x0);
  3550. }
  3551.  
  3552. double right_sinusoidal (y)
  3553. double y; {
  3554.     double x, lat;
  3555.     y -= project_info.y0;
  3556.     y /= project_info.y_scale;
  3557.     lat = y / EQ_RAD;
  3558.     x = EQ_RAD * (project_info.e - project_info.central_meridian) * D2R * cos (lat);
  3559.     return (x * project_info.x_scale + project_info.x0);
  3560. }
  3561.  
  3562. double right_circle (y)
  3563. double y; {
  3564.     y -= project_info.r;
  3565.     return (gmt_half_map_size + d_sqrt (project_info.r * project_info.r - y * y));
  3566. }
  3567.  
  3568. double right_lambert (y)
  3569. double y; {
  3570.     fprintf (stderr, "GMT Warning: right_lambert () called which should not occur.  Report to gmt@soest\n");
  3571.     return (gmt_map_width);    /* For completeness, but should never be called */
  3572. }
  3573.  
  3574. double right_albers (y)
  3575. double y; {
  3576.     fprintf (stderr, "GMT Warning: right_albers () called which should not occur.  Report to gmt@soest\n");
  3577.     return (gmt_map_width);    /* For completeness, but should never be called */
  3578. }
  3579.  
  3580. double right_rect (y)
  3581. double y; {
  3582.     return (gmt_map_width);
  3583. }
  3584.  
  3585. double right_boundary (y)
  3586. double y; {
  3587.     return ((*right_edge) (y));
  3588. }
  3589.  
  3590. int map_jump (x0, y0, x1, y1)
  3591. double x0, y0, x1, y1; {
  3592.     /* TRUE if x-distance between points exceeds 1/2 map width at this y value */
  3593.     double dx, map_half_size;
  3594.     
  3595.     if (!MAPPING || fabs (project_info.w - project_info.e) < 90.0) return (FALSE);
  3596.     
  3597.     map_half_size = gmt_half_map_width (y0);
  3598.     if (fabs (map_half_size) < SMALL) return (0);
  3599.     
  3600.     dx = x1 - x0;
  3601.     if (dx > map_half_size)    /* Cross left/west boundary */
  3602.         return (-1);
  3603.     else if (dx < (-map_half_size)) /* Cross right/east boundary */
  3604.         return (1);
  3605.     else
  3606.         return (0);
  3607. }
  3608.     
  3609. int get_crossings (xc, yc, x0, y0, x1, y1)
  3610. double xc[], yc[];
  3611. double x0, y0, x1, y1; {    /* Finds crossings for wrap-arounds */
  3612.     double xa, xb, ya, yb, dxa, dxb, dyb, c;
  3613.     
  3614.     xa = x0;    xb = x1;
  3615.     ya = y0;    yb = y1;
  3616.     if (xa > xb) {
  3617.         d_swap (xa, xb);
  3618.         d_swap (ya, yb);
  3619.     }
  3620.     
  3621.     xb -= 2.0 * gmt_half_map_width (yb);
  3622.     
  3623.     dxa = xa - left_boundary (ya);
  3624.     dxb = left_boundary (yb) - xb;
  3625.     c = (dxb == 0.0) ? 0.0 : 1.0 + dxa/dxb;
  3626.     dyb = (c == 0.0) ? 0.0 : fabs (yb - ya) / c;
  3627.     yc[0] = yc[1] = (ya > yb) ? yb + dyb : yb - dyb;
  3628.     xc[0] = left_boundary (yc[0]);
  3629.     xc[1] = right_boundary (yc[0]);
  3630. }
  3631.  
  3632. double gmt_half_map_width (y)
  3633. double y;    {    /* Returns 1/2-width of map in inches given y value */
  3634.     double half_width;
  3635.     
  3636.     switch (project_info.projection) {
  3637.     
  3638.         case STEREO:    /* Must compute width of circular map based on y value */
  3639.         case LAMB_AZ_EQ:
  3640.         case ORTHO:
  3641.         case AZ_EQDIST:
  3642.             if (project_info.region && gmt_world_map) {
  3643.                 y -= project_info.r;
  3644.                 half_width = d_sqrt (project_info.r * project_info.r - y * y);
  3645.             }
  3646.             else
  3647.                 half_width = gmt_half_map_size;
  3648.             break;
  3649.  
  3650.         case MOLLWEIDE:        /* Must compute width of Mollweide map based on y value */
  3651.         case HAMMER:
  3652.             if (project_info.region && gmt_world_map) {
  3653.                 y -= project_info.w_r;
  3654.                 half_width = 2.0 * d_sqrt (project_info.w_r * project_info.w_r - y * y);
  3655.             }
  3656.             else
  3657.                 half_width = gmt_half_map_size;
  3658.             break;
  3659.         case WINKEL:
  3660.         case SINUSOIDAL:
  3661.         case ROBINSON:
  3662.         case ECKERT:
  3663.             if (project_info.region && gmt_world_map)
  3664.                 half_width = right_boundary (y) - gmt_half_map_size;
  3665.             else
  3666.                 half_width = gmt_half_map_size;
  3667.             break;
  3668.     
  3669.         default:    /* Rectangular maps are easy */
  3670.             half_width = gmt_half_map_size;
  3671.             break;
  3672.     }
  3673.     return (half_width);
  3674. }
  3675.  
  3676. int will_it_wrap (x, y, n, start)
  3677. double x[], y[];
  3678. int n, *start; {    /* Determines if a polygon will wrap at edges */
  3679.     int i;
  3680.     BOOLEAN wrap;
  3681.     double dx, w;
  3682.     
  3683.     if (!gmt_world_map) return (FALSE);
  3684.     
  3685.     for (i = 1, wrap = FALSE; !wrap && i < n; i++) {
  3686.         dx = fabs (x[i] - x[i-1]);
  3687.         if (dx > (w = gmt_half_map_width (y[i])) && w > 0.0)
  3688.             wrap = TRUE;
  3689.     }
  3690.     *start = i - 1;
  3691.     return (wrap);
  3692. }
  3693.  
  3694. int truncate_left (x, y, n, start)
  3695. double x[], y[];
  3696. int n, start; {    /* Truncates a wrapping polygon agains left edge */
  3697.     int i, i1, j, k;
  3698.     BOOLEAN on;
  3699.     double dx, xc[2], yc[2];
  3700.     
  3701.     /* Find first point that is left of map center */
  3702.     
  3703.     i = (x[start] < gmt_half_map_size) ? start : start - 1;
  3704.     
  3705.     if (!gmt_n_alloc) get_plot_array ();
  3706.     
  3707.     gmt_x_plot[0] = x[i];    gmt_y_plot[0] = y[i];
  3708.     for (k = j = 1, on = FALSE; k < n; k++, j++) {
  3709.         i1 = i;
  3710.         i = (i + 1)%n;    /* Next point */
  3711.         dx = fabs (x[i] - x[i1]);
  3712.         if (dx > gmt_half_map_width (y[i])) {
  3713.             on = !on;
  3714.             get_crossings (xc, yc, x[i1], y[i1], x[i], y[i]);
  3715.             gmt_x_plot[j] = xc[0];
  3716.             gmt_y_plot[j] = yc[0];
  3717.             j++;
  3718.             if (j >= gmt_n_alloc) get_plot_array ();
  3719.         }
  3720.         gmt_x_plot[j] = (on) ? left_boundary (y[i]) : x[i];
  3721.         gmt_y_plot[j] = y[i];
  3722.         if (j >= gmt_n_alloc) get_plot_array ();
  3723.     }
  3724.     return (j);
  3725. }
  3726.  
  3727. int truncate_right (x, y, n, start)
  3728. double x[], y[];
  3729. int n, start; {    /* Truncates a wrapping polygon agains right edge */
  3730.     int i, i1, j, k;
  3731.     BOOLEAN on;
  3732.     double dx, xc[2], yc[2];
  3733.     
  3734.     /* Find first point that is right of map center */
  3735.     
  3736.     i = (x[start] > gmt_half_map_size) ? start : start - 1;
  3737.     
  3738.     if (!gmt_n_alloc) get_plot_array ();
  3739.     gmt_x_plot[0] = x[i];    gmt_y_plot[0] = y[i];
  3740.     for (k = j = 1, on = FALSE; k < n; k++, j++) {
  3741.         i1 = i;
  3742.         i = (i + 1)%n;    /* Next point */
  3743.         dx = fabs (x[i] - x[i1]);
  3744.         if (dx > gmt_half_map_width (y[i])) {
  3745.             on = !on;
  3746.             get_crossings (xc, yc, x[i1], y[i1], x[i], y[i]);
  3747.             gmt_x_plot[j] = xc[1];
  3748.             gmt_y_plot[j] = yc[1];
  3749.             j++;
  3750.             if (j >= gmt_n_alloc) get_plot_array ();
  3751.         }
  3752.         gmt_x_plot[j] = (on) ? right_boundary (y[i]) : x[i];
  3753.         gmt_y_plot[j] = y[i];
  3754.         if (j >= gmt_n_alloc) get_plot_array ();
  3755.     }
  3756.     return (j);
  3757. }
  3758.  
  3759. double great_circle_dist( lon1, lat1, lon2, lat2 )  
  3760. double lon1, lat1, lon2, lat2;
  3761. {
  3762.     /* great circle distance on a sphere in degrees */
  3763.     double C, a, b, c;
  3764.     double cosC, cosa, cosb, cosc;
  3765.     double sina, sinb;
  3766.  
  3767.     if( (lat1==lat2) && (lon1==lon2) ) {
  3768.         return( (double)0.0 );
  3769.         }
  3770.  
  3771.     a=D2R*(90.0-lat2);
  3772.     b=D2R*(90.0-lat1);
  3773.  
  3774.     C = D2R*( lon2 - lon1 );
  3775.  
  3776.     cosa = cos(a);
  3777.     cosb = cos(b);
  3778.     sina = sin(a);
  3779.     sinb = sin(b);
  3780.     cosC = cos(C);
  3781.  
  3782.     cosc = cosa*cosb + sina*sinb*cosC;
  3783.     if (cosc<-1.0) c=M_PI; else if (cosc>1) c=0.0; else c=d_acos(cosc);
  3784.  
  3785.     return( c * R2D);
  3786. }
  3787.  
  3788. /* The *_outside rutines returns the status of the current point.  Status is
  3789.  * the sum of x_status and y_status. x_status may be
  3790.  *    0    w < lon < e
  3791.  *    -1    lon == w
  3792.  *    1    lon == e
  3793.  *    -2    lon < w
  3794.  *    2    lon > e
  3795.  *    y_status may be
  3796.  *    0    s < lat < n
  3797.  *    -1    lat == s
  3798.  *    1    lat == n
  3799.  *    -2    lat < s
  3800.  *    2    lat > n
  3801.  */
  3802.  
  3803. int wesn_outside (lon, lat)
  3804. double lon, lat; {
  3805.     
  3806.     if (gmt_world_map) {
  3807.         while (lon < project_info.w) lon += 360.0;
  3808.         while (lon > project_info.e) lon -= 360.0;
  3809.     }
  3810.     
  3811.     if (on_border_is_outside && fabs (lon - project_info.w) < SMALL )
  3812.         gmt_x_status_new = -1;
  3813.     else if (on_border_is_outside && fabs (lon - project_info.e) < SMALL)
  3814.         gmt_x_status_new = 1;
  3815.     else if (lon < project_info.w)
  3816.         gmt_x_status_new = -2;
  3817.     else if (lon > project_info.e)
  3818.         gmt_x_status_new = 2;
  3819.     else
  3820.         gmt_x_status_new = 0;
  3821.         
  3822.     if (on_border_is_outside && fabs (lat - project_info.s) < SMALL )
  3823.         gmt_y_status_new = -1;
  3824.     else if (on_border_is_outside && fabs (lat - project_info.n) < SMALL)
  3825.         gmt_y_status_new = 1;
  3826.     else if (lat < project_info.s )
  3827.         gmt_y_status_new = -2;
  3828.     else if (lat > project_info.n)
  3829.         gmt_y_status_new = 2;
  3830.     else
  3831.         gmt_y_status_new = 0;
  3832.         
  3833.     return ( !(gmt_x_status_new == 0 && gmt_y_status_new == 0));
  3834.     
  3835. }
  3836.  
  3837. int polar_outside (lon, lat)
  3838. double lon, lat; {
  3839.     
  3840.     if (on_border_is_outside && fabs (lon - project_info.w) < SMALL )
  3841.         gmt_x_status_new = -1;
  3842.     else if (on_border_is_outside && fabs (lon - project_info.e) < SMALL)
  3843.         gmt_x_status_new = 1;
  3844.     else if (lon < project_info.w)
  3845.         gmt_x_status_new = -2;
  3846.     else if (lon > project_info.e)
  3847.         gmt_x_status_new = 2;
  3848.     else
  3849.         gmt_x_status_new = 0;
  3850.     if (!project_info.edge[1]) gmt_x_status_new = 0;    /* 360 degrees, no edge */
  3851.         
  3852.     if (on_border_is_outside && fabs (lat - project_info.s) < SMALL )
  3853.         gmt_y_status_new = -1;
  3854.     else if (on_border_is_outside && fabs (lat - project_info.n) < SMALL)
  3855.         gmt_y_status_new = 1;
  3856.     else if (lat < project_info.s )
  3857.         gmt_y_status_new = -2;
  3858.     else if (lat > project_info.n)
  3859.         gmt_y_status_new = 2;
  3860.     else
  3861.         gmt_y_status_new = 0;
  3862.     if (gmt_y_status_new < 0 && !project_info.edge[0]) gmt_y_status_new = 0;    /* South pole enclosed */
  3863.     if (gmt_y_status_new > 0 && !project_info.edge[2]) gmt_y_status_new = 0;    /* North pole enclosed */
  3864.     
  3865.     return ( !(gmt_x_status_new == 0 && gmt_y_status_new == 0));
  3866.     
  3867. }
  3868.  
  3869. int eqdist_outside (lon, lat)
  3870. double lon, lat; {
  3871.     double dlon, cc;
  3872.     
  3873.     while ((lon - project_info.central_meridian) < -180.0) lon += 360.0;
  3874.     while ((lon - project_info.central_meridian) > 180.0) lon -= 360.0;
  3875.     dlon = (lon - project_info.central_meridian);
  3876.     cc = project_info.sinp * sind (lat) + project_info.cosp * cosd (lat) * cosd (dlon);
  3877.     /* if (cc <= -1.0) { */
  3878.     if (cc < -1.0) {
  3879.         gmt_y_status_new = -1;
  3880.         gmt_x_status_new = 0;
  3881.     }
  3882.     else
  3883.         gmt_x_status_new = gmt_y_status_new = 0;
  3884.     return ( !(gmt_y_status_new == 0));
  3885. }
  3886.  
  3887. int radial_outside (lon, lat)
  3888. double lon, lat; {
  3889.     double dist;
  3890.     
  3891.     /* Test if point is more than 90 spherical degrees from origin.  For global maps, let all borders by "south" */
  3892.  
  3893.     gmt_x_status_new = 0;
  3894.     dist = great_circle_dist (lon, lat, project_info.central_meridian, project_info.pole);
  3895.     if (on_border_is_outside && fabs (dist - 90.0) < SMALL)
  3896.         gmt_y_status_new = -1;
  3897.     else if (dist > 90.0)
  3898.         gmt_y_status_new = -2;
  3899.     else
  3900.         gmt_y_status_new = 0;
  3901.     return ( !(gmt_y_status_new == 0));
  3902. }
  3903.  
  3904. int rect_outside (lon, lat)
  3905. double lon, lat; {
  3906.     double x, y;
  3907.     
  3908.     geo_to_xy (lon, lat, &x, &y);
  3909.     
  3910.     if (on_border_is_outside && fabs (x - project_info.xmin) < SMALL )
  3911.         gmt_x_status_new = -1;
  3912.     else if (on_border_is_outside && fabs (x - project_info.xmax) < SMALL)
  3913.         gmt_x_status_new = 1;
  3914.     else if (x < project_info.xmin)
  3915.         gmt_x_status_new = -2;
  3916.     else if (x > project_info.xmax)
  3917.         gmt_x_status_new = 2;
  3918.     else
  3919.         gmt_x_status_new = 0;
  3920.         
  3921.     if (on_border_is_outside && fabs (y -project_info.ymin) < SMALL )
  3922.         gmt_y_status_new = -1;
  3923.     else if (on_border_is_outside && fabs (y - project_info.ymax) < SMALL)
  3924.         gmt_y_status_new = 1;
  3925.     else if (y < project_info.ymin)
  3926.         gmt_y_status_new = -2;
  3927.     else if (y > project_info.ymax)
  3928.         gmt_y_status_new = 2;
  3929.     else
  3930.         gmt_y_status_new = 0;
  3931.         
  3932.     return ( !(gmt_x_status_new == 0 && gmt_y_status_new == 0));
  3933.     
  3934. }
  3935.  
  3936. int rect_outside2 (lon, lat)
  3937. double lon, lat; {    /* For Azimuthal proj with rect borders since rect_outside may fail for antipodal points */
  3938.     if (radial_outside (lon, lat)) return (TRUE);    /* Point > 90 degrees away */
  3939.     return (rect_outside (lon, lat));    /* Must check if inside box */
  3940. }
  3941.  
  3942. int pen_status () {
  3943.     int pen = 3;
  3944.     
  3945.     if (gmt_x_status_old == 0 && gmt_y_status_old == 0)
  3946.         pen = 2;
  3947.     else if (gmt_x_status_new == 0 && gmt_y_status_new == 0)
  3948.         pen = 3;
  3949.     return (pen);
  3950. }
  3951.  
  3952. int wesn_crossing (lon0, lat0, lon1, lat1, clon, clat, xx, yy, sides)
  3953. double lon0, lat0, lon1, lat1, *clon, *clat, *xx, *yy;
  3954. int *sides; {
  3955.     /* Compute the crossover point(s) on the map boundary for rectangular projections */
  3956.     int n = 0, i;
  3957.     double dlat, dlon;
  3958.     
  3959.     /* Since it may not be obvious which side the line may cross, and since in some cases the two points may be
  3960.      * entirely outside the region but still cut through it, we first find all possible candidates and then decide
  3961.      * which ones are valid crossings.  We may find 0, 1, or 2 intersections */
  3962.     
  3963.     /* First align the longitudes to the region */
  3964.     
  3965.     if (gmt_world_map) {
  3966.         while (lon0 < project_info.w) lon0 += 360.0;
  3967.         while (lon0 > project_info.e) lon0 -= 360.0;
  3968.         while (lon1 < project_info.w) lon1 += 360.0;
  3969.         while (lon1 > project_info.e) lon1 -= 360.0;
  3970.     }
  3971.     
  3972.     /* Then set 'almost'-corners to corners */
  3973.     
  3974.     x_wesn_corner (&lon0);
  3975.     x_wesn_corner (&lon1);
  3976.     y_wesn_corner (&lat0);
  3977.     y_wesn_corner (&lat1);
  3978.     
  3979.     
  3980. /*    if ((lat0 > project_info.s && lat1 <= project_info.s) || (lat1 > project_info.s && lat0 <= project_info.s)) { */
  3981.     if ((lat0 >= project_info.s && lat1 <= project_info.s) || (lat1 >= project_info.s && lat0 <= project_info.s)) {
  3982.         sides[n] = 0;
  3983.         clat[n] = project_info.s;
  3984.         dlat = lat0 - lat1;
  3985.         clon[n] = (dlat == 0.0) ? lon1 : lon1 + (lon0 - lon1) * (clat[n] - lat1) / dlat;
  3986.         x_wesn_corner (&clon[n]);
  3987.         if (fabs(dlat) > 0.0 && lon_inside (clon[n], project_info.w, project_info.e)) n++;
  3988.     }
  3989. /*    if ((lon0 >= project_info.e && lon1 < project_info.e) || (lon1 >= project_info.e && lon0 < project_info.e)) { */
  3990.     if ((lon0 >= project_info.e && lon1 <= project_info.e) || (lon1 >= project_info.e && lon0 <= project_info.e)) {
  3991.         sides[n] = 1;
  3992.         clon[n] = project_info.e;
  3993.         dlon = lon0 - lon1;
  3994.         clat[n] = (dlon == 0.0) ? lat1 : lat1 + (lat0 - lat1) * (clon[n] - lon1) / dlon;
  3995.         y_wesn_corner (&clat[n]);
  3996.         if (fabs(dlon) > 0.0 && clat[n] >= project_info.s && clat[n] <= project_info.n) n++;
  3997.     }
  3998. /*    if ((lat0 >= project_info.n && lat1 < project_info.n) || (lat1 >= project_info.n && lat0 < project_info.n)) { */
  3999.     if ((lat0 >= project_info.n && lat1 <= project_info.n) || (lat1 >= project_info.n && lat0 <= project_info.n)) {
  4000.         sides[n] = 2;
  4001.         clat[n] = project_info.n;
  4002.         dlat = lat0 - lat1;
  4003.         clon[n] = (dlat == 0.0) ? lon1 : lon1 + (lon0 - lon1) * (clat[n] - lat1) / dlat;
  4004.         x_wesn_corner (&clon[n]);
  4005.         if (fabs(dlat) > 0.0 && lon_inside (clon[n], project_info.w, project_info.e)) n++;
  4006.     }
  4007. /*    if ((lon0 <= project_info.w && lon1 > project_info.w) || (lon1 <= project_info.w && lon0 > project_info.w)) { */
  4008.     if ((lon0 <= project_info.w && lon1 >= project_info.w) || (lon1 <= project_info.w && lon0 >= project_info.w)) {
  4009.         sides[n] = 3;
  4010.         clon[n] = project_info.w;
  4011.         dlon = lon0 - lon1;
  4012.         clat[n] = (dlon == 0.0) ? lat1 : lat1 + (lat0 - lat1) * (clon[n] - lon1) / dlon;
  4013.         y_wesn_corner (&clat[n]);
  4014.         if (fabs(dlon) > 0.0 && clat[n] >= project_info.s && clat[n] <= project_info.n) n++;
  4015.     }
  4016.     
  4017.     for (i = 0; i < n; i++) {
  4018.         geo_to_xy (clon[i], clat[i], &xx[i], &yy[i]);
  4019.         if (project_info.projection == POLAR && sides[i]%2) sides[i] = 4 - sides[i];    /*  toggle 1 <-> 3 */
  4020.     }
  4021.  
  4022.     /* Check for corner xover */
  4023.     
  4024.     if (n < 2) return (n);
  4025.     
  4026.     if (is_wesn_corner (clon[0], clat[0])) return (1); 
  4027.     
  4028.     if (is_wesn_corner (clon[1], clat[1])) {
  4029.         clon[0] = clon[1];
  4030.         clat[0] = clat[1];
  4031.         xx[0] = xx[1];
  4032.         yy[0] = yy[1];
  4033.         sides[0] = sides[1];
  4034.         return (1); 
  4035.     }
  4036.  
  4037.     return (n);
  4038. }
  4039.  
  4040. int rect_crossing (lon0, lat0, lon1, lat1, clon, clat, xx, yy, sides)
  4041. double lon0, lat0, lon1, lat1, *clon, *clat, *xx, *yy;
  4042. int *sides; {
  4043.  
  4044.     /* Compute the crossover point(s) on the map boundary for rectangular projections */
  4045.     int i, n = 0;
  4046.     double x0, x1, y0, y1, d;
  4047.     
  4048.     /* Since it may not be obvious which side the line may cross, and since in some cases the two points may be
  4049.      * entirely outside the region but still cut through it, we first find all possible candidates and then decide
  4050.      * which ones are valid crossings.  We may find 0, 1, or 2 intersections */
  4051.         
  4052.     geo_to_xy (lon0, lat0, &x0, &y0);
  4053.     geo_to_xy (lon1, lat1, &x1, &y1);
  4054.     
  4055.     /* First set 'almost'-corners to corners */
  4056.     
  4057.     x_rect_corner (&x0);
  4058.     x_rect_corner (&x1);
  4059.     y_rect_corner (&y0);
  4060.     y_rect_corner (&y1);
  4061.     
  4062. /*    if ((y0 > project_info.ymin && y1 <= project_info.ymin) || (y1 > project_info.ymin && y0 <= project_info.ymin)) { */
  4063.     if ((y0 >= project_info.ymin && y1 <= project_info.ymin) || (y1 >= project_info.ymin && y0 <= project_info.ymin)) {
  4064.         sides[n] = 0;
  4065.         yy[n] = project_info.ymin;
  4066.         d = y0 - y1;
  4067.         xx[n] = (d == 0.0) ? x0 : x1 + (x0 - x1) * (yy[n] - y1) / d;
  4068.         x_rect_corner (&xx[n]);
  4069.         if (xx[n] >= project_info.xmin && xx[n] <= project_info.xmax) n++;
  4070.     }
  4071. /*    if ((x0 < project_info.xmax && x1 >= project_info.xmax) || (x1 < project_info.xmax && x0 >= project_info.xmax)) { */
  4072.     if ((x0 <= project_info.xmax && x1 >= project_info.xmax) || (x1 <= project_info.xmax && x0 >= project_info.xmax)) {
  4073.         sides[n] = 1;
  4074.         xx[n] = project_info.xmax;
  4075.         d = x0 - x1;
  4076.         yy[n] = (d == 0.0) ? y0 : y1 + (y0 - y1) * (xx[n] - x1) / d;
  4077.         y_rect_corner (&yy[n]);
  4078.         if (yy[n] >= project_info.ymin && yy[n] <= project_info.ymax) n++;
  4079.     }
  4080. /*    if ((y0 < project_info.ymax && y1 >= project_info.ymax) || (y1 < project_info.ymax && y0 >= project_info.ymax)) { */
  4081.     if ((y0 <= project_info.ymax && y1 >= project_info.ymax) || (y1 <= project_info.ymax && y0 >= project_info.ymax)) {
  4082.         sides[n] = 2;
  4083.         yy[n] = project_info.ymax;
  4084.         d = y0 - y1;
  4085.         xx[n] = (d == 0.0) ? x0 : x1 + (x0 - x1) * (yy[n] - y1) / d;
  4086.         x_rect_corner (&xx[n]);
  4087.         if (xx[n] >= project_info.xmin && xx[n] <= project_info.xmax) n++;
  4088.     }
  4089. /*    if ((x0 > project_info.xmin && x1 <= project_info.xmin) || (x1 > project_info.xmin && x0 <= project_info.xmin)) { */
  4090.     if ((x0 >= project_info.xmin && x1 <= project_info.xmin) || (x1 >= project_info.xmin && x0 <= project_info.xmin)) {
  4091.         sides[n] = 3;
  4092.         xx[n] = project_info.xmin;
  4093.         d = x0 - x1;
  4094.         yy[n] = (d == 0.0) ? y0 : y1 + (y0 - y1) * (xx[n] - x1) / d;
  4095.         y_rect_corner (&yy[n]);
  4096.         if (yy[n] >= project_info.ymin && yy[n] <= project_info.ymax) n++;
  4097.     }
  4098.  
  4099.     for (i = 0; i < n; i++)    xy_to_geo (&clon[i], &clat[i], xx[i], yy[i]);
  4100.     
  4101.     /* Check for corner xover */
  4102.     
  4103.     if (n < 2) return (n);
  4104.     
  4105.     if (is_rect_corner (xx[0], yy[0])) return (1); 
  4106.     
  4107.     if (is_rect_corner (xx[1], yy[1])) {
  4108.         clon[0] = clon[1];
  4109.         clat[0] = clat[1];
  4110.         xx[0] = xx[1];
  4111.         yy[0] = yy[1];
  4112.         sides[0] = sides[1];
  4113.         return (1);
  4114.     }
  4115.  
  4116.     return (n);
  4117. }
  4118.  
  4119. int x_rect_corner (x)
  4120. double *x; {
  4121.     if (fabs (*x) <= SMALL)
  4122.         *x = 0.0;
  4123.     else if (fabs (*x - project_info.xmax) <= SMALL)
  4124.         *x = project_info.xmax;
  4125. }
  4126.  
  4127. int y_rect_corner (y)
  4128. double *y; {
  4129.     if (fabs (*y) <= SMALL)
  4130.         *y = 0.0;
  4131.     else if (fabs (*y - project_info.ymax) <= SMALL)
  4132.         *y = project_info.ymax;
  4133. }
  4134.  
  4135. int is_rect_corner (x, y)
  4136. double x, y; {    /* Checks if point is a corner */
  4137.     gmt_corner = -1;
  4138.     if (x == project_info.xmin) {
  4139.         if (y == project_info.ymin)
  4140.             gmt_corner = 1;
  4141.         else if (y == project_info.ymax)
  4142.             gmt_corner = 4;
  4143.     }
  4144.     else if (x == project_info.xmax) {
  4145.         if (y == project_info.ymin)
  4146.             gmt_corner = 2;
  4147.         else if (y == project_info.ymax)
  4148.             gmt_corner = 3;
  4149.     }
  4150.     return (gmt_corner > 0);
  4151. }
  4152.  
  4153. int x_wesn_corner (x)
  4154. double *x; {
  4155. /*    if (fabs (fmod (fabs (*x - project_info.w), 360.0)) <= SMALL)
  4156.         *x = project_info.w;
  4157.     else if (fabs (fmod (fabs (*x - project_info.e), 360.0)) <= SMALL)
  4158.         *x = project_info.e; */
  4159.         
  4160.     if (fabs (*x - project_info.w) <= SMALL)
  4161.         *x = project_info.w;
  4162.     else if (fabs (*x - project_info.e) <= SMALL)
  4163.         *x = project_info.e;
  4164.     
  4165. }
  4166.  
  4167. int y_wesn_corner (y)
  4168. double *y; {
  4169.     if (fabs (*y - project_info.s) <= SMALL)
  4170.         *y = project_info.s;
  4171.     else if (fabs (*y - project_info.n) <= SMALL)
  4172.         *y = project_info.n;
  4173. }
  4174.  
  4175. int is_wesn_corner (x, y)
  4176. double x, y; {    /* Checks if point is a corner */
  4177.     gmt_corner = 0;
  4178.     
  4179.     if (fmod (fabs (x - project_info.w), 360.0) == 0.0) {
  4180.         if (y == project_info.s)
  4181.             gmt_corner = 1;
  4182.         else if (y == project_info.n)
  4183.             gmt_corner = 4;
  4184.     }
  4185.     else if (fmod (fabs (x - project_info.e), 360.0) == 0.0) {
  4186.         if (y == project_info.s)
  4187.             gmt_corner = 2;
  4188.         else if (y == project_info.n)
  4189.             gmt_corner = 3;
  4190.     }
  4191.     return (gmt_corner > 0);
  4192. }
  4193.  
  4194. int radial_crossing (lon1, lat1, lon2, lat2, clon, clat, xx, yy, sides)
  4195. double lon1, lat1, lon2, lat2, *clon, *clat, *xx, *yy;
  4196. int *sides; {
  4197.     /* Computes the lon/lat of a point that is 90 spherical degrees from
  4198.      * the origin and lies on the great circle between points 1 and 2 */
  4199.     
  4200.     double dist1, dist2, delta, eps, dlon;
  4201.     
  4202.     dist1 = great_circle_dist (project_info.central_meridian, project_info.pole, lon1, lat1);
  4203.     dist2 = great_circle_dist (project_info.central_meridian, project_info.pole, lon2, lat2);
  4204.     delta = dist2 - dist1;
  4205.     eps = (delta == 0.0) ? 0.0 : (90.0 - dist1) / delta;
  4206.     dlon = lon2 - lon1;
  4207.     if (fabs (dlon) > 180.0) dlon = copysign (360.0 - fabs (dlon), -dlon);
  4208.     clon[0] = lon1 + dlon * eps;
  4209.     clat[0] = lat1 + (lat2 - lat1) * eps;
  4210.     
  4211.     geo_to_xy (clon[0], clat[0], &xx[0], &yy[0]);
  4212.     sides[0] = 1;
  4213.     
  4214.     return (1);
  4215. }
  4216.  
  4217. int ellipse_crossing (lon1, lat1, lon2, lat2, clon, clat, xx, yy, sides)
  4218. double lon1, lat1, lon2, lat2, *clon, *clat, *xx, *yy;
  4219. int *sides; {
  4220.     /* Compute the crossover point(s) on the map boundary for rectangular projections */
  4221.     int n = 0, i, jump;
  4222.     double x1, x2, y1, y2;
  4223.     
  4224.     /* Crossings here must be at the W or E borders. Lat points may only touch border */
  4225.     
  4226.     if (lat1 == -90.0) {
  4227.         sides[n] = 0;
  4228.         clon[n] = lon1;
  4229.         clat[n] = lat1;
  4230.         n = 1;
  4231.     }
  4232.     else if (lat2 == -90.0) {
  4233.         sides[n] = 0;
  4234.         clon[n] = lon2;
  4235.         clat[n] = lat2;
  4236.         n = 1;
  4237.     }
  4238.     else if (lat1 == 90.0) {
  4239.         sides[n] = 2;
  4240.         clon[n] = lon1;
  4241.         clat[n] = lat1;
  4242.         n = 1;
  4243.     }
  4244.     else if (lat2 == 90.0) {
  4245.         sides[n] = 2;
  4246.         clon[n] = lon2;
  4247.         clat[n] = lat2;
  4248.         n = 1;
  4249.     }
  4250.     else {    /* May cross somewhere else */
  4251.         geo_to_xy (lon1, lat1, &x1, &y1);
  4252.         geo_to_xy (lon2, lat2, &x2, &y2);
  4253.         if ((jump = map_jump (x2, y2, x1, y1))) {
  4254.             get_crossings (xx, yy, x2, y2, x1, y1);
  4255.             if (jump == 1) {    /* Add right border point first */
  4256.                 d_swap (xx[0], xx[1]);
  4257.                 d_swap (yy[0], yy[1]);
  4258.             }
  4259.             xy_to_geo (&clon[0], &clat[0], xx[0], yy[0]);
  4260.             xy_to_geo (&clon[1], &clat[1], xx[1], yy[1]);
  4261.         }
  4262.         n = -2;    /* To signal dont change order */
  4263.     }
  4264.     if (n == 1) for (i = 0; i < n; i++) geo_to_xy (clon[i], clat[i], &xx[i], &yy[i]);
  4265.     return (n);
  4266. }
  4267.  
  4268. int eqdist_crossing (lon1, lat1, lon2, lat2, clon, clat, xx, yy, sides)
  4269. double lon1, lat1, lon2, lat2, *clon, *clat, *xx, *yy;
  4270. int *sides; {
  4271.     double angle, x, y;
  4272.     
  4273.     /* Computes the x.y of the antipole point that lies on a radius from
  4274.      * the origin through the inside point */
  4275.     
  4276.     if (eqdist_outside (lon1, lat1)) {    /* Point 1 is on perimeter */
  4277.         geo_to_xy (lon2, lat2, &x, &y);
  4278.         angle = d_atan2 (y - project_info.y0, x - project_info.x0);
  4279.         xx[0] = project_info.r * cos (angle) + project_info.x0;
  4280.         yy[0] = project_info.r * sin (angle) + project_info.y0;
  4281.         clon[0] = lon1;
  4282.         clat[0] = lat1;
  4283.     }
  4284.     else {    /* Point 2 is on perimeter */
  4285.         geo_to_xy (lon1, lat1, &x, &y);
  4286.         angle = d_atan2 (y - project_info.y0, x - project_info.x0);
  4287.         xx[0] = project_info.r * cos (angle) + project_info.x0;
  4288.         yy[0] = project_info.r * sin (angle) + project_info.y0;
  4289.         clon[0] = lon2;
  4290.         clat[0] = lat2;
  4291.     }
  4292.     sides[0] = 1;
  4293.     
  4294.     return (1);
  4295. }
  4296.  
  4297. /*  Routines to add pieces of parallels or meridians */
  4298.  
  4299. int map_path (lon1, lat1, lon2, lat2, x, y)
  4300. double lon1, lat1, lon2, lat2;
  4301. double *x[], *y[]; {
  4302.     if (lat1 == lat2)
  4303.         return (latpath (lat1, lon1, lon2, x, y));
  4304.     else
  4305.         return (lonpath (lon1, lat1, lat2, x, y));
  4306. }
  4307.  
  4308. int lonpath (lon, lat1, lat2, x, y)
  4309. double lon, lat1, lat2;
  4310. double *x[], *y[]; {
  4311.     int ny, n = 0, n_try, keep_trying, jump, pos;
  4312.     double dlat, *tlon, *tlat, x0, x1, y0, y1, d;
  4313.     double min_gap;
  4314.  
  4315.     min_gap = 0.1 * gmtdefs.line_step;
  4316.     if ((ny = ceil (fabs (lat2 - lat1) / gmtdefs.dlat)) == 0) return (0);
  4317.  
  4318.     ny++;
  4319.     dlat = (lat2 - lat1) / ny;
  4320.     pos = (dlat > 0.0); 
  4321.     
  4322.     tlon = (double *) memory (CNULL, ny, sizeof (double), "lonpath");
  4323.     tlat = (double *) memory (CNULL, ny, sizeof (double), "lonpath");
  4324.     
  4325.     tlon[0] = lon;
  4326.     tlat[0] = lat1;
  4327.     geo_to_xy (tlon[0], tlat[0], &x0, &y0);
  4328.     while ((pos && tlat[n] < lat2) || (!pos & tlat[n] > lat2)) {
  4329.         n++;
  4330.         if (n == ny-1) {
  4331.             ny += GMT_SMALL_CHUNK;
  4332.             tlon = (double *) memory ((char *)tlon, ny, sizeof (double), "lonpath");
  4333.             tlat = (double *) memory ((char *)tlat, ny, sizeof (double), "lonpath");
  4334.         }
  4335.         n_try = 0;
  4336.         keep_trying = TRUE;
  4337.         do {
  4338.             n_try++;
  4339.             tlon[n] = lon;
  4340.             tlat[n] = tlat[n-1] + dlat;
  4341.             geo_to_xy (tlon[n], tlat[n], &x1, &y1);
  4342.             jump = map_jump (x0, y0, x1, y1) || (y0 < project_info.ymin || y0 > project_info.ymax);
  4343.             if (!jump && (d = hypot (x1 - x0, y1 - y0)) > gmtdefs.line_step)
  4344.                 dlat *= 0.5;
  4345.             else if (!jump && d < min_gap)
  4346.                 dlat *= 2.0;
  4347.             else
  4348.                 keep_trying = FALSE;
  4349.         } while (keep_trying && n_try < 10);
  4350.         x0 = x1;    y0 = y1;
  4351.     }
  4352.     tlon[n] = lon;
  4353.     tlat[n] = lat2;
  4354.     n++;
  4355.     
  4356.     if (n != ny) {
  4357.         tlon = (double *) memory ((char *)tlon, n, sizeof (double), "lonpath");
  4358.         tlat = (double *) memory ((char *)tlat, n, sizeof (double), "lonpath");
  4359.     }
  4360.     
  4361.     *x = tlon;    *y = tlat;
  4362.     return (n);
  4363. }
  4364.  
  4365. int latpath (lat, lon1, lon2, x, y)
  4366. double lat, lon1, lon2;
  4367. double *x[], *y[]; {
  4368.     int nx, n = 0, n_try, keep_trying, jump, pos;
  4369.     double dlon, *tlon, *tlat, x0, x1, y0, y1, d;
  4370.     double min_gap;
  4371.     
  4372.     min_gap = 0.1 * gmtdefs.line_step;
  4373.     if ((nx = ceil (fabs (lon2 - lon1) / gmtdefs.dlon)) == 0) return (0);
  4374.  
  4375.     nx++;
  4376.     dlon = (lon2 - lon1) / nx;
  4377.     pos = (dlon > 0.0); 
  4378.     
  4379.     tlon = (double *) memory (CNULL, nx, sizeof (double), "latpath");
  4380.     tlat = (double *) memory (CNULL, nx, sizeof (double), "latpath");
  4381.     
  4382.     tlon[0] = lon1;
  4383.     tlat[0] = lat;
  4384.     geo_to_xy (tlon[0], tlat[0], &x0, &y0);
  4385.     while ((pos && tlon[n] < lon2) || (!pos & tlon[n] > lon2)) {
  4386.         n++;
  4387.         if (n == nx-1) {
  4388.             nx += GMT_CHUNK;
  4389.             tlon = (double *) memory ((char *)tlon, nx, sizeof (double), "latpath");
  4390.             tlat = (double *) memory ((char *)tlat, nx, sizeof (double), "latpath");
  4391.         }
  4392.         n_try = 0;
  4393.         keep_trying = TRUE;
  4394.         do {
  4395.             n_try++;
  4396.             tlat[n] = lat;
  4397.             tlon[n] = tlon[n-1] + dlon;
  4398.             geo_to_xy (tlon[n], tlat[n], &x1, &y1);
  4399.             jump = map_jump (x0, y0, x1, y1) || (y0 < project_info.ymin || y0 > project_info.ymax);
  4400.             if (!jump && (d = hypot (x1 - x0, y1 - y0)) > gmtdefs.line_step)
  4401.                 dlon *= 0.5;
  4402.             else if (!jump && d < min_gap)
  4403.                 dlon *= 2.0;
  4404.             else
  4405.                 keep_trying = FALSE;
  4406.         } while (keep_trying && n_try < 10);
  4407.         x0 = x1;    y0 = y1;
  4408.     }
  4409.     tlon[n] = lon2;
  4410.     tlat[n] = lat;
  4411.     n++;
  4412.     
  4413.     if (n != nx) {
  4414.         tlon = (double *) memory ((char *)tlon, n, sizeof (double), "latpath");
  4415.         tlat = (double *) memory ((char *)tlat, n, sizeof (double), "latpath");
  4416.     }
  4417.     
  4418.     *x = tlon;    *y = tlat;
  4419.     return (n);
  4420. }
  4421.  
  4422. /*  Routines to do with clipping */
  4423.  
  4424. int clip_to_map (lon, lat, np, x, y)
  4425. double lon[], lat[];
  4426. int np;
  4427. double *x[], *y[]; {
  4428.     /* This routine makes sure that all points are either inside or on the map boundary
  4429.      * and returns the number of points to be used for plotting (in x,y units) */
  4430.      
  4431.     int i, n, out = 0;
  4432.     double *xx, *yy;
  4433.     
  4434.     /* First check for trivial cases:  All points outside or all points inside */
  4435.     
  4436.     for (i = 0; i < np; i++)  {
  4437.         map_outside (lon[i], lat[i]);
  4438.         out += (abs (gmt_x_status_new) == 2 || abs (gmt_y_status_new) == 2);
  4439.     }
  4440.     if (out == 0) {        /* All points are inside map boundary */
  4441.         xx = (double *) memory (CNULL, np, sizeof (double), "clip_to_map");
  4442.         yy = (double *) memory (CNULL, np, sizeof (double), "clip_to_map");
  4443.         for (i = 0; i < np; i++) geo_to_xy (lon[i], lat[i], &xx[i], &yy[i]);
  4444.         *x = xx;    *y = yy;
  4445.         n = np;
  4446.     }
  4447.     else if (out == np)    /* All points are outside map boundary */
  4448.         n = 0;
  4449.     else 
  4450.         n = (*map_clip) (lon, lat, np, x, y);
  4451.     return (n);
  4452. }
  4453.  
  4454. int rect_clip (lon, lat, n, x, y)
  4455. double lon[], lat[];
  4456. double *x[], *y[];
  4457. int n; {
  4458.     int i, j = 0, k, nx, sides[2], n_alloc = GMT_CHUNK;
  4459.     double xlon[2], xlat[2], xc[2], yc[2], *xx, *yy;
  4460.     
  4461.     if (n == 0) return (0);
  4462.     
  4463.     xx = (double *) memory (CNULL, n_alloc, sizeof (double), "rect_clip");
  4464.     yy = (double *) memory (CNULL, n_alloc, sizeof (double), "rect_clip");
  4465.     map_outside (lon[0], lat[0]);
  4466.     geo_to_xy (lon[0], lat[0], &xx[0], &yy[0]);
  4467.     j += move_to_rect (xx, yy, j);    /* May add 2 points, << n_alloc */
  4468.     
  4469.     /* for (i = j = 1; i < n; i++) { */
  4470.     for (i = 1; i < n; i++) {
  4471.         map_outside (lon[i], lat[i]);
  4472.         if (break_through (lon[i-1], lat[i-1], lon[i], lat[i])) {
  4473.             nx = map_crossing (lon[i-1], lat[i-1], lon[i], lat[i], xlon, xlat, xc, yc, sides);
  4474.             for (k = 0; k < nx; k++) {
  4475.                 xx[j] = xc[k];
  4476.                 yy[j++] = yc[k];
  4477.                 if (j == (n_alloc-2)) {
  4478.                     n_alloc += GMT_CHUNK;
  4479.                     xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "rect_clip");
  4480.                     yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "rect_clip");
  4481.                 }
  4482.             }
  4483.         }
  4484.         geo_to_xy (lon[i], lat[i], &xx[j], &yy[j]);
  4485.         if (j == (n_alloc-2)) {
  4486.             n_alloc += GMT_CHUNK;
  4487.             xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "rect_clip");
  4488.             yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "rect_clip");
  4489.         }
  4490.         j += move_to_rect (xx, yy, j);    /* May add 2 points, which explains the n_alloc-2 stuff */
  4491.     }
  4492.     
  4493.     xx = (double *) memory ((char *)xx, j, sizeof (double), "rect_clip");
  4494.     yy = (double *) memory ((char *)yy, j, sizeof (double), "rect_clip");
  4495.     *x = xx;
  4496.     *y = yy;
  4497.     
  4498.     return (j);
  4499. }        
  4500.         
  4501. int wesn_clip (lon, lat, n, x, y)
  4502. double lon[], lat[];
  4503. double *x[], *y[];
  4504. int n; {
  4505.     int i, j = 0, k, nx, sides[2], n_alloc = GMT_CHUNK;
  4506.     double xlon[2], xlat[2], xc[2], yc[2], *xx, *yy;
  4507.     
  4508.     if (n == 0) return (0);
  4509.     
  4510.     xx = (double *) memory (CNULL, n_alloc, sizeof (double), "wesn_clip");
  4511.     yy = (double *) memory (CNULL, n_alloc, sizeof (double), "wesn_clip");
  4512.  
  4513.     map_outside (lon[0], lat[0]);
  4514.     j = move_to_wesn (xx, yy, lon[0], lat[0], 0);    /* May add 2 points, << n_alloc */
  4515.     
  4516.     for (i = 1; i < n; i++) {
  4517.         map_outside (lon[i], lat[i]);
  4518.         if (break_through (lon[i-1], lat[i-1], lon[i], lat[i])) {
  4519.             nx = map_crossing (lon[i-1], lat[i-1], lon[i], lat[i], xlon, xlat, xc, yc, sides);
  4520.             for (k = 0; k < nx; k++) {
  4521.                 xx[j] = xc[k];
  4522.                 yy[j++] = yc[k];
  4523.                 if (j == n_alloc) {
  4524.                     n_alloc += GMT_CHUNK;
  4525.                     xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "wesn_clip");
  4526.                     yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "wesn_clip");
  4527.                 }
  4528.             }
  4529.         }
  4530.         if (j == (n_alloc-2)) {
  4531.             n_alloc += GMT_CHUNK;
  4532.             xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "wesn_clip");
  4533.             yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "wesn_clip");
  4534.         }
  4535.         j += move_to_wesn (xx, yy, lon[i], lat[i], j);    /* May add 2 points, which explains the n_alloc-2 stuff */
  4536.     }
  4537.  
  4538.     xx = (double *) memory ((char *)xx, j, sizeof (double), "wesn_clip");
  4539.     yy = (double *) memory ((char *)yy, j, sizeof (double), "wesn_clip");
  4540.     *x = xx;
  4541.     *y = yy;
  4542.  
  4543.     return (j);
  4544. }        
  4545.         
  4546. int move_to_rect (x_edge, y_edge, j)
  4547. double x_edge[], y_edge[];
  4548. int j; {
  4549.     int n = 0;
  4550.     double xtmp, ytmp;
  4551.     
  4552.     /* May add 0, 1, or 2 points to path */
  4553.     
  4554.     if (gmt_x_status_new == 0 && gmt_y_status_new == 0) return (1);    /* Inside */
  4555.     
  4556.     if (j > 0 && gmt_x_status_new != gmt_x_status_old && gmt_y_status_new != gmt_y_status_old) {    /* Must include corner */
  4557.         xtmp = x_edge[j];    ytmp = y_edge[j];
  4558.         x_edge[j] = (MIN (gmt_x_status_new, gmt_x_status_old) < 0) ? project_info.xmin : project_info.xmax;
  4559.         y_edge[j] = (MIN (gmt_y_status_new, gmt_y_status_old) < 0) ? project_info.ymin : project_info.ymax;
  4560.         j++;
  4561.         x_edge[j] = xtmp;    y_edge[j] = ytmp;
  4562.         n = 1;
  4563.     }
  4564.     if (gmt_x_status_new != 0) x_edge[j] = (gmt_x_status_new < 0) ? project_info.xmin : project_info.xmax;
  4565.     if (gmt_y_status_new != 0) y_edge[j] = (gmt_y_status_new < 0) ? project_info.ymin : project_info.ymax;
  4566.     return (n + 1);
  4567. }
  4568.  
  4569. int move_to_wesn (x_edge, y_edge, lon, lat, j)
  4570. double x_edge[], y_edge[], lon, lat;
  4571. int j; {
  4572.     int n = 0;
  4573.     double xtmp, ytmp, lon_p, lat_p;
  4574.     
  4575.     /* May add 0, 1, or 2 points to path */
  4576.     
  4577.     if (j > 0 && gmt_x_status_new != gmt_x_status_old && gmt_y_status_new != gmt_y_status_old) {    /* Need corner */
  4578.         xtmp = x_edge[j];    ytmp = y_edge[j];
  4579.         lon_p = (MIN (gmt_x_status_new, gmt_x_status_old) < 0) ? project_info.w : project_info.e;
  4580.         lat_p = (MIN (gmt_y_status_new, gmt_y_status_old) < 0) ? project_info.s : project_info.n;
  4581.         geo_to_xy (lon_p, lat_p, &x_edge[j], &y_edge[j]);
  4582.         j++;
  4583.         x_edge[j] = xtmp;    y_edge[j] = ytmp;
  4584.         n = 1;
  4585.     }
  4586.     if (gmt_x_status_new != 0) lon = (gmt_x_status_new < 0) ? project_info.w : project_info.e;
  4587.     if (gmt_y_status_new != 0) lat = (gmt_y_status_new < 0) ? project_info.s : project_info.n;
  4588.     geo_to_xy (lon, lat, &x_edge[j], &y_edge[j]);
  4589.     return (n + 1);
  4590. }
  4591.  
  4592. int radial_clip (lon, lat, np, x, y)
  4593. double lon[], lat[];
  4594. int np;
  4595. double *x[], *y[]; {
  4596.     int n = 0, this, i, sides[2], n_alloc = GMT_CHUNK;
  4597.     double xlon[2], xlat[2], xc[2], yc[2], xr, yr, r, scale, x0, y0, *xx, *yy;
  4598.     
  4599.     if (np == 0) return (0);
  4600.     
  4601.     xx = (double *) memory (CNULL, n_alloc, sizeof (double), "radial_clip");
  4602.     yy = (double *) memory (CNULL, n_alloc, sizeof (double), "radial_clip");
  4603.     
  4604.     if (!map_outside (lon[0], lat[0])) {
  4605.         geo_to_xy (lon[0], lat[0], &xx[0], &yy[0]);
  4606.         n++;
  4607.     }
  4608.     for (i = 1; i < np; i++) {
  4609.         this = map_outside (lon[i], lat[i]);
  4610.         if (break_through (lon[i-1], lat[i-1], lon[i], lat[i])) {    /* Crossed map_boundary */
  4611.             map_crossing (lon[i-1], lat[i-1], lon[i], lat[i], xlon, xlat, xc, yc, sides);
  4612.             xx[n] = xc[0];    yy[n] = yc[0];
  4613.             n++;
  4614.             if (n == n_alloc) {
  4615.                 n_alloc += GMT_CHUNK;
  4616.                 xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "radial_clip");
  4617.                 yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "radial_clip");
  4618.             }
  4619.         }
  4620.         geo_to_xy (lon[i], lat[i], &xr, &yr);
  4621.         if (this) {    /* Project point onto perimeter */
  4622.             geo_to_xy (project_info.central_meridian, project_info.pole, &x0, &y0);
  4623.             xr -= x0;    yr -= y0;
  4624.             r = hypot (xr, yr);
  4625.             scale = project_info.r / r;
  4626.             xr *= scale;
  4627.             yr *= scale;
  4628.             xr += x0;    yr += y0;
  4629.         }
  4630.         xx[n] = xr;    yy[n] = yr;
  4631.         n++;
  4632.         if (n == n_alloc) {
  4633.             n_alloc += GMT_CHUNK;
  4634.             xx = (double *) memory ((char *)xx, n_alloc, sizeof (double), "radial_clip");
  4635.             yy = (double *) memory ((char *)yy, n_alloc, sizeof (double), "radial_clip");
  4636.         }
  4637.     }
  4638.     
  4639.     xx = (double *) memory ((char *)xx, n, sizeof (double), "radial_clip");
  4640.     yy = (double *) memory ((char *)yy, n, sizeof (double), "radial_clip");
  4641.     *x = xx;
  4642.     *y = yy;
  4643.  
  4644.     return (n);
  4645. }
  4646.  
  4647. int lon_inside (lon, w, e)
  4648. double lon, w, e; {
  4649.     
  4650.     while (lon < project_info.w) lon += 360.0;
  4651.     while (lon > project_info.e) lon -= 360.0;
  4652.     
  4653.     if (lon < w) return (FALSE);
  4654.     if (lon > e) return (FALSE);
  4655.     return (TRUE);
  4656. }
  4657.  
  4658. int geo_to_xy_line (lon, lat, n)
  4659. double lon[], lat[];
  4660. int n; {
  4661.     /* Traces the lon/lat array and returns x,y plus appropriate pen moves */
  4662.     int j, np, this, nx, sides[2], wrap = FALSE, ok;
  4663.     double xlon[2], xlat[2], xx[2], yy[2];
  4664.     double this_x, this_y, last_x, last_y, dummy[2];
  4665.     
  4666.     if (n > gmt_n_alloc) get_plot_array ();
  4667.     
  4668.     np = 0;
  4669.     geo_to_xy (lon[0], lat[0], &last_x, &last_y);
  4670.     if (!map_outside (lon[0], lat[0])) {
  4671.         gmt_x_plot[0] = last_x;     gmt_y_plot[0] = last_y;
  4672.         gmt_pen[np++] = 3;
  4673.     }
  4674.     for (j = 1; j < n; j++) {
  4675.         geo_to_xy (lon[j], lat[j], &this_x, &this_y);
  4676.         this = map_outside (lon[j], lat[j]);
  4677.         nx = 0;
  4678.         if (break_through (lon[j-1], lat[j-1], lon[j], lat[j]))    { /* Crossed map boundary */
  4679.             nx = map_crossing (lon[j-1], lat[j-1], lon[j], lat[j], xlon, xlat, xx, yy, sides);
  4680.             ok = ok_xovers (nx, last_x, this_x, sides, n);
  4681.         }
  4682.         if (gmt_world_map) wrap = wrap_around_check (dummy, last_x, last_y, this_x, this_y, xx, yy, sides, &nx);
  4683.         if (nx == 1) {
  4684.             gmt_x_plot[np] = xx[0];    gmt_y_plot[np] = yy[0];
  4685.             gmt_pen[np++] = pen_status ();
  4686.             if (np == gmt_n_alloc) get_plot_array ();
  4687.         }
  4688.         else if (nx == 2 && ok) {
  4689.             gmt_x_plot[np] = xx[0];    gmt_y_plot[np] = yy[0];
  4690.             gmt_pen[np++] = (wrap) ? 2 : 3;
  4691.             if (np == gmt_n_alloc) get_plot_array ();
  4692.             gmt_x_plot[np] = xx[1];    gmt_y_plot[np] = yy[1];
  4693.             gmt_pen[np++] = (wrap) ? 3 : 2;
  4694.             if (np == gmt_n_alloc) get_plot_array ();
  4695.         }
  4696.         if (!this) {
  4697.             gmt_x_plot[np] = this_x;     gmt_y_plot[np] = this_y;
  4698.             gmt_pen[np++] = 2;
  4699.             if (np == gmt_n_alloc) get_plot_array ();
  4700.         }
  4701.         last_x = this_x;    last_y = this_y;
  4702.     }
  4703.     return (np);
  4704. }    
  4705.  
  4706. int ok_xovers (nx, x0, x1, sides, n)
  4707. int nx;
  4708. double x0, x1;
  4709. int sides[], n; {
  4710.     if (!MAPPING) return (TRUE);    /* Data is not periodic*/
  4711.     if (gmt_world_map || nx < 2) return (TRUE);
  4712.     if ((sides[0] + sides[1]) == 2) return (TRUE);    /* Crossing in the n-s direction */
  4713.     if (fabs (fabs (x0 - x1) - gmt_map_width) < SMALL) return (TRUE);
  4714.     if ((sides[0] + sides[1]) != 4) return (TRUE);    /* Not Crossing in the e-w direction */
  4715.     return (FALSE);
  4716. }    
  4717.  
  4718. int compact_line (x, y, n, pen_flag, pen)
  4719. double x[], y[];
  4720. int n, pen[];
  4721. BOOLEAN pen_flag; {    /* TRUE if pen movements is present */
  4722.     /* compact_line will remove unnecessary points in paths */
  4723.     int i, j;
  4724.     double old_slope, new_slope, dx;
  4725.     char *flag;
  4726.     
  4727.     if (n < 3) return (n);
  4728.     flag = memory (CNULL, n, sizeof (char), "compact_line");
  4729.     
  4730.     old_slope = ( (dx = (x[1] - x[0])) == 0.0) ? copysign (MAXDOUBLE, y[1] - y[0]) : (y[1] - y[0]) / dx;
  4731.     
  4732.     for (i = 1; i < n-1; i++) {
  4733.         new_slope = ( (dx = (x[i+1] - x[i])) == 0.0) ? copysign (MAXDOUBLE, y[i+1] - y[i]) : (y[i+1] - y[i]) / dx;
  4734.         if (new_slope == old_slope && !(pen_flag && (pen[i]+pen[i+1]) > 4))
  4735.             flag[i] = 1;
  4736.         else
  4737.             old_slope = new_slope;
  4738.     }
  4739.     
  4740.     for (i = j = 1; i < n; i++) {    /* i = 1 since first point must be included */
  4741.         if (flag[i] == 0) {
  4742.             x[j] = x[i];
  4743.             y[j] = y[i];
  4744.             if (pen_flag) pen[j] = pen[i];
  4745.             j++;
  4746.         }
  4747.     }
  4748.     free (flag);
  4749.     
  4750.     return (j);
  4751. }
  4752.  
  4753. /* Routines to transform grdfiles to/from map projections */
  4754.  
  4755. int grdproject_init (head, x_inc, y_inc, nx, ny, dpi, offset)
  4756. struct GRD_HEADER *head;
  4757. double x_inc, y_inc;
  4758. int nx, ny, dpi, offset; {
  4759.     int one;
  4760.     
  4761.     one = (offset) ? 0 : 1;
  4762.     
  4763.     if (x_inc > 0.0 && y_inc > 0.0) {
  4764.         head->nx = rint ((head->x_max - head->x_min) / x_inc) + one;
  4765.         head->ny = rint ((head->y_max - head->y_min) / y_inc) + one;
  4766.         head->x_inc = (head->x_max - head->x_min) / (head->nx - one);
  4767.         head->y_inc = (head->y_max - head->y_min) / (head->ny - one);
  4768.     }
  4769.     else if (nx > 0 && ny > 0) {
  4770.         head->nx = nx;    head->ny = ny;
  4771.         head->x_inc = (head->x_max - head->x_min) / (head->nx - one);
  4772.         head->y_inc = (head->y_max - head->y_min) / (head->ny - one);
  4773.     }
  4774.     else if (dpi > 0) {
  4775.         head->nx = rint ((head->x_max - head->x_min) * dpi) + one;
  4776.         head->ny = rint ((head->y_max - head->y_min) * dpi) + one;
  4777.         head->x_inc = (head->x_max - head->x_min) / (head->nx - one);
  4778.         head->y_inc = (head->y_max - head->y_min) / (head->ny- one);
  4779.     }
  4780.     else {
  4781.         fprintf (stderr, "grdproject_init: Necessary arguments not set\n");
  4782.         exit (-1);
  4783.     }
  4784.     head->node_offset = offset;
  4785.     
  4786.     if (gmtdefs.verbose) fprintf (stderr, "grdproject: New size (nx,ny) %d by %d\n", head->nx, head->ny);
  4787. }
  4788.  
  4789. int grd_forward (geo, g_head, rect, r_head, max_radius, center)
  4790. float geo[], rect[];
  4791. struct GRD_HEADER *g_head, *r_head;
  4792. double max_radius;
  4793. BOOLEAN center; {    /* Forward projection from geographical to rectangular grid */
  4794.     int i, j, k, ij, ii, jj, i_r, j_r, nm, di, dj, not_used = 0;
  4795.     float *weight_sum;
  4796.     double dx, dy, dr, x_0, y_0, x, y, lon, lat, delta, weight;
  4797.     double dx2, dy2, xinc2, yinc2, i_max_3r;
  4798.     
  4799.     if (project_info.projection == MERCATOR && g_head->nx == r_head->nx) {
  4800.         merc_forward (geo, g_head, rect, r_head, max_radius, center);
  4801.         return;
  4802.     }
  4803.     
  4804.     nm = r_head->nx * r_head->ny;
  4805.     weight_sum = (float *) memory (CNULL, nm, sizeof (float), "grdproject");
  4806.         
  4807.     if (max_radius == 0.0) {    /* Make sensible default for search radius */
  4808.         dx = 2.0 * (r_head->x_max - r_head->x_min) / (g_head->nx);
  4809.         dy = 2.0 * (r_head->y_max - r_head->y_min) / (g_head->ny);
  4810.         if (dx < r_head->x_inc) dx = r_head->x_inc;
  4811.         if (dy < r_head->y_inc) dy = r_head->y_inc;
  4812.         max_radius = MAX (dx, dy);
  4813.         if (gmtdefs.verbose) fprintf (stderr, "grd_forward: Use max-radius = %lg\n", max_radius);
  4814.     }
  4815.     di = ceil (max_radius / r_head->x_inc);
  4816.     dj = ceil (max_radius / r_head->y_inc);
  4817.     
  4818.     dx2 = 0.5 * g_head->x_inc;    dy2 = 0.5 * g_head->y_inc;
  4819.     xinc2 = 0.5 * r_head->x_inc;    yinc2 = 0.5 * r_head->y_inc;
  4820.     i_max_3r = 3.0 / max_radius;
  4821.     
  4822.     for (j = ij = 0; j < g_head->ny; j++) {
  4823.         lat = g_head->y_max - j * g_head->y_inc;
  4824.         if (g_head->node_offset) lat -= dy2;
  4825.         if (project_info.projection == MERCATOR && fabs (lat) == 90.0) lat = copysign (89.99, lat);
  4826.         for (i = 0; i < g_head->nx; i++, ij++) {
  4827.             if (bad_float ((double)geo[ij])) continue;
  4828.                 
  4829.             lon = g_head->x_min + i * g_head->x_inc;
  4830.             if (g_head->node_offset) lon += dx2;
  4831.             if (map_outside (lon, lat)) continue;
  4832.             geo_to_xy (lon, lat, &x_0, &y_0);
  4833.             if (center) {
  4834.                 x_0 -= project_info.x0;
  4835.                 y_0 -= project_info.y0;
  4836.             }
  4837.             if (r_head->node_offset) {
  4838.                 ii = (x_0 == r_head->x_max) ? r_head->nx - 1 : floor ( (x_0 - r_head->x_min) / r_head->x_inc);
  4839.                 jj = (y_0 == r_head->y_min) ? r_head->ny - 1 : floor ( (r_head->y_max - y_0) / r_head->y_inc);
  4840.             }
  4841.             else {
  4842.                 ii = rint ( (x_0 - r_head->x_min) / r_head->x_inc);
  4843.                 jj = rint ( (r_head->y_max - y_0) / r_head->y_inc);
  4844.             }
  4845.                 
  4846.             for (j_r = jj - dj; j_r <= (jj + dj); j_r++) {
  4847.                 if (j_r < 0 || j_r >= r_head->ny) continue;
  4848.                 for (i_r = ii - di; i_r <= (ii + di); i_r++) {
  4849.                     if (i_r < 0 || i_r >= r_head->nx) continue;
  4850.                     k = j_r * r_head->nx + i_r;
  4851.                     x = r_head->x_min + i_r * r_head->x_inc;
  4852.                     y = r_head->y_max - j_r * r_head->y_inc;
  4853.                     if (r_head->node_offset) {
  4854.                         x += xinc2;
  4855.                         y -= yinc2;
  4856.                     }
  4857.                     dr = hypot (x - x_0, y - y_0);
  4858.                     if (dr > max_radius) continue;
  4859.                     delta = dr * i_max_3r;
  4860.                     weight = 1.0 / (1.0 + delta * delta);
  4861.                     rect[k] += weight * geo[ij];
  4862.                     weight_sum[k] += weight;
  4863.                 }
  4864.             }
  4865.         }
  4866.     }
  4867.     r_head->z_min = MAXDOUBLE;    r_head->z_max = -MAXDOUBLE;
  4868.     for (k = 0; k < nm; k++) {
  4869.         if (weight_sum[k] > 0.0) {
  4870.             rect[k] /= weight_sum[k];
  4871.             r_head->z_min = MIN (r_head->z_min, rect[k]);
  4872.             r_head->z_max = MAX (r_head->z_max, rect[k]);
  4873.         }
  4874.         else {
  4875.             not_used++;
  4876.             rect[k] = gmt_NaN;
  4877.         }
  4878.     }
  4879.         
  4880.     free ((char *)weight_sum);
  4881.     
  4882.     if (not_used) fprintf (stderr, "grd_forward: some projected nodes not loaded (%d)\n", not_used);
  4883. }
  4884.  
  4885. int grd_inverse (geo, g_head, rect, r_head, max_radius, center)
  4886. float geo[], rect[];
  4887. struct GRD_HEADER *g_head, *r_head;
  4888. double max_radius;
  4889. BOOLEAN center; {    /* Transforming from rectangular projection to geographical */
  4890.     int i, j, k, ij, ii, jj, i_r, j_r, nm, di, dj, not_used = 0;
  4891.     float *weight_sum;
  4892.     double dx, dy, dr, lat_0, lon_0, x_0, y_0, lon, lat, x, y, delta, weight;
  4893.     double dx2, dy2, xinc2, yinc2, i_max_3r;
  4894.     
  4895.     if (project_info.projection == MERCATOR && g_head->nx == r_head->nx) {
  4896.         merc_inverse (geo, g_head, rect, r_head, max_radius, center);
  4897.         return;
  4898.     }
  4899.     
  4900.     nm = g_head->nx * g_head->ny;
  4901.         
  4902.     weight_sum = (float *) memory (CNULL, nm, sizeof (float), "grdproject");
  4903.     
  4904.     if (max_radius == 0.0) {    /* Make sensible default for search radius */
  4905.         dx = 2.0 * (r_head->x_max - r_head->x_min) / (g_head->nx);
  4906.         dy = 2.0 * (r_head->y_max - r_head->y_min) / (g_head->ny);
  4907.         if (dx < r_head->x_inc) dx = r_head->x_inc;
  4908.         if (dy < r_head->y_inc) dy = r_head->y_inc;
  4909.         max_radius = MAX (dx, dy);
  4910.         if (gmtdefs.verbose) fprintf (stderr, "grd_inverse: Use max-radius = %lg\n", max_radius);
  4911.     }
  4912.     di = ceil (max_radius / r_head->x_inc);
  4913.     dj = ceil (max_radius / r_head->y_inc);
  4914.         
  4915.     dx2 = 0.5 * g_head->x_inc;    dy2 = 0.5 * g_head->y_inc;
  4916.     xinc2 = 0.5 * r_head->x_inc;    yinc2 = 0.5 * r_head->y_inc;
  4917.     i_max_3r = 3.0 / max_radius;
  4918.     
  4919.     for (j = ij = 0; j < r_head->ny; j++) {
  4920.         y_0 = r_head->y_max - j * r_head->y_inc;
  4921.         if (r_head->node_offset) y_0 -= yinc2;
  4922.         if (center) y_0 += project_info.y0;
  4923.         for (i = 0; i < r_head->nx; i++, ij++) {
  4924.             if (bad_float ((double)rect[ij])) continue;
  4925.                 
  4926.             x_0 = r_head->x_min + i * r_head->x_inc;
  4927.             if (r_head->node_offset) x_0 += xinc2;
  4928.             if (center) x_0 += project_info.x0;
  4929.             xy_to_geo (&lon_0, &lat_0, x_0, y_0);
  4930.             if (g_head->node_offset) {
  4931.                 ii = (lon_0 == g_head->x_max) ? g_head->nx - 1 : floor ( (lon_0 - g_head->x_min) / g_head->x_inc);
  4932.                 jj = (lat_0 == g_head->y_min) ? g_head->ny - 1 : floor ( (g_head->y_max - lat_0) / g_head->y_inc);
  4933.             }
  4934.             else {
  4935.                 ii = rint ( (lon_0 - g_head->x_min) / g_head->x_inc);
  4936.                 jj = rint ( (g_head->y_max - lat_0) / g_head->y_inc);
  4937.             }
  4938.                 
  4939.             for (j_r = jj - dj; j_r <= (jj + dj); j_r++) {
  4940.                 if (j_r < 0 || j_r >= g_head->ny) continue;
  4941.                 for (i_r = ii - di; i_r <= (ii + di); i_r++) {
  4942.                     if (i_r < 0 || i_r >= g_head->nx) continue;
  4943.                     k = j_r * g_head->nx + i_r;
  4944.                     lon = g_head->x_min + i_r * g_head->x_inc;
  4945.                     lat = g_head->y_max - j_r * g_head->y_inc;
  4946.                     if (g_head->node_offset) {
  4947.                         lon += dx2;
  4948.                         lat -= dy2;
  4949.                     }
  4950.                     geo_to_xy (lon, lat, &x, &y);
  4951.                     dr = hypot (x - x_0, y - y_0);
  4952.                     if (dr > max_radius) continue;
  4953.                     delta = dr * i_max_3r;
  4954.                     weight = 1.0 / (1.0 + delta * delta);
  4955.                     geo[k] += weight * rect[ij];
  4956.                     weight_sum[k] += weight;
  4957.                 }
  4958.             }
  4959.         }
  4960.     }
  4961.     g_head->z_min = MAXDOUBLE;    g_head->z_max = -MAXDOUBLE;
  4962.     for (k = 0; k < nm; k++) {    /* Compute weighted average */
  4963.         if (weight_sum[k] > 0.0) {
  4964.             geo[k] /= weight_sum[k];
  4965.             g_head->z_min = MIN (g_head->z_min, geo[k]);
  4966.             g_head->z_max = MAX (g_head->z_max, geo[k]);
  4967.         }
  4968.         else {
  4969.             not_used++;
  4970.             geo[k] = gmt_NaN;
  4971.         }
  4972.     }
  4973.     
  4974.     free ((char *)weight_sum);
  4975.     
  4976.     if (not_used) fprintf (stderr, "grdproject: some geographical nodes not loaded (%d)\n", not_used);
  4977. }
  4978.  
  4979. int merc_forward (geo, g_head, rect, r_head, max_radius, center)
  4980. float geo[], rect[];
  4981. struct GRD_HEADER *g_head, *r_head;
  4982. double max_radius;    /* Here max_radius is not used */
  4983. BOOLEAN center; {    /* Forward projection from geographical to mercator grid */
  4984.     int i, j, g_off, r_off;
  4985.     double dy, y, dummy, *lat_in, *lat_out, *hold, *value;
  4986.     
  4987.  
  4988.     lat_in = (double *) memory (CNULL, g_head->ny, sizeof (double), "merc_forward");
  4989.     lat_out = (double *) memory (CNULL, r_head->ny, sizeof (double), "merc_forward");
  4990.     value = (double *) memory (CNULL, r_head->ny, sizeof (double), "merc_forward");
  4991.     hold = (double *) memory (CNULL, g_head->ny, sizeof (double), "merc_forward");
  4992.     
  4993.     dy = (g_head->node_offset) ? 0.5 * g_head->y_inc : 0.0;
  4994.     for (j = 0; j < g_head->ny; j++) lat_in[j] = g_head->y_min + j * g_head->y_inc + dy;
  4995.     
  4996.     dy = (r_head->node_offset) ? 0.5 * r_head->y_inc : 0.0;
  4997.  
  4998.     for (j = 0; j < r_head->ny; j++) { /* Construct merc y-grid */
  4999.         y = r_head->y_min + j * r_head->y_inc + dy;
  5000.         if (center) y -= project_info.y0;
  5001.         xy_to_geo (&dummy, &lat_out[j], 0.0, y);
  5002.     }
  5003.     
  5004.     /* Make sure new nodes outside border are set to be on border (pixel grid only) */
  5005.     
  5006.     j = 0;
  5007.     while (j < r_head->ny && (lat_out[j] - lat_in[0]) < 0.0) lat_out[j++] = lat_in[0];
  5008.     j = r_head->ny-1;
  5009.     while (j >= 0 && (lat_out[j] - lat_in[g_head->ny-1]) > 0.0) lat_out[j--] = lat_in[g_head->ny-1];
  5010.     g_off = g_head->ny - 1;
  5011.     r_off = r_head->ny - 1;
  5012.     for (i = 0; i < r_head->nx; i++) {    /* r_head->nx must == g_head->nx */
  5013.         for (j = 0; j < g_head->ny; j++) hold[g_off-j] = geo[j*g_head->nx+i];    /* Copy and reverse a column */
  5014.         intpol (lat_in, hold, g_head->ny, r_head->ny, lat_out, value, gmtdefs.interpolant);
  5015.         for (j = 0; j < r_head->ny; j++) rect[j*r_head->nx+i] = value[r_off-j];    /* Reverse and load new column */
  5016.     }
  5017.     free ((char *)lat_in);
  5018.     free ((char *)lat_out);
  5019.     free ((char *)value);
  5020.     free ((char *)hold);
  5021. }
  5022.  
  5023. int merc_inverse (geo, g_head, rect, r_head, max_radius, center)
  5024. float geo[], rect[];
  5025. struct GRD_HEADER *g_head, *r_head;
  5026. double max_radius;    /* Here max_radius is not used */
  5027. BOOLEAN center; {    /* Inverse projection from mercator to geographical grid */
  5028.     int i, j, g_off, r_off;
  5029.     double dy, y, dummy, *lat_in, *lat_out, *tmp, *val;
  5030.     
  5031.     lat_in = (double *) memory (CNULL, g_head->ny, sizeof (double), "merc_forward");
  5032.     lat_out = (double *) memory (CNULL, r_head->ny, sizeof (double), "merc_forward");
  5033.     tmp = (double *) memory (CNULL, g_head->ny, sizeof (double), "merc_forward");
  5034.     val = (double *) memory (CNULL, r_head->ny, sizeof (double), "merc_forward");
  5035.     
  5036.     dy = (g_head->node_offset) ? 0.5 * g_head->y_inc : 0.0;
  5037.     for (j = 0; j < g_head->ny; j++) lat_in[j] = g_head->y_min + j * g_head->y_inc + dy;
  5038.     
  5039.     dy = (r_head->node_offset) ? 0.5 * r_head->y_inc : 0.0;
  5040.     for (j = 0; j < r_head->ny; j++) { /* Construct merc y-grid */
  5041.         y = r_head->y_min + j * r_head->y_inc + dy;
  5042.         if (center) y -= project_info.y0;
  5043.         xy_to_geo (&dummy, &lat_out[j], 0.0, y);
  5044.     }
  5045.     
  5046.     /* Make sure new nodes outside border are set to be on border (pixel grid only) */
  5047.     
  5048.     j = 0;
  5049.     while (j < r_head->ny && (lat_in[j] - lat_out[0]) < 0.0) lat_in[j++] = lat_out[0];
  5050.     j = r_head->ny-1;
  5051.     while (j >= 0 && (lat_in[j] - lat_out[g_head->ny-1]) > 0.0) lat_in[j--] = lat_out[g_head->ny-1];
  5052.     
  5053.     g_off = g_head->ny - 1;
  5054.     r_off = r_head->ny - 1;
  5055.     for (i = 0; i < g_head->nx; i++) {    /* r_head->nx must == g_head->nx */
  5056.         for (j = 0; j < r_head->ny; j++) val[r_off-j] = rect[j*r_head->nx+i];    /* Copy and reverse a column */
  5057.         intpol (lat_out, val, r_head->ny, g_head->ny, lat_in, tmp, gmtdefs.interpolant);
  5058.         for (j = 0; j < g_head->ny; j++) geo[j*g_head->nx+i] = tmp[g_off-j];    /* Copy and reverse a column */
  5059.     }
  5060.     free ((char *)lat_in);
  5061.     free ((char *)lat_out);
  5062.     free ((char *)val);
  5063.     free ((char *)tmp);
  5064. }
  5065.  
  5066. int two_d_to_three_d (x, y, n)
  5067. double x[], y[];
  5068. int n; {
  5069.     int i;
  5070.     
  5071.     /* Convert from two-D to three-D coordinates */
  5072.     
  5073.     for (i = 0; i < n; i++) xy_do_z_to_xy (x[i], y[i], project_info.z_level, &x[i], &y[i]);
  5074. }
  5075.  
  5076. int azim_2_angle (lon, lat, c, azim, angle)
  5077. double lon, lat, c, azim;    /* All variables in degrees */
  5078. double *angle; {
  5079.     double lon1, lat1, x0, x1, y0, y1, sinc, cosc, sinaz, cosaz, sinl, cosl;
  5080.     
  5081.     if (project_info.projection < MERCATOR) {    /* Trivial case */
  5082.         *angle = 90.0 - azim;
  5083.         return;
  5084.     }
  5085.  
  5086.     /* Find second point c spherical degrees away in the azim direction */
  5087.     
  5088.     geo_to_xy (lon, lat, &x0, &y0);
  5089.  
  5090.     azim  *= D2R;
  5091.     sinaz = sin (azim);
  5092.     cosaz = cos (azim);
  5093.     c   *= D2R;
  5094.     lat *= D2R;
  5095.     sinc = sin (c);
  5096.     cosc = cos (c);
  5097.     sinl = sin (lat);
  5098.     cosl = cos (lat);
  5099.     
  5100.     lon1 = lon + R2D * atan (sinc * sinaz / (cosl * cosc - sinl * sinc * cosaz));
  5101.     lat1 = R2D * d_asin (sinl * cosc + cosl * sinc * cosaz);
  5102.  
  5103.     /* Convert to x,y and get angle */
  5104.     
  5105.     geo_to_xy (lon1, lat1, &x1, &y1);
  5106.     
  5107.     *angle = d_atan2 (y1 - y0, x1 - x0) * R2D;
  5108. }
  5109.  
  5110. int gmt_check_R_J (clon)    /* Make sure -R and -J agree for global plots; J given priority */
  5111. double *clon; {
  5112.     double lon0;
  5113.     
  5114.     lon0 = 0.5 * (project_info.w + project_info.e);
  5115.     if (gmt_world_map && lon0 != *clon) {
  5116.         project_info.w = *clon - 180.0;
  5117.         project_info.e = *clon + 180.0;
  5118.         fprintf (stderr, "%s: GMT Warning: Central meridian set with -J (%lg) implies -R%lg/%lg/%lg/%lg\n",
  5119.             gmt_program, *clon, project_info.w, project_info.e, project_info.s, project_info.n);
  5120.     }
  5121.     else if (!gmt_world_map && !(project_info.w <= *clon && *clon <= project_info.e)) {    /* Must reset meridian */
  5122.         *clon = lon0;
  5123.         fprintf (stderr, "%s: GMT Warning: Central meridian outside region, reset to %lg\n", gmt_program, lon0);
  5124.     }    
  5125. }
  5126.  
  5127. int gmt_set_spherical () {    /* Force spherical solution */
  5128.     gmtdefs.ellipsoid = N_ELLIPSOIDS - 1;    /* Use equatorial radius */
  5129.     EQ_RAD = gmtdefs.ellipse[gmtdefs.ellipsoid].eq_radius;
  5130.     M_PR_DEG = PI_2 * EQ_RAD / 360.0;
  5131.     ECC = ECC2 = ECC4 = ECC6 = 0.0;
  5132.     if (gmtdefs.verbose) fprintf (stderr, "%s: GMT Warning: Spherical approximation used!\n", gmt_program);
  5133. }
  5134.  
  5135. int map_setinfo (xmin, xmax, ymin, ymax, scl)
  5136. double xmin, xmax, ymin, ymax, scl; {    /* Set [and rescale] parameters */
  5137.     double factor;
  5138.      
  5139.     if (project_info.gave_map_width) {    /* Must rescale */
  5140.         factor = scl / ((xmax - xmin) * project_info.x_scale);
  5141.         project_info.x_scale *= factor;
  5142.         project_info.y_scale *= factor;
  5143.     }
  5144.     map_setxy (xmin, xmax, ymin, ymax);
  5145. }
  5146.  
  5147. int map_setxy (xmin, xmax, ymin, ymax)
  5148. double xmin, xmax, ymin, ymax; {    /* Set x/y parameters */
  5149.      
  5150.     project_info.xmax = (xmax - xmin) * project_info.x_scale;
  5151.     project_info.ymax = (ymax - ymin) * project_info.y_scale;
  5152.     project_info.x0 = -xmin * project_info.x_scale;
  5153.     project_info.y0 = -ymin * project_info.y_scale;
  5154. }
  5155.  
  5156. int map_clip_path (x, y, donut)
  5157. double *x[], *y[];
  5158. BOOLEAN *donut; {
  5159.     /* This function returns a clip path corresponding to the
  5160.      * extent of the map.
  5161.      */
  5162.      
  5163.     double *work_x, *work_y, angle, da, r0;
  5164.     int i, j, np;
  5165.     
  5166.     *donut = FALSE;
  5167.     
  5168.     if (!project_info.region)    /* Rectangular map boundary */
  5169.         np = 4;
  5170.     else {
  5171.         switch (project_info.projection) {
  5172.             case LINEAR:
  5173.             case MERCATOR:
  5174.             case CYL_EQ:
  5175.             case CYL_EQDIST:
  5176.             case OBLIQUE_MERC:
  5177.                 np = 4;
  5178.                 break;
  5179.             case POLAR:
  5180.                 *donut = (project_info.s > 0.0 && fabs (project_info.w - project_info.e) == 360.0);
  5181.                 np = gmtdefs.n_lon_nodes + 1;
  5182.                 if (project_info.s > 0.0) np *= 2; 
  5183.                 break;
  5184.             case STEREO:
  5185.             case LAMBERT:
  5186.             case LAMB_AZ_EQ:
  5187.             case ORTHO:
  5188.             case AZ_EQDIST:
  5189.             case ALBERS:
  5190.                 np = 2 * gmtdefs.n_lon_nodes + 2;
  5191.                 break;
  5192.             case MOLLWEIDE:
  5193.             case SINUSOIDAL:
  5194.             case ROBINSON:
  5195.                 np = 2 * gmtdefs.n_lat_nodes + 2;
  5196.                 break;
  5197.             case WINKEL:
  5198.             case HAMMER:
  5199.             case ECKERT:
  5200.                 np = 2 * gmtdefs.n_lat_nodes + 2;
  5201.                 if (project_info.s != -90.0) np += gmtdefs.n_lon_nodes - 1;
  5202.                 if (project_info.n != 90.0) np += gmtdefs.n_lon_nodes - 1;
  5203.                 break;
  5204.             case TM:
  5205.             case UTM:
  5206.             case CASSINI:
  5207.                 np = 2 * (gmtdefs.n_lon_nodes + gmtdefs.n_lat_nodes);
  5208.                 break;
  5209.         }
  5210.     }
  5211.     
  5212.     work_x = (double *)memory (CNULL, np, sizeof (double), "map_clip_on");
  5213.     work_y = (double *)memory (CNULL, np, sizeof (double), "map_clip_on");
  5214.     
  5215.     if (!project_info.region) {
  5216.         work_x[0] = work_x[3] = project_info.xmin;    work_y[0] = work_y[1] = project_info.ymin;
  5217.         work_x[1] = work_x[2] = project_info.xmax;    work_y[2] = work_y[3] = project_info.ymax;
  5218.     
  5219.     }
  5220.     else {
  5221.         switch (project_info.projection) {    /* Fill in clip path */
  5222.             case LINEAR:
  5223.             case MERCATOR:
  5224.             case CYL_EQ:
  5225.             case CYL_EQDIST:
  5226.             case OBLIQUE_MERC:
  5227.                 work_x[0] = work_x[3] = project_info.xmin;    work_y[0] = work_y[1] = project_info.ymin;
  5228.                 work_x[1] = work_x[2] = project_info.xmax;    work_y[2] = work_y[3] = project_info.ymax;
  5229.                 break;
  5230.             case LAMBERT:
  5231.             case ALBERS:
  5232.                 for (i = j = 0; i <= gmtdefs.n_lon_nodes; i++, j++)
  5233.                     geo_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, &work_x[j], &work_y[j]);
  5234.                 for (i = 0; i <= gmtdefs.n_lon_nodes; i++, j++)
  5235.                     geo_to_xy (project_info.e - i * gmtdefs.dlon, project_info.n, &work_x[j], &work_y[j]);
  5236.                 break;
  5237.             case TM:
  5238.             case UTM:
  5239.             case CASSINI:
  5240.                 for (i = j = 0; i < gmtdefs.n_lon_nodes; i++, j++)    /* South */
  5241.                     geo_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, &work_x[j], &work_y[j]);
  5242.                 for (i = 0; i < gmtdefs.n_lat_nodes; j++, i++)    /* East */
  5243.                     geo_to_xy (project_info.e, project_info.s + i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5244.                 for (i = 0; i < gmtdefs.n_lon_nodes; i++, j++)    /* North */
  5245.                     geo_to_xy (project_info.e - i * gmtdefs.dlon, project_info.n, &work_x[j], &work_y[j]);
  5246.                 for (i = 0; i < gmtdefs.n_lat_nodes; j++, i++)    /* West */
  5247.                     geo_to_xy (project_info.w, project_info.n - i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5248.                 break;
  5249.             case POLAR:
  5250.                 r0 = project_info.r * project_info.s / project_info.n;
  5251.                 if (*donut) {
  5252.                     np /= 2;
  5253.                     da = 2 * M_PI / np;
  5254.                     for (i = 0, j = 2*np-1; i < np; i++, j--) {    /* Draw outer clippath */
  5255.                         angle = i * da;
  5256.                         work_x[i] = project_info.r * (1.0 + cos (angle));
  5257.                         work_y[i] = project_info.r * (1.0 + sin (angle));
  5258.                         /* Do inner clippath and put it at end of array */
  5259.                         work_x[j] = project_info.r + r0 * cos (angle);
  5260.                         work_y[j] = project_info.r + r0 * sin (angle);
  5261.                     }
  5262.                 }
  5263.                 else {
  5264.                     da = fabs (project_info.e - project_info.w) / (gmtdefs.n_lon_nodes - 1);
  5265.                     for (i = j = 0; i <= gmtdefs.n_lon_nodes; i++, j++)    /* Draw outer clippath */
  5266.                         geo_to_xy (project_info.w + i * da, project_info.n, &work_x[j], &work_y[j]);
  5267.                     for (i = gmtdefs.n_lon_nodes; project_info.s > 0.0 && i >= 0; i--, j++)    /* Draw inner clippath */
  5268.                         geo_to_xy (project_info.w + i * da, project_info.s, &work_x[j], &work_y[j]);
  5269.                 }
  5270.                 break;
  5271.             case LAMB_AZ_EQ:
  5272.             case ORTHO:
  5273.             case AZ_EQDIST:
  5274.                 da = 2.0 * M_PI / np;
  5275.                 for (i = 0; i < np; i++) {
  5276.                     angle = i * da;
  5277.                     work_x[i] = project_info.r * (1.0 + cos (angle));
  5278.                     work_y[i] = project_info.r * (1.0 + sin (angle));
  5279.                 }
  5280.                 break;
  5281.             case STEREO:
  5282.                 if (project_info.polar) {
  5283.                     for (i = j = 0; i <= gmtdefs.n_lon_nodes; i++, j++)
  5284.                         geo_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, &work_x[j], &work_y[j]);
  5285.                     for (i = 0; i <= gmtdefs.n_lon_nodes; i++, j++)
  5286.                         geo_to_xy (project_info.e - i * gmtdefs.dlon, project_info.n, &work_x[j], &work_y[j]);
  5287.                 }
  5288.                 else {
  5289.                     da = 2.0 * M_PI / np;
  5290.                     for (i = 0; i < np; i++) {
  5291.                         angle = i * da;
  5292.                         work_x[i] = project_info.r * (1.0 + cos (angle));
  5293.                         work_y[i] = project_info.r * (1.0 + sin (angle));
  5294.                     }
  5295.                 }
  5296.                 break;
  5297.             case MOLLWEIDE:
  5298.             case SINUSOIDAL:
  5299.             case ROBINSON:
  5300.                 for (i = j = 0; i <= gmtdefs.n_lat_nodes; i++, j++)    /* Right */
  5301.                     geo_to_xy (project_info.e, project_info.s + i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5302.                 for (i = gmtdefs.n_lat_nodes; i >= 0; j++, i--)    /* Left */
  5303.                     geo_to_xy (project_info.w, project_info.s + i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5304.                 break;
  5305.             case HAMMER:
  5306.             case WINKEL:
  5307.             case ECKERT:
  5308.                 for (i = j = 0; i <= gmtdefs.n_lat_nodes; i++, j++)    /* Right */
  5309.                     geo_to_xy (project_info.e, project_info.s + i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5310.                 for (i = 1; project_info.n != 90.0 && i < gmtdefs.n_lon_nodes; i++, j++)
  5311.                     geo_to_xy (project_info.e - i * gmtdefs.dlon, project_info.n, &work_x[j], &work_y[j]);
  5312.                 for (i = gmtdefs.n_lat_nodes; i >= 0; j++, i--)    /* Left */
  5313.                     geo_to_xy (project_info.w, project_info.s + i * gmtdefs.dlat, &work_x[j], &work_y[j]);
  5314.                 for (i = 1; project_info.s != -90.0 && i < gmtdefs.n_lon_nodes; i++, j++)
  5315.                     geo_to_xy (project_info.w + i * gmtdefs.dlon, project_info.s, &work_x[j], &work_y[j]);
  5316.                 break;
  5317.         }
  5318.     }
  5319.     
  5320.     if (!(*donut)) np = compact_line (work_x, work_y, np, FALSE, 0);
  5321.     if (project_info.three_D) two_d_to_three_d (work_x, work_y, np);
  5322.     
  5323.     *x = work_x;
  5324.     *y = work_y;
  5325.     
  5326.     return (np);
  5327. }
  5328.  
  5329.