/* $Id: util.c,v 1.4 2003/03/22 14:39:04 d3august Exp $
*/
/*  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 <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "xt.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(const char *str, int type)
{
  double factor = 1.0;
  double loc = 0;
  float sub;
  int i = 0;
  
  while(1)
    {
      int retval = sscanf(&str[i], "%f", &sub);
      if(retval == 0 || retval == EOF)
	{
	  /* Trouble! */
	  printf("Xtraceroute: locStrToNum[1]: got bad LOC data!\n");
	  printf("\tData: \"%s\"\n", str);
	  return(-1000);
	}
      loc += sub*factor;

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

      // Skip all numbers (including decimal point)
      while(isdigit((int)str[i]) || str[i] == '.')
	  i++;
      
      switch(type)
        {
	case LATITUDE:
	  if(toupper(str[i]) == 'N' || 
	     (str[i] == ' ' && toupper(str[i+1]) == 'N') )
	    {
	      return loc;
	    }
	  else if(toupper(str[i]) == 'S' || 
		  (str[i] == ' ' && toupper(str[i+1]) == 'S'))
	    {
	      return -loc;
	    }
	  break;

	case LONGITUDE:
	  if(toupper(str[i]) == 'E' || 
	     (str[i] == ' ' && toupper(str[i+1]) == 'E'))
	    {
	      return loc;
	    }
	  else if(toupper(str[i]) == 'W' || 
		  (str[i] == ' ' && toupper(str[i+1]) == 'W'))
	    {
	      return -loc;
	    }
	  break;
	}

      factor /= 60.0;

      if (factor <= 1.0 / (60.0 * 60.0 * 60.0))
	{
	  /* We've gotten more than 3 number fields! */
	  /* Malformed data, this is not a proper lat/lon string! */
	  printf("Xtraceroute: locStrToNum[2]: got bad LOC data!\n");
	  printf("\tData: \"%s\"\n", str);
	  return(-2000);	  
	}
    }
  /* 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?)
 */

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

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

double 
toz(double lat, double lon)
  {  return(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.)
 */

double 
tolon(double x, double y, double z)
{
  double 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((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.)
 */

double 
tolat(double x, double y, double z)
{
  return(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 (whatever is afer the last '.' in the string)
 * of site a in b. (Or "None" if there's no '.') 
 */

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;
}

/**
 * This is a debug stub. See xt.h.
 */

#ifndef XT_DEBUG
int dontprintf(const char *format, ...)
{
	return (0);
}
#endif /* !XT_DEBUG */



syntax highlighted by Code2HTML, v. 0.9.1