/* @(#)ast_edq.c	19.1 (ES0-DMD) 02/25/03 13:53:53 */
/*===========================================================================
  Copyright (C) 1995 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*+++++++++  
.MODULE    edq.c
.AUTHOR    Francois Ochsenbein [ESO]
.LANGUAGE  C
.CATEGORY  Edition of spherical coordinates

.COMMENTS
Functions in this module edit coordinates, either
as decimal degrees ("G" type), or as equatorial coordinates
("Q" type).

.VERSION 1.0 	26-Feb-1987: Creation 
.VERSION 1.1 	02-Mar-1987: Declinations are properly aligned.
.VERSION 1.2 	24-Mar-1987: Fill with blank if necessary
.VERSION 1.3 	14-Oct-1988: Cosmetic modifications
----------------------------------------------------------------------------*/
 
#define DEBUG		0	/* For debugging	*/

#include <osdefos.h>
#include <macrogen.h>
#include <math.h>		/* System	*/

RSTATIC double gf[] = {1., 10., 100., 1.e3,  1.e4,  1.e5,  1.e6,  1.e7};
RSTATIC double qf[] = {1., 10.,  60., 600., .36e4, .36e5, .36e6, .36e7, .36e8};

#define FINISH		goto FIN

/*===========================================================================*/
static int ed(dest, value, nd)
/*++++++++++
.PURPOSE Edit number `value' with `nd' digits
.RETURNS 0 for OK, remainder if number not edited.
-------------*/
	char   *dest; 		/* OUT: pointer to destination string 	*/
	long   value;		/* IN: The number edit	*/
	int    nd;		/* IN: Number of digits		*/
{
	long 	n;
  	char 	*p;
	int	i;

  for (n = value, i = nd, p = dest + nd; --i >= 0; n /= 10)
  	*(--p) = '0' + n%10;

  i = n;
  return(i);
}

/*===========================================================================*/
int ed_o1(dest, value, precision, op)
/*++++++++++
.PURPOSE	Edit Single coordinates in decimal degrees
		(longitude or declination)
		The precision (number of decimals) must be between
		1 and 7.
.METHOD		Coordinates are rounded.
.RETURNS	Length of the EOS-terminated edited string, -1
		for errors.
-------------*/
	char   *dest; 		/* OUT: pointer to destination string 	*/
	double value[2];	/* IN: The coordinates to edit	*/
	int    precision;	/* IN: Precision for edition		*/
	int 	op;		/* IN: 0 = long, 1 = lat	*/
{
	long 	int n;
  	char 	*p;
  	double 	 f;

	/* Test bad coordinates	or not enough space	*/

  p = dest;

  if (precision < 0) 	FINISH;
  if (precision > 7)	precision = 7;

	/* Round the Longitude / Latitude	*/
	
  if (op == 0)
  {	f = value[0] + .5e0/gf[precision] ;
  	if (f < 0.0e0)		f += 360.0e0;
  	if (f >= 360.0e0)	f -= 360.0e0;
  	n = f;			/* Integer part */
  	ed(p, n, 3);
  	p += 3;
  }
  else
  {	*(p++) = (value[1] >= 0 ? '+' : '-');
  	f = fabs(value[1]) + .5e0/gf[precision] ;
  	n = f;			/* Integer part */
  	ed(p, n, 2);
  	p += 2;
  }  
  
	/* Edit Fractions */

  if (precision > 0)
  {	*(p++) = '.';
  	f = (f - n) * gf[precision];
  	n = f;
  	ed(p, n, precision);
  	p += precision;
  }

  FIN:
  *p = EOS;
  return(p - dest);
}
  
/*===========================================================================*/
int ed_o(dest, value, precision)
/*++++++++++
.PURPOSE	Edit coordinates in decimal degrees.
		The precision (number of decimals) msut be between
		1 and 6.
.METHOD		Coordinates are rounded
.RETURNS	Length of the EOS-terminated edited string, -1
		for errors.
-------------*/
     char   *dest; 		/* OUT: pointer to destination string 	*/
     double value[2];		/* IN: The 2 coordinates to edit	*/
     int    precision;		/* IN: Precision for edition		*/
{
  	char 	*p;

#if DEBUG
  printf("ed_o: coordinates=(%12.6f,%12.6f)=%d=\n",
	value[0], value[1], precision);
#endif
  
  p = dest;

	/* Edit the Longitude	*/
	
  p += ed_o1(p, value, precision, 0);

  *(p++) = ' ';		/* Add a blank	*/
  
	/* Edit the Latitude	*/
	
  p += ed_o1(p, value, precision, 1);
  
  return(p - dest);
}
  
/*===========================================================================*/
int ed_q1(dest, value, precision, op)
/*++++++++++
.PURPOSE	Edit equatorial coordinates in the astronomical form.
		The precision ranges from 0 to 7, for degrees to 
		arc.sec/1000.
.METHOD		Coordinates are rounded
.RETURNS	The length (without the trailing EOS) / -1 if error
.REMARKS	Right ascension with at least minutes.
-------------*/
	char 	*dest; 		/* OUT: pointer to destination string 	*/
	double	value[2];	/* IN: The 2 coordinates to edit	*/
	int	precision;	/* IN: The precision, 0 to 7		*/
	int op;			/* IN: 0 = RA, 1 = dec	*/
{
	long 	int n;
  	char 	*p;
  	double 	 f;
  	int	nd, i;
	RSTATIC char sep[3] = {EOS, '.', ' '};
  
	/* Test bad coordinates	or not enough space	*/

  p = dest;

  if (precision < 0) 	FINISH;
  if (precision > 7) 	precision = 7;

	/* Round and Edit the Right Ascension	*/
	
  if (op == 0)
  {	nd = (precision ? precision + 1 : 2);
  	f = value[0]/15.0e0 + 0.5e0/qf[nd] ;
  	if (f < 0.0e0)		f += 24.0e0;
  	if (f >= 24.0e0)	f -= 24.0e0;
  }
  else
  {	*(p++) = (value[1] >= 0 ? '+' : '-');
  	nd = precision;
  	f = fabs(value[1]) + .5e0/qf[nd] ;
  }  

  n = f;			/* Integer part */
  ed(p, n, 2), p += 2;
  
	/* Edit mn	*/
	
  i = MIN(nd, 2);
  if (i == 0)	FINISH;
  *(p++) = sep[i];
  f = (f-n) * qf[i];
  n = f;
  ed(p, n, i);
  p += i, nd -= i;
  
  
	/* Edit seconds	*/
	
  i = MIN(nd, 2);
  if (i == 0)	FINISH;
  *(p++) = sep[i];
  f = (f-n) * qf[i];
  n = f;
  ed(p, n, i);
  p += i, nd -= i;
  
	/* Edit Fractions of seconds	*/
	
  if (nd == 0)	FINISH;
  *(p++) = '.';
  f = (f-n) * gf[nd];
  n = f;
  ed(p, n, nd);
  p += nd;

  FIN:
  *p = EOS;
  return(p-dest);
}

/*===========================================================================*/
int ed_q(dest, value, precision)
/*++++++++++
.PURPOSE	Edit equatorial coordinates in the astronomical form.
		The precision ranges from 0 to 7, for degrees to 
		arc.sec/1000.
.METHOD		Coordinates are rounded
.RETURNS	The length (without the trailing EOS) / -1 if error
.REMARKS	The string is filled with * if the coordinates cannot be edited .
-------------*/
	char 	*dest; 		/* OUT: pointer to destination string 	*/
	double	value[2];	/* IN: The 2 coordinates to edit	*/
	int	precision;	/* IN: The precision, 0 to 7		*/
{
  	char 	*p;

#if DEBUG
  printf("ed_q: coordinates=(%12.6f,%12.6f)=%d=\n",
	value[0], value[1], precision);
#endif

  p = dest;

	/* Edit the Right Ascension	*/
	
  p += ed_q1(p, value, precision, 0);

  *(p++) = ' ';		/* Add a blank	*/
  
	/* Edit the Declination	*/
	
  p += ed_q1(p, value, precision, 1);
  
  return(p - dest);
}

