Beispiel #1
0
long Convert_UTM_To_OSSIM_MGRS (long Zone,
                          char Hemisphere,
                          double Easting,
                          double Northing,
                          long Precision,
                          char* OSSIM_MGRS)
/*
 * The function Convert_UTM_To_OSSIM_MGRS converts UTM (zone, easting, and
 * northing) coordinates to an OSSIM_MGRS coordinate string, according to the 
 * current ellipsoid parameters.  If any errors occur, the error code(s) 
 * are returned by the  function, otherwise OSSIM_MGRS_NO_ERROR is returned.
 *
 *    Zone       : UTM zone                         (input)
 *    Hemisphere : North or South hemisphere        (input)
 *    Easting    : Easting (X) in meters            (input)
 *    Northing   : Northing (Y) in meters           (input)
 *    Precision  : Precision level of OSSIM_MGRS string   (input)
 *    OSSIM_MGRS       : OSSIM_MGRS coordinate string           (output)
 */
{ /* Convert_UTM_To_OSSIM_MGRS */
  long error_code = OSSIM_MGRS_NO_ERROR;
  long temp_error = OSSIM_MGRS_NO_ERROR;
  long Letters[OSSIM_MGRS_LETTERS]; /* Number location of 3 letters in alphabet   */
  double Latitude;           /* Latitude of UTM point */
  double Longitude;          /* Longitude of UTM point */
  double divisor;
  if ((Zone < 1) || (Zone > 60))
    error_code |= OSSIM_MGRS_ZONE_ERROR;
  if ((Hemisphere != 'S') && (Hemisphere != 'N'))
    error_code |= OSSIM_MGRS_HEMISPHERE_ERROR;
  if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING))
    error_code |= OSSIM_MGRS_EASTING_ERROR;
  if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING))
    error_code |= OSSIM_MGRS_NORTHING_ERROR;
  if ((Precision < 0) || (Precision > MAX_PRECISION))
    error_code |= OSSIM_MGRS_PRECISION_ERROR;
  if (!error_code)
  {
    Set_UTM_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f,0);
    temp_error = Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &Latitude, &Longitude);
	if (temp_error & UTM_NORTHING_ERROR)
		error_code |= OSSIM_MGRS_NORTHING_ERROR;
	else
	{
	  /* Round easting and northing values */
	  divisor = pow (10.0, (5 - Precision));
	  Easting = Round_OSSIM_MGRS (Easting/divisor) * divisor;
	  Northing = Round_OSSIM_MGRS (Northing/divisor) * divisor;
	  UTMOSSIM_MGRS (Zone, Letters, Latitude, Easting, Northing);
	  /* UTM checks - these should be done in UTMOSSIM_MGRS */
	  if ((Zone == 31) && (Letters[0] == LETTER_V))
	    if (Easting > 500000)
		  Easting = 500000;
	  if (Northing > 10000000)
	    Northing = 10000000;
	  Make_OSSIM_MGRS_String (OSSIM_MGRS, Zone, Letters, Easting, Northing, Precision);
	}
  }
  return (error_code);
} /* Convert_UTM_To_OSSIM_MGRS */
Beispiel #2
0
long Convert_OSSIM_MGRS_To_Geodetic (const char* OSSIM_MGRS, 
                               double *Latitude, 
                               double *Longitude)
/*
 *    OSSIM_MGRS       : OSSIM_MGRS coordinate string           (output)
 *    Latitude   : Latitude in radians              (input)
 *    Longitude  : Longitude in radians             (input)
 *  
 */
{ /* Convert_OSSIM_MGRS_To_Geodetic */
  long error_code = OSSIM_MGRS_NO_ERROR;
  long Zone;
  long Letters[OSSIM_MGRS_LETTERS];
  char Hemisphere;
  double Easting;
  double Northing;
  long In_Precision;
  error_code = Break_OSSIM_MGRS_String (OSSIM_MGRS, &Zone, Letters, &Easting, &Northing, &In_Precision);
  if (!error_code)
  {
     if (Zone)
     {
        error_code |= Convert_OSSIM_MGRS_To_UTM (OSSIM_MGRS, &Zone, &Hemisphere, &Easting, &Northing);
        Set_UTM_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f, 0);
        error_code |= Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, Latitude, Longitude);
     }
     else
     {
        error_code |= Convert_OSSIM_MGRS_To_UPS (OSSIM_MGRS, &Hemisphere, &Easting, &Northing);
        Set_UPS_Parameters (OSSIM_MGRS_a, OSSIM_MGRS_f);
        error_code |= Convert_UPS_To_Geodetic (Hemisphere, Easting, Northing, Latitude, Longitude);
     }
  }
  return (error_code);
} /* END OF Convert_OSSIM_MGRS_To_Geodetic */
Beispiel #3
0
long Convert_UTM_To_MGRS (long Zone,
                          char Hemisphere,
                          double Easting,
                          double Northing,
                          long Precision,
                          char* MGRS)
/*
 * The function Convert_UTM_To_MGRS converts UTM (zone, easting, and
 * northing) coordinates to an MGRS coordinate string, according to the
 * current ellipsoid parameters.  If any errors occur, the error code(s)
 * are returned by the function, otherwise MGRS_NO_ERROR is returned.
 *
 *    Zone       : UTM zone                         (input)
 *    Hemisphere : North or South hemisphere        (input)
 *    Easting    : Easting (X) in meters            (input)
 *    Northing   : Northing (Y) in meters           (input)
 *    Precision  : Precision level of MGRS string   (input)
 *    MGRS       : MGRS coordinate string           (output)
 */
{ /* Convert_UTM_To_MGRS */
  double latitude;           /* Latitude of UTM point */
  double longitude;          /* Longitude of UTM point */
  long utm_error_code = MGRS_NO_ERROR;
  long error_code = MGRS_NO_ERROR;

  if ((Zone < 1) || (Zone > 60))
    error_code |= MGRS_ZONE_ERROR;
  if ((Hemisphere != 'S') && (Hemisphere != 'N'))
    error_code |= MGRS_HEMISPHERE_ERROR;
  if ((Easting < MIN_EASTING) || (Easting > MAX_EASTING))
    error_code |= MGRS_EASTING_ERROR;
  if ((Northing < MIN_NORTHING) || (Northing > MAX_NORTHING))
    error_code |= MGRS_NORTHING_ERROR;
  if ((Precision < 0) || (Precision > MAX_PRECISION))
    error_code |= MGRS_PRECISION_ERROR;
  if (!error_code)
  {
    Set_UTM_Parameters (MGRS_a, MGRS_f, 0);
    utm_error_code = Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &latitude, &longitude);
    if(utm_error_code)
    {
      if((utm_error_code & UTM_ZONE_ERROR) || (utm_error_code & UTM_HEMISPHERE_ERROR))
        error_code |= MGRS_STRING_ERROR;
      if(utm_error_code & UTM_EASTING_ERROR)
        error_code |= MGRS_EASTING_ERROR;
      if(utm_error_code & UTM_NORTHING_ERROR)
        error_code |= MGRS_NORTHING_ERROR;
    }

	  error_code = UTM_To_MGRS (Zone, Hemisphere, longitude, latitude, Easting, Northing, Precision, MGRS);
  }
  return (error_code);
} /* Convert_UTM_To_MGRS */
Beispiel #4
0
static int parse_location (char *e)
{
	int len;
	int ipat;
	char xstr[20], ystr[20], zstr[20], bstr[20], dstr[20];
	double x, y, dist, bearing;
	double lat0, lon0;
	double lat9, lon9;
	long lerr;	
	double easting, northing;
	char mh[20];	

	assert (*e == 'B');

	m_dao[2] = e[0];
	m_dao[3] = e[1];	/* Type of location.  e.g.  !TB6! */
				/* Will be changed by point types. */

				/* If this ever changes, be sure to update corresponding */
				/* section in process_comment() in decode_aprs.c */

	len = strlen(e);

	ipat = find_ttloc_match (e, xstr, ystr, zstr, bstr, dstr);
	if (ipat >= 0) {

	  //dw_printf ("ipat=%d, x=%s, y=%s, b=%s, d=%s\n", ipat, xstr, ystr, bstr, dstr);

	  switch (tt_config.ttloc_ptr[ipat].type) {
	    case TTLOC_POINT:
		
	      m_latitude = tt_config.ttloc_ptr[ipat].point.lat;
	      m_longitude = tt_config.ttloc_ptr[ipat].point.lon;

	      /* Is it one of ten or a hundred positions? */
	      /* It's not hardwired to always be B0n or B9nn.  */
	      /* This is a pretty good approximation. */

	      if (strlen(e) == 3) {	/* probably B0n -->  !Tn ! */
		m_dao[2] = e[2];
	        m_dao[3] = ' ';
	      }
	      if (strlen(e) == 4) {	/* probably B9nn -->  !Tnn! */
		m_dao[2] = e[2];
	        m_dao[3] = e[3];
	      }
	      break;

	    case TTLOC_VECTOR:

	      if (strlen(bstr) != 3) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Bearing \"%s\" should be 3 digits.\n", bstr);
	        // return error code?
	      }
	      if (strlen(dstr) < 1) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Distance \"%s\" should 1 or more digits.\n", dstr);
	        // return error code?
	      }

	      lat0 = D2R(tt_config.ttloc_ptr[ipat].vector.lat);
	      lon0 = D2R(tt_config.ttloc_ptr[ipat].vector.lon);
	      dist = atof(dstr) * tt_config.ttloc_ptr[ipat].vector.scale;
	      bearing = D2R(atof(bstr));

	      /* Equations and caluculators found here: */
	      /* http://movable-type.co.uk/scripts/latlong.html */
	      /* This should probably be a function in latlong.c in case we have another use for it someday. */

	      m_latitude = R2D(asin(sin(lat0) * cos(dist/R) + cos(lat0) * sin(dist/R) * cos(bearing)));

	      m_longitude = R2D(lon0 + atan2(sin(bearing) * sin(dist/R) * cos(lat0),
				  cos(dist/R) - sin(lat0) * sin(D2R(m_latitude))));
	      break;

	    case TTLOC_GRID:

	      if (strlen(xstr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Missing X coordinate.\n");
		strcpy (xstr, "0");
	      }
	      if (strlen(ystr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Missing Y coordinate.\n");
		strcpy (ystr, "0");
	      }

	      lat0 = tt_config.ttloc_ptr[ipat].grid.lat0;
	      lat9 = tt_config.ttloc_ptr[ipat].grid.lat9;
	      y = atof(ystr);
	      m_latitude = lat0 + y * (lat9-lat0) / (pow(10., strlen(ystr)) - 1.);

	      lon0 = tt_config.ttloc_ptr[ipat].grid.lon0;
	      lon9 = tt_config.ttloc_ptr[ipat].grid.lon9;
	      x = atof(xstr);
	      m_longitude = lon0 + x * (lon9-lon0) / (pow(10., strlen(xstr)) - 1.);

	      break;

	    case TTLOC_UTM:

	      if (strlen(xstr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Missing X coordinate.\n");
	        /* Avoid divide by zero later.  Put in middle of range. */
		strcpy (xstr, "5");
	      }
	      if (strlen(ystr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Missing Y coordinate.\n");
	        /* Avoid divide by zero later.  Put in middle of range. */
		strcpy (ystr, "5");
	      }

	      x = atof(xstr);
	      easting = x * tt_config.ttloc_ptr[ipat].utm.scale + tt_config.ttloc_ptr[ipat].utm.x_offset;

	      y = atof(ystr);
	      northing = y * tt_config.ttloc_ptr[ipat].utm.scale + tt_config.ttloc_ptr[ipat].utm.y_offset;
		
              lerr = Convert_UTM_To_Geodetic(tt_config.ttloc_ptr[ipat].utm.lzone, 
			tt_config.ttloc_ptr[ipat].utm.hemi, easting, northing, &lat0, &lon0);

              if (lerr == 0) {
                m_latitude = R2D(lat0);
                m_longitude = R2D(lon0);

                //printf ("DEBUG: from UTM, latitude = %.6f, longitude = %.6f\n", m_latitude, m_longitude);
              }
              else {
	        char message[300];

		text_color_set(DW_COLOR_ERROR);
	        utm_error_string (lerr, message);
                dw_printf ("Conversion from UTM failed:\n%s\n\n", message);
              }

	      break;


	    case TTLOC_MGRS:
	    case TTLOC_USNG:

	      if (strlen(xstr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("MGRS/USNG: Missing X (easting) coordinate.\n");
	        /* Should not be possible to get here. Fake it and carry on. */
		strcpy (xstr, "5");
	      }
	      if (strlen(ystr) == 0) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("MGRS/USNG: Missing Y (northing) coordinate.\n");
	        /* Should not be possible to get here. Fake it and carry on. */
		strcpy (ystr, "5");
	      }

	      char loc[40];
	
	      strcpy (loc, tt_config.ttloc_ptr[ipat].mgrs.zone);
	      strcat (loc, xstr);
	      strcat (loc, ystr);

	      //text_color_set(DW_COLOR_DEBUG);
	      //dw_printf ("MGRS/USNG location debug:  %s\n", loc);

	      if (tt_config.ttloc_ptr[ipat].type == TTLOC_MGRS)
                lerr = Convert_MGRS_To_Geodetic(loc, &lat0, &lon0);
	      else
                lerr = Convert_USNG_To_Geodetic(loc, &lat0, &lon0);


              if (lerr == 0) {
                m_latitude = R2D(lat0);
                m_longitude = R2D(lon0);

                //printf ("DEBUG: from MGRS/USNG, latitude = %.6f, longitude = %.6f\n", m_latitude, m_longitude);
              }
              else {
	        char message[300];

		text_color_set(DW_COLOR_ERROR);
	        mgrs_error_string (lerr, message);
                dw_printf ("Conversion from MGRS/USNG failed:\n%s\n\n", message);
              }
	      break;

	    case TTLOC_SATSQ:

	      if (strlen(xstr) != 4) {
	        text_color_set(DW_COLOR_ERROR);
	        dw_printf ("Expected 4 digits for the Satellite Square.\n");
	        return (TT_ERROR_SATSQ);
	      }

	      /* Convert 4 digits to usual AA99 form, then to location. */

	      if (tt_gridsquare_to_text (xstr, 0, mh)  == 0) {
		ll_from_grid_square (mh, &m_latitude, &m_longitude);
	      }
	      break;


	    default:
	      assert (0);
	  }
	  return (0);
	}

	/* Send reject sound. */
	/* Does not match any location specification. */

	return (TT_ERROR_INVALID_LOC);

} /* end parse_location */
Beispiel #5
0
long Convert_MGRS_To_UTM (char   *MGRS,
                          long   *Zone,
                          char   *Hemisphere,
                          double *Easting,
                          double *Northing)
/*
 * The function Convert_MGRS_To_UTM converts an MGRS coordinate string
 * to UTM projection (zone, hemisphere, easting and northing) coordinates
 * according to the current ellipsoid parameters.  If any errors occur,
 * the error code(s) are returned by the function, otherwise UTM_NO_ERROR
 * is returned.
 *
 *    MGRS       : MGRS coordinate string           (input)
 *    Zone       : UTM zone                         (output)
 *    Hemisphere : North or South hemisphere        (output)
 *    Easting    : Easting (X) in meters            (output)
 *    Northing   : Northing (Y) in meters           (output)
 */
{ /* Convert_MGRS_To_UTM */
  double min_northing;
  double northing_offset;
  long ltr2_low_value;
  long ltr2_high_value;
  double pattern_offset;
  double upper_lat_limit;     /* North latitude limits based on 1st letter  */
  double lower_lat_limit;     /* South latitude limits based on 1st letter  */
  double grid_easting;        /* Easting for 100,000 meter grid square      */
  double grid_northing;       /* Northing for 100,000 meter grid square     */
  long letters[MGRS_LETTERS];
  long in_precision;
  double latitude = 0.0;
  double longitude = 0.0;
  double divisor = 1.0;
  long utm_error_code = MGRS_NO_ERROR;
  long error_code = MGRS_NO_ERROR;

  error_code = Break_MGRS_String (MGRS, Zone, letters, Easting, Northing, &in_precision);
  if (!*Zone)
    error_code |= MGRS_STRING_ERROR;
  else
  {
    if (!error_code)
    {
      if ((letters[0] == LETTER_X) && ((*Zone == 32) || (*Zone == 34) || (*Zone == 36)))
        error_code |= MGRS_STRING_ERROR;
      else
      {
        if (letters[0] < LETTER_N)
          *Hemisphere = 'S';
        else
          *Hemisphere = 'N';

        Get_Grid_Values(*Zone, &ltr2_low_value, &ltr2_high_value, &pattern_offset);

        /* Check that the second letter of the MGRS string is within
         * the range of valid second letter values
         * Also check that the third letter is valid */
        if ((letters[1] < ltr2_low_value) || (letters[1] > ltr2_high_value) || (letters[2] > LETTER_V))
          error_code |= MGRS_STRING_ERROR;

        if (!error_code)
        {
          double row_letter_northing = (double)(letters[2]) * ONEHT;
          grid_easting = (double)((letters[1]) - ltr2_low_value + 1) * ONEHT;
          if ((ltr2_low_value == LETTER_J) && (letters[1] > LETTER_O))
            grid_easting = grid_easting - ONEHT;

          if (letters[2] > LETTER_O)
            row_letter_northing = row_letter_northing - ONEHT;

          if (letters[2] > LETTER_I)
            row_letter_northing = row_letter_northing - ONEHT;

          if (row_letter_northing >= TWOMIL)
            row_letter_northing = row_letter_northing - TWOMIL;

          error_code = Get_Latitude_Band_Min_Northing(letters[0], &min_northing, &northing_offset);
          if (!error_code)
          {
            grid_northing = row_letter_northing - pattern_offset;
            if(grid_northing < 0)
              grid_northing += TWOMIL;

            grid_northing += northing_offset;

            if(grid_northing < min_northing)
              grid_northing += TWOMIL;

            *Easting = grid_easting + *Easting;
            *Northing = grid_northing + *Northing;

            /* check that point is within Zone Letter bounds */
            utm_error_code = Set_UTM_Parameters(MGRS_a,MGRS_f,0);
            if (!utm_error_code)
            {
              utm_error_code = Convert_UTM_To_Geodetic(*Zone,*Hemisphere,*Easting,*Northing,&latitude,&longitude);
              if (!utm_error_code)
              {
                divisor = pow (10.0, in_precision);
                error_code = Get_Latitude_Range(letters[0], &upper_lat_limit, &lower_lat_limit);
                if (!error_code)
                {
                  if (!(((lower_lat_limit - DEG_TO_RAD/divisor) <= latitude) && (latitude <= (upper_lat_limit + DEG_TO_RAD/divisor))))
                    error_code |= MGRS_LAT_WARNING;
                }
              }
              else
              {
                if((utm_error_code & UTM_ZONE_ERROR) || (utm_error_code & UTM_HEMISPHERE_ERROR))
                  error_code |= MGRS_STRING_ERROR;
                if(utm_error_code & UTM_EASTING_ERROR)
                  error_code |= MGRS_EASTING_ERROR;
                if(utm_error_code & UTM_NORTHING_ERROR)
                  error_code |= MGRS_NORTHING_ERROR;
              }
            }
            else
            {
              if(utm_error_code & UTM_A_ERROR)
                error_code |= MGRS_A_ERROR;
              if(utm_error_code & UTM_INV_F_ERROR)
                error_code |= MGRS_INV_F_ERROR;
              if(utm_error_code & UTM_ZONE_OVERRIDE_ERROR)
                error_code |= MGRS_ZONE_ERROR;
            }
          }
        }
      }
    }
  }
  return (error_code);
} /* Convert_MGRS_To_UTM */
Beispiel #6
0
long Convert_MGRS_To_Geodetic (char* MGRS,
                               double *Latitude,
                               double *Longitude)
/*
 * The function Convert_MGRS_To_Geodetic converts an MGRS coordinate string
 * to Geodetic (latitude and longitude) coordinates
 * according to the current ellipsoid parameters.  If any errors occur,
 * the error code(s) are returned by the function, otherwise UTM_NO_ERROR
 * is returned.
 *
 *    MGRS       : MGRS coordinate string           (input)
 *    Latitude   : Latitude in radians              (output)
 *    Longitude  : Longitude in radians             (output)
 *
 */
{ /* Convert_MGRS_To_Geodetic */
  long zone;
  char hemisphere;
  double easting;
  double northing;
  long zone_exists;
  long temp_error_code = MGRS_NO_ERROR;
  long error_code = MGRS_NO_ERROR;

  error_code = Check_Zone(MGRS, &zone_exists);
  if (!error_code)
  {
    if (zone_exists)
    {
      error_code |= Convert_MGRS_To_UTM (MGRS, &zone, &hemisphere, &easting, &northing);
      if(!error_code || (error_code & MGRS_LAT_WARNING))
      {
        temp_error_code = Set_UTM_Parameters (MGRS_a, MGRS_f, 0);
        if(!temp_error_code)
        {
          temp_error_code = Convert_UTM_To_Geodetic (zone, hemisphere, easting, northing, Latitude, Longitude);
          if(temp_error_code)
          {
            if((temp_error_code & UTM_ZONE_ERROR) || (temp_error_code & UTM_HEMISPHERE_ERROR))
              error_code |= MGRS_STRING_ERROR;
            if(temp_error_code & UTM_EASTING_ERROR)
              error_code |= MGRS_EASTING_ERROR;
            if(temp_error_code & UTM_NORTHING_ERROR)
              error_code |= MGRS_NORTHING_ERROR;
          }
        }
        else
        {
          if(temp_error_code & UTM_A_ERROR)
            error_code |= MGRS_A_ERROR;
          if(temp_error_code & UTM_INV_F_ERROR)
            error_code |= MGRS_INV_F_ERROR;
          if(temp_error_code & UTM_ZONE_OVERRIDE_ERROR)
            error_code |= MGRS_ZONE_ERROR;
        }
      }
    }
    else
    {
      error_code |= Convert_MGRS_To_UPS (MGRS, &hemisphere, &easting, &northing);
      if(!error_code)
      {
        temp_error_code = Set_UPS_Parameters (MGRS_a, MGRS_f);
        if(!temp_error_code)
        {
          temp_error_code = Convert_UPS_To_Geodetic (hemisphere, easting, northing, Latitude, Longitude);
          if(temp_error_code)
          {
            if(temp_error_code & UPS_HEMISPHERE_ERROR)
              error_code |= MGRS_STRING_ERROR;
            if(temp_error_code & UPS_EASTING_ERROR)
              error_code |= MGRS_EASTING_ERROR;
            if(temp_error_code & UPS_LAT_ERROR)
              error_code |= MGRS_NORTHING_ERROR;
          }
        }
        else
        {
          if(temp_error_code & UPS_A_ERROR)
            error_code |= MGRS_A_ERROR;
          if(temp_error_code & UPS_INV_F_ERROR)
            error_code |= MGRS_INV_F_ERROR;
        }
      }
    }
  }
  return (error_code);
} /* END OF Convert_MGRS_To_Geodetic */
Beispiel #7
0
void GRID_UTM (long   *Zone,
               long   *Letters,
               char   *Hemisphere,
               double *Easting,
               double *Northing,
               long   In_Precision,
               long   *Error)
{ /* BEGIN GRID_UTM */
  double fnltr;               /* False northing for 3rd letter              */
  long ltrhi;                 /* 2nd letter range - High number             */
  long ltrlow;                /* 2nd letter range - Low number              */
  long number;                /* Value of ltrnum[0] + 1                     */
/*  double slam;*/
  double slcm;                /* Central meridian                           */
  double sleast;              /* Longitude east limit - UTM                 */
  double slwest;              /* Longitude west limit -UTM                  */
  double sphi;                /* Latitude (needed by UTMLIM)                */
  double spnor;               /* North latitude limits based on 1st letter  */
  double spsou;               /* South latitude limits based on 1st letter  */
  double xltr;                /* Easting for 100,000 meter grid square      */
  double ylow;                /* Lowest northing of area to nearest 100,000 */
  double yltr;                /* Northing for 100,000 meter grid square     */
  double yslow;               /* Northing scaled down to less than 2 million*/
  double Latitude = 0.0;
  double Longitude = 0.0;
  double divisor = 1.0;
  if ((*Zone == 32) && (Letters[0] == LETTER_X))
  {
    *Error = TRUE;
    return;
  }
  if ((*Zone == 34) && (Letters[0] == LETTER_X))
  {
    *Error = TRUE;
    return;
  }
  if ((*Zone == 36) && (Letters[0] == LETTER_X))
  {
    *Error = TRUE;
    return;
  }
  number = Letters[0] + 1;
  sphi = 0.0;
  UTMLIM(&number,sphi,*Zone,&spsou,&spnor,&sleast,&slwest);
  Set_UTM_Parameters(OSSIM_MGRS_a,OSSIM_MGRS_f,*Zone);
  slcm = (double)(*Zone * 6 - 183) * DEGRAD; 
  Convert_Geodetic_To_UTM(spsou,slcm,Zone,Hemisphere,&xltr,&yltr);
  ylow = ((double)((long)((double)((long)(yltr / ONEHT)) * ONEHT)));
  yslow = ylow;
  while (yslow >= TWOMIL)
  {
    yslow = yslow - TWOMIL;
  }
  yslow = ((double)((long)(yslow)));
  UTMSET(*Zone, &ltrlow, &ltrhi, &fnltr);
  LTR2UTM(Letters, ltrlow, ltrhi, Error, &xltr, &yltr, fnltr, yslow, ylow);
  *Easting = xltr + *Easting;
  *Northing = yltr + *Northing;
  /* check that point is within Zone Letter bounds */
  Convert_UTM_To_Geodetic(*Zone,*Hemisphere,*Easting,*Northing,&Latitude,&Longitude);
  divisor = pow (10.0, In_Precision);
  if (((spsou - DEGRAD/divisor) <= Latitude) && (Latitude <= (spnor + DEGRAD/divisor)))
    return;
  else
    *Error = TRUE;
  return;
}/* END OF GRID_UTM */