// take RA/Dec coordinates and give chart numbers for either of
// the following publications:
// Uranometria 2nd Edition
// Sky Atlas 2000.0
// My info from Sky Atlas 2000 came from the 2nd edition but I don't think
// there are any differences as far as chart numbers.
// if anyone can provide info on Uranometria 1st edition let me know
// and I'll add support for that as well.

// Copyright 2002, John Ridley
// This code is released to the public domain.
// You can do whatever you want with this code including making money
// off of it, but I retain original authorship so I can also do what
// I want with it.
// I would only make two requests; leave this notice in the code, and
// email me at john.ridley@gt.org and let me know what product you are 
// incorporating this code into.
// - I'm just curious

#define Uranometria2nd 0
#define SkyAtlas2k     1


// Uranometria
// charts 1->120 are in volume 1
// charts 101-> 220 are in volume 2 (there is overlap)
// overlapping areas are split evenly between adjacent maps
typedef struct
{
  float SouthBorder;
  int BoundaryMap;
  int MapsThisTier;
} TierFormat;

static TierFormat U_Data[] = 
{
  {  84.5,   1,  1}, // 1st tier, chart 1
  {  73.5,   7,  6}, // 2nd tier, charts 2->7
  {  62.5,  17, 10}, // 3rd tier, charts 8->17
  {  51.5,  29, 12}, // 4th tier, charts 18->29
  {  40.5,  44, 15}, // 5th tier, charts 30->44
  {  29.5,  62, 18}, // 6th tier, charts 45->62 
  {  17.5,  80, 18}, // 7th tier, charts 63->80
  {   5.5, 100, 20}, // 8th tier, charts 81->100
  {  -5.5, 120, 20}, // 9th tier, charts 101->120
  { -17.5, 140, 20}, // 10th tier, charts 121->140
  { -29.5, 158, 18}, // 11th tier, charts 141->158
  { -40.5, 176, 18}, // 12th tier, charts 159->176
  { -51.5, 191, 15}, // 13th tier, charts 177->191
  { -62.5, 203, 12}, // 14th tier, charts 192->203
  { -73.5, 213, 10}, // 15th tier, charts 204->213
  { -84.5, 219,  6}, // 16th tier, charts 214->219
  { -90.0, 220,  1}, // 17th tier, chart 220
};

// Sky Atlas 2000
static TierFormat SA_Data[] = 
{
  {  50.0,   1,  3}, // 1st tier, charts 1->3
  {  20.0,   4,  6}, // 2nd tier, charts 4->9
  { -20.0,  10,  8}, // 3rd tier, charts 10->17
  { -50.0,  18,  6}, // 4th tier, charts 18->23
  { -90.0,  24,  3}, // 5th tier, charts 24->26
};

#define BOOL int

// sky atlas; no start offset, maps go clockwise  
int ChartNumber(float ra, float dec, int Publication)
{
  TierFormat *data;
  int Tier;
  int MapOffset;
  float HoursPerChart;
  BOOL OffsetCharts, Clockwise;

  // sanity checks
  if ((dec > 90) || (dec < -90))
    return 0;
  if ((ra > 24) || (ra < 0))
    return 0;

  if (Publication == Uranometria2nd)
  {
    data = U_Data;
    OffsetCharts = 1;
    Clockwise = 0;
  }
  else if (Publication == SkyAtlas2k)
  {
    data = SA_Data;
    OffsetCharts = 0;
    Clockwise = 1;
  }
  else
    return 0;
    
  // find proper tier
  for (Tier = 0; 
       dec < data[Tier].SouthBorder;
       Tier++);

  HoursPerChart = 24.0 / data[Tier].MapsThisTier;

  // Offset; middle of 1st map is in the middle of 0 hours RA
  if (OffsetCharts)
  {
    ra = ra - (HoursPerChart/2);
    // force sanity
  }
  if (ra < 0.0)
    ra += 24.0;
  if (ra >= 24.0)
    ra -= 24.0;

  MapOffset = (ra / HoursPerChart);
  if (Clockwise)
    return data[Tier].BoundaryMap + MapOffset;
  else
    return data[Tier].BoundaryMap - MapOffset;
}


// test program
int main()
{
  float ra, dec;
  int chart;
  
  while (1)
  {
    printf("RA: ");
    scanf("%f",&ra);
    printf("Dec: ");
    scanf("%f",&dec);
    chart = ChartNumber(ra,dec,Uranometria2nd);
    printf("Uranometria chart %d\n\n",chart);
    chart = ChartNumber(ra,dec,SkyAtlas2k);
    printf("Sky Atlas chart %d\n\n",chart);
  }
  return 0;
}

