/*  xtraceroute - graphically show traceroute information.
 *  Copyright (C) 1996-1998  Björn Augustsson 
 *
 *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "xt.h"
#include <ctype.h>

/**
 *  This one converts a string with a latitude or 
 *  longitude in "XXX YY ZZc" format, where
 *  XXX is the degree, YY is the minute, zz is the 
 *  second and c is s, n, e or w for direction into
 *  a double.
 *
 * That double is returned.
 */

double
locStrToNum(char *str, int type)
{
  double factor = 1.0;
  double loc = 0;
  float sub;
  int i = 0;

  while(1)
    {
      sscanf(&str[i], "%f", &sub);
      loc += sub*factor;

      // Skip all spaces and tabs
      while(is_whitespace(str[i]))
	  i++;

      // Skip all numbers
      while(isdigit((int)str[i]))
	  i++;
      
      switch(type)
        {
	  case LATITUDE:
	  if(str[i] == 'n' || str[i] == 'N')
	    return loc;
	  else if(str[i] == 's' || str[i] == 'S')
	    return -loc;
	  break;

	  case LONGITUDE:
	  if(str[i] == 'e' || str[i] == 'E')
	    return loc;
	  else if(str[i] == 'w' || str[i] == 'W')
	    return -loc;
	  break;
	} 
      factor /= 60.0;
    }
  /* Not reached */
}

/**
 *  This one converts a double with a latitude or 
 *  longitude into a "XXX YY ZZc" format, where
 *  XXX is the degree, YY is the minute, zz is the 
 *  second and c is s, n, e or w for direction. 
 *
 * That string is returned.
 */

char *
locNumToStr(double loc, int type)
{
  char *str;
  int deg, min, sec;
  char direction;
  
  str = (char *)malloc(12);

  switch(type)
    {
    case LATITUDE:
      if(loc < 0)
	{
	  direction = 's';
	  loc = -loc;
	}
      else
	direction = 'n';
      break;
    default:  // LONGITUDE
      if(loc < 0)
	{
	  direction = 'w';
	  loc = -loc;
	}
      else
	direction = 'e';
      break;
    }

  deg = (int)floor(loc);  

  loc -= floor(loc);  
  loc *= 60.0;
  
  min = (int)floor(loc);
  
  loc -= floor(loc);
  loc *= 60.0;
  
  sec = (int)floor(loc);
  
  sprintf(str,"%d %d %d%c", deg, min, sec, direction);
  return str;
}

/**
 * The following three functions returns the x-, y-, and z-coordinate
 * respectively for the specified point on the surface.
 * (These are often used together: maybe make a combined function?)
 */

GLdouble tox(GLdouble lat, GLdouble lon)
  {  return((GLdouble)sin(lon*torad)*cos(lat*torad)); }

GLdouble toy(GLdouble lat, GLdouble lon)
  {  return((GLdouble)sin(lat*torad));  }

GLdouble toz(GLdouble lat, GLdouble lon)
  {  return((GLdouble)cos(lon*torad)*cos(lat*torad)); }

/**
 * tolon() returns the longitude of a point on the unit sphere.
 * (Longitudes are the "x" axis on a mercator projection map.)
 */

GLdouble tolon(GLdouble x, GLdouble y, GLdouble z)
{
  GLdouble s;
  if(y == 1.0 || y == -1.0)
    return(5000.0);    /* Problem! The texture will warp! Actually these */
  s = sqrt(1 - y*y);   /* points (the poles) are on ALL the longitudes! */
  return((GLdouble)(atan2(x/s,z/s) * todeg));
}

/**
 * tolat() returns the latitude of a point on the unit sphere.
 * (Latitudes are the "y" axis on a mercator projection map.)
 */

GLdouble tolat(GLdouble x, GLdouble y, GLdouble z)
{
  return((GLdouble) (atan2(y, sqrt(1 - y*y)) * todeg));
}

/**
 * distance returns the actual theoretical minimum 
 * distance (in meters) the signal has to travel. 
 */
unsigned long distance(int site)
{
  int i;
  unsigned long distance_covered = 0;
  
  for(i=1 ; i<=site ; i++)
    {
      /* This is not really the way to do this. This assumes that
	 earth is round (it isn't!). I'm sure there's a good way to
	 compute the actual distance between two locations on earth. */
      
      /*    Angle is arccos(Ax*Bx + Ay*By + Az*Bz)    */
      
      float angle = acos((float)
			 (tox(sites[ i ].lat,sites[ i ].lon)
			  *tox(sites[i-1].lat,sites[i-1].lon)
			  +toy(sites[ i ].lat,sites[ i ].lon)
			  *toy(sites[i-1].lat,sites[i-1].lon)
			  +toz(sites[ i ].lat,sites[ i ].lon)
			  *toz(sites[i-1].lat,sites[i-1].lon)))
	* todeg;
      
      distance_covered += (int)rint((angle/360.0) * PHYSICAL_EARTH_CIRC);
    }
  return distance_covered;
}

/*   isin() returns 1 if a is in b  (sort of like grep)    */

int isin(const char a[],const char b[])
{
 int i;
 int a_len    = strlen(a);
 int len_diff = strlen(b) - a_len;

/*   'grep' backwards, since most DB entries are endings, like 
     "chalmers.se". Performance opt! Yeah!  */

 for(i=len_diff;i>=0;i--)
   if(!strncasecmp(a,&b[i],a_len))
     return(1);
 return(0);
}

/*   getsuff puts the suffix of site a in b.   */

void getsuff(const char a[], char b[])
{
 int i;
 for(i=strlen(a);i>0;i--)
   if(a[i]=='.')
    {
     strcpy(b, &a[i+1]);
     return;
    }
 strcpy(b, "None");
 return;
}


