/* code to handle constellation boundaries and figures */

/*
Constellation boundaries:

 Primary reference:

  METHOD TO DETERMINE THE CONSTELLATION IN WHICH A POSITION IS LOCATED

        Recently, Mr. Barry N. Rappaport of New  Mexico State University
  transcribed  the constellation  boundaries as  fixed  by the IAU  into
  machine-readable form.  These have  been  transcribed  by Dr. Nancy G.
  Roman to make it possible  to determine by  computer the constellation
  in which a position is located.

 NSSDC catalog description:
 6042   AN     Catalog of Constellation Boundary Data (Delporte, E. 1930, 
               Cambridge Univ. Press)
               Comment(s): includes constellation identification software 
               (ADC 1987; see Roman, N.G. 1987, Publ. Astron. Soc. Pacific 
               99, 695); 23 description, 118 software, 358 data records. 
               3 files: 23x80, 118x80, 358x29 

 Further adapted for xephem by:

    Craig Counterman: conversion from original F77 to C
    Elwood Downey:    incorporation into xephem
    Ernie Wright:     additional speed and time improvments

Constellation figures:

    Chris Marriott:   original figures
    Elwood Downey:    incorporated into xephem
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include "astro.h"

/*
======================================================================
Ernie Wright  2 Mar 94

Find the constellation for a given position.

First C version by Craig Counterman and Elwood Downey.  Based on a
FORTRAN program by Nancy G. Roman (Roman, N.G. 1987, Publ. Astron.
Soc. Pacific 99, 695).  IAU constellation boundaries transcribed into
machine-readable form by Barry N. Rappaport, New Mexico State Univ.
======================================================================
*/

#define NBOUNDS 357

/* constellation ids */
#define And  0
#define Ant  1
#define Aps  2
#define Aql  3
#define Aqr  4
#define Ara  5
#define Ari  6
#define Aur  7
#define Boo  8
#define CMa  9
#define CMi 10
#define CVn 11
#define Cae 12
#define Cam 13
#define Cap 14
#define Car 15
#define Cas 16
#define Cen 17
#define Cep 18
#define Cet 19
#define Cha 20
#define Cir 21
#define Cnc 22
#define Col 23
#define Com 24
#define CrA 25
#define CrB 26
#define Crt 27
#define Cru 28
#define Crv 29
#define Cyg 30
#define Del 31
#define Dor 32
#define Dra 33
#define Equ 34
#define Eri 35
#define For 36
#define Gem 37
#define Gru 38
#define Her 39
#define Hor 40
#define Hya 41
#define Hyi 42
#define Ind 43
#define LMi 44
#define Lac 45
#define Leo 46
#define Lep 47
#define Lib 48
#define Lup 49
#define Lyn 50
#define Lyr 51
#define Men 52
#define Mic 53
#define Mon 54
#define Mus 55
#define Nor 56
#define Oct 57
#define Oph 58
#define Ori 59
#define Pav 60
#define Peg 61
#define Per 62
#define Phe 63
#define Pic 64
#define PsA 65
#define Psc 66
#define Pup 67
#define Pyx 68
#define Ret 69
#define Scl 70
#define Sco 71
#define Sct 72
#define Se1 73
#define Sex 74
#define Sge 75
#define Sgr 76
#define Tau 77
#define Tel 78
#define TrA 79
#define Tri 80
#define Tuc 81
#define UMa 82
#define UMi 83
#define Vel 84
#define Vir 85
#define Vol 86
#define Vul 87
#define Se2 88

static char *cns_namemap[ NCNS ] = {
   /*  0 */   "And: Andromeda",
   /*  1 */   "Ant: Antlia",
   /*  2 */   "Aps: Apus",
   /*  3 */   "Aql: Aquila",
   /*  4 */   "Aqr: Aquarius",
   /*  5 */   "Ara: Ara",
   /*  6 */   "Ari: Aries",
   /*  7 */   "Aur: Auriga",
   /*  8 */   "Boo: Bootes",
   /*  9 */   "CMa: Canis Major",
   /* 10 */   "CMi: Canis Minor",
   /* 11 */   "CVn: Canes Venatici",
   /* 12 */   "Cae: Caelum",
   /* 13 */   "Cam: Camelopardalis",
   /* 14 */   "Cap: Capricornus",
   /* 15 */   "Car: Carina",
   /* 16 */   "Cas: Cassiopeia",
   /* 17 */   "Cen: Centaurus",
   /* 18 */   "Cep: Cepheus",
   /* 19 */   "Cet: Cetus",
   /* 20 */   "Cha: Chamaeleon",
   /* 21 */   "Cir: Circinus",
   /* 22 */   "Cnc: Cancer",
   /* 23 */   "Col: Columba",
   /* 24 */   "Com: Coma Berenices",
   /* 25 */   "CrA: Corona Australis",
   /* 26 */   "CrB: Corona Borealis",
   /* 27 */   "Crt: Crater",
   /* 28 */   "Cru: Crux",
   /* 29 */   "Crv: Corvus",
   /* 30 */   "Cyg: Cygnus",
   /* 31 */   "Del: Delphinus",
   /* 32 */   "Dor: Dorado",
   /* 33 */   "Dra: Draco",
   /* 34 */   "Equ: Equuleus",
   /* 35 */   "Eri: Eridanus",
   /* 36 */   "For: Fornax",
   /* 37 */   "Gem: Gemini",
   /* 38 */   "Gru: Grus",
   /* 39 */   "Her: Hercules",
   /* 40 */   "Hor: Horologium",
   /* 41 */   "Hya: Hydra",
   /* 42 */   "Hyi: Hydrus",
   /* 43 */   "Ind: Indus",
   /* 44 */   "LMi: Leo Minor",
   /* 45 */   "Lac: Lacerta",
   /* 46 */   "Leo: Leo",
   /* 47 */   "Lep: Lepus",
   /* 48 */   "Lib: Libra",
   /* 49 */   "Lup: Lupus",
   /* 50 */   "Lyn: Lynx",
   /* 51 */   "Lyr: Lyra",
   /* 52 */   "Men: Mensa",
   /* 53 */   "Mic: Microscopium",
   /* 54 */   "Mon: Monoceros",
   /* 55 */   "Mus: Musca",
   /* 56 */   "Nor: Norma",
   /* 57 */   "Oct: Octans",
   /* 58 */   "Oph: Ophiuchus",
   /* 59 */   "Ori: Orion",
   /* 60 */   "Pav: Pavo",
   /* 61 */   "Peg: Pegasus",
   /* 62 */   "Per: Perseus",
   /* 63 */   "Phe: Phoenix",
   /* 64 */   "Pic: Pictor",
   /* 65 */   "PsA: Piscis Austrinus",
   /* 66 */   "Psc: Pisces",
   /* 67 */   "Pup: Puppis",
   /* 68 */   "Pyx: Pyxis",
   /* 69 */   "Ret: Reticulum",
   /* 70 */   "Scl: Sculptor",
   /* 71 */   "Sco: Scorpius",
   /* 72 */   "Sct: Scutum",
   /* 73 */   "Se1: Serpens Caput",
   /* 74 */   "Sex: Sextans",
   /* 75 */   "Sge: Sagitta",
   /* 76 */   "Sgr: Sagittarius",
   /* 77 */   "Tau: Taurus",
   /* 78 */   "Tel: Telescopium",
   /* 79 */   "TrA: Triangulum Australe",
   /* 80 */   "Tri: Triangulum",
   /* 81 */   "Tuc: Tucana",
   /* 82 */   "UMa: Ursa Major",
   /* 83 */   "UMi: Ursa Minor",
   /* 84 */   "Vel: Vela",
   /* 85 */   "Vir: Virgo",
   /* 86 */   "Vol: Volans",
   /* 87 */   "Vul: Vulpecula",
   /* 88 */   "Se2: Serpens Cauda",
};

static struct {
   unsigned short lower_ra;      /* hours * 1800 */
   unsigned short upper_ra;      /* hours * 1800 */
   short          lower_dec;     /* degrees * 60 */
   short          index;
} cbound[ NBOUNDS ] = {
   {     0, 43200,  5280, UMi },
   { 14400, 26100,  5190, UMi },
   { 37800, 41400,  5170, UMi },
   { 32400, 37800,  5160, UMi },
   {     0, 14400,  5100, Cep },
   { 16500, 19200,  4920, Cam },
   {     0,  9000,  4800, Cep },
   { 19200, 26100,  4800, Cam },
   { 31500, 32400,  4800, UMi },
   { 36300, 37800,  4800, Dra },
   {     0,  6315,  4620, Cep },
   { 20700, 24450,  4620, Cam },
   { 29760, 31500,  4500, UMi },
   { 36300, 37200,  4500, Cep },
   { 14340, 16500,  4410, Cam },
   { 16500, 20400,  4410, Dra },
   { 23400, 29760,  4200, UMi },
   {  5580,  6150,  4080, Cas },
   { 36750, 37200,  4020, Dra },
   { 20400, 21600,  3990, Dra },
   {     0,   600,  3960, Cep },
   { 25200, 28200,  3960, UMi },
   { 42450, 43200,  3960, Cep },
   { 21600, 24300,  3840, Dra },
   { 24300, 25950,  3780, Dra },
   { 41700, 42450,  3780, Cep },
   { 10980, 12600,  3720, Cam },
   { 36000, 36750,  3690, Dra },
   { 36966, 37080,  3655, Cep },
   { 12600, 14340,  3600, Cam },
   { 14340, 15150,  3600, UMa },
   { 35580, 36000,  3570, Dra },
   { 36000, 36966,  3570, Cep },
   { 41160, 41700,  3545, Cep },
   {     0,  4380,  3510, Cas },
   { 34950, 35580,  3480, Dra },
   {  3060,  3435,  3450, Cas },
   {  4380,  5580,  3420, Cas },
   {  5580,  5700,  3420, Cam },
   { 40170, 41160,  3375, Cep },
   {  9000, 10980,  3360, Cam },
   { 25260, 25950,  3330, UMa },
   { 25950, 34950,  3330, Dra },
   {  5700,  6000,  3300, Cam },
   { 39840, 40170,  3300, Cep },
   { 37080, 39540,  3290, Cep },
   {     0,  3060,  3240, Cas },
   { 10980, 11700,  3240, Lyn },
   { 21750, 24300,  3180, UMa },
   { 27450, 28350,  3180, Dra },
   { 39540, 39840,  3165, Cep },
   {  6000,  9000,  3150, Cam },
   { 41160, 42000,  3150, Cas },
   { 28350, 30600,  3090, Dra },
   {  3675,  4530,  3030, Per },
   { 30600, 32820,  3030, Dra },
   {     0,  2460,  3000, Cas },
   {  2460,  3000,  3000, Per },
   { 11700, 12240,  3000, Lyn },
   { 42000, 43200,  3000, Cas },
   { 24300, 25260,  2910, UMa },
   {     0,  2010,  2880, Cas },
   { 42450, 43200,  2880, Cas },
   { 32715, 32820,  2850, Her },
   { 32820, 34350,  2850, Dra },
   { 34350, 34500,  2850, Cyg },
   {  3000,  3675,  2820, Per },
   { 15150, 16500,  2820, UMa },
   {   300,  1560,  2760, Cas },
   { 21600, 21750,  2700, UMa },
   { 12240, 13260,  2670, Lyn },
   { 39435, 39540,  2640, Cyg },
   { 39375, 39435,  2625, Cyg },
   { 34500, 34920,  2610, Cyg },
   { 16500, 18300,  2520, UMa },
   { 18300, 19410,  2400, UMa },
   { 27780, 28350,  2400, Boo },
   { 28350, 29400,  2400, Her },
   { 16650, 17250,  2385, Lyn },
   {     0,  4530,  2205, And },
   {  4530,  4620,  2205, Per },
   { 34845, 34920,  2190, Lyr },
   {  8100,  8445,  2160, Per },
   { 39120, 39375,  2160, Cyg },
   { 39375, 39600,  2160, Lac },
   { 11760, 13260,  2130, Aur },
   { 13260, 13950,  2130, Lyn },
   {     0,  3600,  2100, And },
   { 39600, 41070,  2100, Lac },
   { 41070, 41160,  2070, Lac },
   { 41160, 42300,  2070, And },
   {  4620,  4890,  2040, Per },
   { 19410, 19800,  2040, UMa },
   { 21600, 22200,  2040, CVn },
   { 13950, 16650,  2010, Lyn },
   { 16650, 17790,  2010, LMi },
   {  1290,  2535,  1980, And },
   { 27330, 27780,  1980, Boo },
   { 42300, 42750,  1925, And },
   { 22200, 23850,  1920, CVn },
   { 42750, 43200,  1880, And },
   { 25125, 25260,  1845, CVn },
   {  4350,  4890,  1840, Tri },
   {  4890,  8100,  1840, Per },
   {  8100,  8550,  1800, Aur },
   { 32715, 34845,  1800, Lyr },
   { 19800, 21600,  1740, UMa },
   { 35400, 37650,  1740, Cyg },
   {  8550, 10590,  1710, Aur },
   { 17790, 18900,  1710, LMi },
   { 23850, 25125,  1710, CVn },
   {     0,   120,  1680, And },
   {  2535,  3000,  1680, Tri },
   { 10590, 11760,  1680, Aur },
   { 14190, 14400,  1680, Gem },
   { 37650, 39120,  1680, Cyg },
   { 34665, 35400,  1650, Cyg },
   {  3450,  4350,  1635, Tri },
   { 29100, 29400,  1620, CrB },
   { 27150, 27330,  1560, Boo },
   { 27330, 29100,  1560, CrB },
   { 33060, 33960,  1560, Lyr },
   { 19350, 19800,  1530, LMi },
   { 33960, 34665,  1530, Lyr },
   {  3000,  3450,  1500, Tri },
   {  1290,  1530,  1425, Psc },
   { 18900, 19350,  1410, LMi },
   { 38250, 38550,  1410, Vul },
   { 10260, 10590,  1370, Tau },
   {   120,   255,  1320, And },
   { 28650, 28860,  1320, Se1 },
   { 10590, 11190,  1290, Gem },
   { 35700, 36450,  1275, Vul },
   { 33960, 34650,  1265, Vul },
   {   255,  1530,  1260, And },
   { 36450, 37020,  1230, Vul },
   { 14055, 14190,  1200, Gem },
   { 37020, 38250,  1170, Vul },
   { 34650, 35700,  1150, Vul },
   {  5910,  6060,  1140, Ari },
   { 33960, 34200,  1110, Sge },
   { 10260, 10380,  1080, Ori },
   { 11190, 11355,  1050, Gem },
   { 34200, 35700,   970, Sge },
   {  8940,  9600,   960, Tau },
   { 28650, 28950,   960, Her },
   { 35700, 36450,   945, Sge },
   {  8310,  8940,   930, Tau },
   {  9600, 10080,   930, Tau },
   { 23100, 24300,   900, Com },
   { 31050, 32850,   860, Her },
   { 21360, 23100,   840, Com },
   { 13500, 14055,   810, Gem },
   { 30150, 31050,   770, Her },
   {     0,   255,   750, Peg },
   { 10080, 10380,   750, Tau },
   { 12600, 13500,   750, Gem },
   { 38010, 38400,   750, Peg },
   { 11355, 12480,   720, Gem },
   { 32850, 33960,   720, Her },
   { 37575, 37890,   710, Del },
   { 37890, 38010,   710, Peg },
   { 20730, 21360,   660, Leo },
   { 11235, 11355,   600, Ori },
   { 12480, 12600,   600, Gem },
   { 14055, 14265,   600, Cnc },
   { 42900, 43200,   600, Peg },
   {  3000,  5910,   595, Ari },
   { 36255, 36540,   510, Del },
   { 24300, 27150,   480, Boo },
   { 40950, 42900,   450, Peg },
   { 14265, 16650,   420, Cnc },
   { 16650, 19350,   420, Leo },
   { 32850, 33592,   375, Oph },
   { 33592, 33960,   375, Aql },
   { 37500, 37575,   360, Del },
   { 12600, 12630,   330, CMi },
   { 32850, 33165,   270, Se2 },
   { 28950, 30150,   240, Her },
   { 32850, 33165,   180, Oph },
   { 38640, 39000,   165, Peg },
   {     0,  3600,   120, Psc },
   { 33450, 33960,   120, Se2 },
   { 36540, 37500,   120, Del },
   { 37500, 38400,   120, Equ },
   { 38400, 38640,   120, Peg },
   { 39600, 40950,   120, Peg },
   { 39000, 39600,   105, Peg },
   { 12630, 12960,    90, CMi },
   {  6450,  8310,     0, Tau },
   {  8310,  8400,     0, Ori },
   { 12960, 14550,     0, CMi },
   { 26400, 27150,     0, Vir },
   { 32100, 32850,     0, Oph },
   {  4770,  5910,  -105, Cet },
   {  5910,  6450,  -105, Tau },
   { 27150, 29280,  -195, Se1 },
   {  8400,  9150,  -240, Ori },
   { 10500, 11235,  -240, Ori },
   { 32100, 32340,  -240, Se2 },
   { 32850, 33450,  -240, Se2 },
   { 33450, 33960,  -240, Aql },
   { 40950, 42900,  -240, Psc },
   { 19350, 20730,  -360, Leo },
   { 20730, 21300,  -360, Vir },
   {     0,   600,  -420, Psc },
   { 42900, 43200,  -420, Psc },
   { 25650, 26400,  -480, Vir },
   { 28650, 29280,  -480, Oph },
   { 36000, 36960,  -540, Aql },
   { 38400, 39360,  -540, Aqr },
   { 30900, 32340,  -600, Oph },
   { 10500, 14550,  -660, Mon },
   {  8850,  9150,  -660, Eri },
   {  9150, 10500,  -660, Ori },
   { 14550, 15060,  -660, Hya },
   { 17250, 19350,  -660, Sex },
   { 21300, 23100,  -660, Vir },
   { 31650, 31800,  -700, Oph },
   { 33960, 36000,  -722, Aql },
   {  8700,  8850,  -870, Eri },
   { 36960, 38400,  -900, Aqr },
   { 30900, 32850,  -960, Se2 },
   { 32850, 33960,  -960, Sct },
   { 15060, 15450, -1020, Hya },
   { 29280, 29475, -1095, Oph },
   { 15450, 16350, -1140, Hya },
   { 19350, 19500, -1140, Crt },
   { 29280, 29475, -1155, Sco },
   { 28200, 28650, -1200, Lib },
   { 22650, 23100, -1320, Crv },
   { 23100, 25650, -1320, Vir },
   { 16350, 17550, -1440, Hya },
   {  3000,  4770, -1463, Cet },
   {  4770,  6750, -1463, Eri },
   { 19500, 21300, -1470, Crt },
   { 21300, 22650, -1470, Crv },
   { 25650, 26850, -1470, Lib },
   { 29280, 30150, -1475, Oph },
   {     0,  3000, -1530, Cet },
   { 38400, 39360, -1530, Cap },
   { 39360, 42900, -1530, Aqr },
   { 42900, 43200, -1530, Cet },
   { 17550, 18450, -1590, Hya },
   {  8460,  8700, -1635, Eri },
   {  8700, 11010, -1635, Lep },
   { 36000, 38400, -1680, Cap },
   { 18450, 19050, -1750, Hya },
   { 22650, 26850, -1770, Hya },
   { 26850, 28200, -1770, Lib },
   { 28200, 28800, -1770, Sco },
   {  8250,  8460, -1800, Eri },
   { 30150, 31680, -1800, Oph },
   { 31680, 32100, -1800, Sgr },
   { 19050, 19500, -1870, Hya },
   { 11010, 13260, -1980, CMa },
   { 22050, 22650, -1980, Hya },
   { 19500, 22050, -2100, Hya },
   {  6300,  6750, -2160, For },
   { 15060, 16860, -2205, Pyx },
   {  7680,  8250, -2220, Eri },
   { 32100, 34500, -2220, Sgr },
   { 38400, 41400, -2220, PsA },
   { 41400, 42000, -2220, Scl },
   {  5400,  6300, -2375, For },
   { 16860, 19800, -2385, Ant },
   {     0,  3000, -2400, Scl },
   {  3000,  5400, -2400, For },
   {  6960,  7680, -2400, Eri },
   { 42000, 43200, -2400, Scl },
   { 25500, 26850, -2520, Cen },
   { 28200, 28800, -2520, Lup },
   { 28800, 29557, -2520, Sco },
   {  8700,  9000, -2580, Cae },
   {  9000, 11850, -2580, Col },
   { 14400, 15060, -2580, Pup },
   {  6150,  6960, -2640, Eri },
   { 29557, 32100, -2730, Sco },
   { 32100, 34500, -2730, CrA },
   { 34500, 36600, -2730, Sgr },
   { 36600, 38400, -2730, Mic },
   {  5400,  6150, -2760, Eri },
   {  8100,  8700, -2790, Cae },
   { 27600, 28200, -2880, Lup },
   {     0,  4200, -2890, Phe },
   {  4800,  5400, -2940, Eri },
   {  7350,  7680, -2940, Hor },
   {  7680,  8100, -2940, Cae },
   { 38400, 39600, -3000, Gru },
   { 10800, 14400, -3045, Pup },
   { 14400, 14700, -3045, Vel },
   {  4350,  4800, -3060, Eri },
   {  6900,  7350, -3060, Hor },
   {     0,  3300, -3090, Phe },
   { 10800, 11100, -3150, Car },
   { 14700, 15210, -3180, Vel },
   {  6300,  6900, -3190, Hor },
   {  6900,  7200, -3190, Dor },
   {     0,  2850, -3210, Phe },
   {  3900,  4350, -3240, Eri },
   {  8100,  9000, -3240, Pic },
   { 27090, 27600, -3240, Lup },
   { 15210, 15900, -3270, Vel },
   { 11100, 11700, -3300, Car },
   { 21300, 23100, -3300, Cen },
   { 25500, 27090, -3300, Lup },
   { 27090, 27600, -3300, Nor },
   {  7200,  7800, -3390, Dor },
   { 15900, 19800, -3390, Vel },
   { 19800, 20250, -3390, Cen },
   { 31500, 32400, -3420, Ara },
   { 32400, 36600, -3420, Tel },
   { 39600, 42000, -3420, Gru },
   {  5760,  6300, -3450, Hor },
   {  9000,  9900, -3450, Pic },
   { 11700, 12300, -3480, Car },
   {     0,  2400, -3510, Phe },
   {  2400,  3900, -3510, Eri },
   { 42000, 43200, -3510, Phe },
   {  7800,  8250, -3540, Dor },
   { 27600, 29557, -3600, Nor },
   { 36600, 38400, -3600, Ind },
   {  9900, 10800, -3660, Pic },
   { 27300, 27600, -3660, Cir },
   { 29557, 29850, -3660, Ara },
   { 26850, 27300, -3815, Cir },
   { 29850, 30150, -3815, Ara },
   { 10800, 12300, -3840, Pic },
   { 12300, 16260, -3840, Car },
   { 20250, 21300, -3840, Cen },
   { 21300, 23100, -3840, Cru },
   { 23100, 26160, -3840, Cen },
   { 24300, 24600, -3900, Cir },
   { 30150, 30300, -3900, Ara },
   {  3900,  5760, -4050, Hor },
   {  5760,  8250, -4050, Ret },
   { 26550, 26850, -4050, Cir },
   { 30300, 31500, -4050, Ara },
   { 31500, 32400, -4050, Pav },
   { 39600, 42000, -4050, Tuc },
   {  8250, 11850, -4200, Dor },
   { 24600, 26550, -4200, Cir },
   { 26550, 30600, -4200, TrA },
   {     0,  2400, -4500, Tuc },
   {  6300,  8250, -4500, Hyi },
   { 11850, 16260, -4500, Vol },
   { 16260, 20250, -4500, Car },
   { 20250, 24600, -4500, Mus },
   { 32400, 38400, -4500, Pav },
   { 38400, 42000, -4500, Ind },
   { 42000, 43200, -4500, Tuc },
   {  1350,  2400, -4560, Tuc },
   {     0,  6300, -4950, Hyi },
   { 13800, 24600, -4950, Cha },
   { 24600, 32400, -4950, Aps },
   {  6300, 13800, -5100, Men },
   {     0, 43200, -5400, Oct }
};

static short start[] = {
   355, 352, 343, 340, 332, 320,
   303, 288, 277, 266, 257, 251,
   239, 229, 221, 211, 203, 189,
   177, 163, 149, 136, 124, 104,
    87,  75,  69,  54,  43,  29,
    23,  16,  12,   6,   4,   0,   0
};


/*
======================================================================
constellation_pick()

Do a constellation pick from RA and Dec.

INPUTS
   r        right ascension, radians
   d        declination, radians
   e        epoch to which r and d precessed, as an mjd

RESULTS
   Returns an index for the constellation region that the coordinates
   belong to, or -1 if no constellation pick can be found.

The constellation is identified by linear search.  We look for a
member of cbound[] whose lower_dec is less than the declination of the
pick point and whose lower_ra and upper_ra bracket the pick point's
right ascension.  The data for that cbound[] member describes a sub-
region belonging to the picked constellation.

In geometric terms, the search amounts to starting at the north pole
and traveling south on a line of constant right ascension through the
pick point.  At every declination where a cbound[] member lives, we
wake up, and if (1) the pick point is now behind us, and (2) the
cbound[] segment is crossing our path, we know we've hit the edge of
a constellation subregion that the pick point belongs to.

The cbound[] right ascension and declination values are scaled into
integers; this conserves storage and makes comparisons faster.  The
start[] array, which gives starting points in cbound[] for different
declinations in 5-degree increments, further speeds the search by
skipping early parts of the list for which we know the search can't
succeed--geometrically, we start no more than 5 degrees north of the
pick point, rather than at the north pole.

The data in cbound[] are for epoch 1875.
======================================================================
*/

int
cns_pick(double r, double d, double e)
{
   double Mjd;
   unsigned short ra;
   short de, i;

   cal_mjd( 1, 1.0, 1875, &Mjd );
   precess( e, Mjd, &r, &d );
   ra = ( unsigned short )( radhr( r ) * 1800 );
   de = ( short )( raddeg( d ) * 60 );
   if (d < 0.0) --de;

   i = ( de + 5400 ) / 300;
   if ( i < 0 || i > 36 ) return -1;
   i = start[ i ];

   for ( ; i < NBOUNDS; i++ )
      if ( cbound[ i ].lower_dec <= de &&
           cbound[ i ].upper_ra   > ra &&
           cbound[ i ].lower_ra  <= ra ) break;

   return ( i == NBOUNDS ) ? -1 : ( int ) cbound[ i ].index;
}

/* given a constellation id (as from cns_pick()), return pointer to static
 * storage containg its name in the form "AAA: Name".
 * return "???: ???" if id is invalid.
 */
char *
cns_name (int id)
{
	if (id < 0 || id >= NCNS)
	    return ("???: ???");
	return (cns_namemap[id]);
}

/* return cns_namemap index matching first three chars in abbrev[], else -1.
 */
int
cns_id (char *abbrev)
{
	int i;

	for (i = 0; i < NCNS; i++)
	    if (strncmp (abbrev, cns_namemap[i], 3) == 0)
		return (i);
	return (-1);
}

/* edges of constant ra */
static struct {
   unsigned short ra;	/* hours * 1800 */
   short dec0, dec1;	/* degrees * 60 */
} ra_edges[] = {
    {     0, -4950, -4500 },
    {     0,   600,   750 },
    {     0,  1680,  1879 },
    {   120,  1320,  1680 },
    {   255,   750,  1260 },
    {   255,  1260,  1320 },
    {   300,  2760,  2880 },
    {   599,  -420,     0 },
    {   599,     0,   120 },
    {   599,  3960,  4620 },
    {  1290,  1425,  1980 },
    {  1350, -4500, -4560 },
    {  1530,  1260,  1425 },
    {  1560,  2760,  2880 },
    {  2010,  2880,  3000 },
    {  2399, -4560, -3510 },
    {  2399, -3510, -3210 },
    {  2460,  3000,  3240 },
    {  2534,  1680,  1980 },
    {  2534,  1980,  2100 },
    {  2849, -3210, -3090 },
    {  3000, -2400, -1530 },
    {  3000, -1530, -1462 },
    {  3000,   595,  1500 },
    {  3000,  1500,  1680 },
    {  3000,  2820,  3000 },
    {  3060,  3240,  3450 },
    {  3299, -3090, -2890 },
    {  3434,  3450,  3510 },
    {  3450,  1500,  1635 },
    {  3600,   120,   595 },
    {  3600,  2100,  2205 },
    {  3675,  2820,  3030 },
    {  3900, -4050, -3510 },
    {  3900, -3510, -3240 },
    {  4199, -2890, -2400 },
    {  4350, -3240, -3060 },
    {  4350,  1635,  1840 },
    {  4379,  3420,  3510 },
    {  4530,  2205,  3030 },
    {  4620,  2040,  2205 },
    {  4770, -1462,  -105 },
    {  4800, -3060, -2940 },
    {  4890,  1840,  2040 },
    {  5400, -2940, -2760 },
    {  5400, -2400, -2374 },
    {  5580,  3420,  4080 },
    {  5700,  3300,  3420 },
    {  5760, -3450, -4050 },
    {  5909,  -105,     0 },
    {  5909,     0,   595 },
    {  5909,   595,  1140 },
    {  5999,  3150,  3300 },
    {  6060,  1140,  1840 },
    {  6150, -2760, -2640 },
    {  6150,  4080,  4620 },
    {  6300, -5100, -4950 },
    {  6300, -4950, -4500 },
    {  6300, -3190, -3450 },
    {  6300, -2374, -2160 },
    {  6314,  4620,  4800 },
    {  6449,  -105,     0 },
    {  6750, -2160, -1462 },
    {  6899, -3060, -3190 },
    {  6960, -2640, -2400 },
    {  7200, -3390, -3190 },
    {  7349, -2940, -3060 },
    {  7680, -2400, -2940 },
    {  7680, -2220, -2400 },
    {  7799, -3540, -3390 },
    {  8100, -3240, -2940 },
    {  8100, -2940, -2790 },
    {  8100,  1800,  1840 },
    {  8100,  1840,  2160 },
    {  8249, -4500, -4200 },
    {  8249, -4050, -4200 },
    {  8249, -4050, -3540 },
    {  8249, -1800, -2220 },
    {  8310,     0,   930 },
    {  8400,  -240,     0 },
    {  8445,  2160,  3150 },
    {  8460, -1635, -1800 },
    {  8550,  1710,  1800 },
    {  8699, -2790, -2580 },
    {  8699,  -870, -1635 },
    {  8850,  -660,  -870 },
    {  8940,   930,   960 },
    {  9000, -3450, -3240 },
    {  9000, -2580, -1635 },
    {  9000,  3150,  3360 },
    {  9000,  4800,  5100 },
    {  9149,  -660,  -240 },
    {  9599,   930,   960 },
    {  9900, -3660, -3450 },
    { 10080,   750,   930 },
    { 10260,  1080,  1369 },
    { 10380,   750,  1080 },
    { 10499,  -660,  -240 },
    { 10589,  1290,  1369 },
    { 10589,  1369,  1680 },
    { 10589,  1680,  1710 },
    { 10800, -3840, -3660 },
    { 10800, -3150, -3045 },
    { 10800, -3045, -2580 },
    { 10980,  3240,  3360 },
    { 10980,  3360,  3720 },
    { 11010, -1980, -1635 },
    { 11010, -1635,  -660 },
    { 11100, -3300, -3150 },
    { 11190,  1050,  1290 },
    { 11235,  -240,     0 },
    { 11235,     0,   600 },
    { 11354,   600,   720 },
    { 11354,   720,  1050 },
    { 11700, -3480, -3300 },
    { 11700,  3000,  3240 },
    { 11759,  1680,  2130 },
    { 11849, -4200, -4500 },
    { 11849, -4200, -3840 },
    { 11849, -1980, -2580 },
    { 12240,  2670,  3000 },
    { 12299, -3840, -3480 },
    { 12479,   600,   720 },
    { 12600,   330,   600 },
    { 12600,   600,   750 },
    { 12600,  3600,  3720 },
    { 12630,    90,   330 },
    { 12960,     0,    90 },
    { 13260,  -660, -1980 },
    { 13260,  2130,  2670 },
    { 13500,   750,   810 },
    { 13800, -5100, -4950 },
    { 13800, -4500, -4950 },
    { 13950,  2010,  2130 },
    { 14054,   600,   810 },
    { 14054,   810,  1200 },
    { 14189,  1200,  1680 },
    { 14265,   420,   600 },
    { 14340,  3600,  4410 },
    { 14400, -3045, -2580 },
    { 14400,  1680,  2010 },
    { 14400,  5100,  5190 },
    { 14400,  5280,  5190 },
    { 14549,  -660,     0 },
    { 14549,     0,   420 },
    { 14700, -3180, -3045 },
    { 15060, -2580, -2205 },
    { 15060, -2205, -1020 },
    { 15060, -1020,  -660 },
    { 15150,  2820,  3600 },
    { 15209, -3270, -3180 },
    { 15449, -1140, -1020 },
    { 15899, -3390, -3270 },
    { 16259, -4500, -3840 },
    { 16349, -1440, -1140 },
    { 16500,  2520,  2820 },
    { 16500,  4410,  4920 },
    { 16650,   420,  2010 },
    { 16650,  2010,  2385 },
    { 16860, -2385, -2205 },
    { 16860, -1440, -2205 },
    { 17249,  -660,     0 },
    { 17249,     0,   420 },
    { 17249,  2385,  2520 },
    { 17550, -1590, -1440 },
    { 17789,  1710,  2010 },
    { 18300,  2400,  2520 },
    { 18450, -1750, -1590 },
    { 18900,  1410,  1710 },
    { 19049, -1870, -1750 },
    { 19200,  4800,  4920 },
    { 19350,  -660, -1140 },
    { 19350,  -360,  -660 },
    { 19350,  -360,     0 },
    { 19350,     0,   420 },
    { 19350,  1410,  1530 },
    { 19409,  2040,  2400 },
    { 19499, -2100, -1870 },
    { 19499, -1140, -1470 },
    { 19800, -3390, -2385 },
    { 19800, -2385, -2100 },
    { 19800,  1530,  1740 },
    { 19800,  1740,  2040 },
    { 20250, -4500, -3840 },
    { 20250, -3840, -3390 },
    { 20399,  3990,  4410 },
    { 20700,  4620,  4800 },
    { 20730,  -360,     0 },
    { 20730,     0,   660 },
    { 21299, -3840, -3300 },
    { 21299, -1470,  -660 },
    { 21299,  -660,  -360 },
    { 21360,   660,   840 },
    { 21360,   840,  1740 },
    { 21600,  1740,  2040 },
    { 21600,  2040,  2700 },
    { 21600,  3840,  3990 },
    { 21749,  2700,  3180 },
    { 22050, -1980, -2100 },
    { 22199,  1920,  2040 },
    { 22649, -1770, -1980 },
    { 22649, -1470, -1320 },
    { 23099, -3840, -3300 },
    { 23099, -1320,  -660 },
    { 23099,   840,   900 },
    { 23400,  4620,  4200 },
    { 23850,  1710,  1920 },
    { 24300, -3900, -3840 },
    { 24300,   480,   900 },
    { 24300,   900,  1710 },
    { 24300,  2910,  3180 },
    { 24300,  3780,  3840 },
    { 24449,  4800,  4620 },
    { 24600, -4950, -4500 },
    { 24600, -4500, -4200 },
    { 24600, -4200, -3900 },
    { 25124,  1710,  1845 },
    { 25200,  4200,  3960 },
    { 25259,  1845,  2910 },
    { 25259,  2910,  3330 },
    { 25500, -3300, -2520 },
    { 25650, -1320, -1470 },
    { 25650,  -480, -1320 },
    { 25950,  3330,  3780 },
    { 26100,  5190,  4800 },
    { 26159, -3840, -3300 },
    { 26400,     0,  -480 },
    { 26550, -4200, -4050 },
    { 26850, -4050, -3814 },
    { 26850, -2520, -1770 },
    { 26850, -1470, -1770 },
    { 27090, -3300, -3240 },
    { 27149,  -195,     0 },
    { 27149,     0,   480 },
    { 27149,   480,  1560 },
    { 27300, -3814, -3660 },
    { 27329,  1560,  1980 },
    { 27450,  3180,  3330 },
    { 27599, -3660, -3600 },
    { 27599, -3600, -3300 },
    { 27599, -3240, -2880 },
    { 27779,  1980,  2400 },
    { 28200, -2880, -2520 },
    { 28200, -1770, -1200 },
    { 28200,  3960,  4200 },
    { 28350,  2400,  3090 },
    { 28350,  3090,  3180 },
    { 28650, -1200,  -480 },
    { 28650,  -480,  -195 },
    { 28650,   960,  1320 },
    { 28800, -2520, -1770 },
    { 28859,  1320,  1560 },
    { 28949,   240,   960 },
    { 29100,  1560,  1620 },
    { 29280, -1474, -1155 },
    { 29280, -1095,  -480 },
    { 29280,  -195,     0 },
    { 29280,     0,   240 },
    { 29399,  1620,  2400 },
    { 29475, -1155, -1095 },
    { 29557, -3660, -3600 },
    { 29557, -3600, -2730 },
    { 29557, -2730, -2520 },
    { 29759,  4200,  4500 },
    { 29849, -3814, -3660 },
    { 30150, -3900, -3814 },
    { 30150, -1800, -1474 },
    { 30150,   240,   769 },
    { 30299, -4050, -3900 },
    { 30600, -4050, -4200 },
    { 30600,  3030,  3090 },
    { 30900,  -960,  -600 },
    { 31050,   769,   859 },
    { 31500, -3420, -4050 },
    { 31500,  4500,  4800 },
    { 31649,  -700,  -600 },
    { 31680,  -960, -1800 },
    { 31800,  -700,  -600 },
    { 32099, -2730, -2220 },
    { 32099, -1800, -2220 },
    { 32099,  -240,     0 },
    { 32340,  -600,  -240 },
    { 32400, -4950, -4500 },
    { 32400, -4500, -4050 },
    { 32400, -2730, -3420 },
    { 32400,  4800,  5160 },
    { 32715,  1800,  2850 },
    { 32819,  2850,  3030 },
    { 32850,  -240,  -960 },
    { 32850,     0,   180 },
    { 32850,   270,   375 },
    { 32850,   720,   859 },
    { 33060,  1560,  1800 },
    { 33165,   180,   270 },
    { 33449,  -240,     0 },
    { 33449,     0,   120 },
    { 33591,   375,   720 },
    { 33960,  -960,  -721 },
    { 33960,  -721,  -240 },
    { 33960,   120,   375 },
    { 33960,   720,  1110 },
    { 33960,  1110,  1264 },
    { 33960,  1264,  1530 },
    { 33960,  1530,  1560 },
    { 34200,   970,  1110 },
    { 34349,  2850,  3330 },
    { 34500, -2220, -2730 },
    { 34500,  2610,  2850 },
    { 34650,  1150,  1264 },
    { 34664,  1530,  1650 },
    { 34664,  1650,  1800 },
    { 34844,  1800,  2190 },
    { 34920,  2190,  2610 },
    { 34950,  3330,  3480 },
    { 35400,  1650,  1740 },
    { 35580,  3480,  3570 },
    { 35699,   945,   970 },
    { 35699,  1150,  1275 },
    { 36000, -1680,  -721 },
    { 36000,  -540,  -721 },
    { 36000,  3570,  3690 },
    { 36255,   510,   945 },
    { 36300,  4500,  4800 },
    { 36450,   945,  1230 },
    { 36450,  1230,  1275 },
    { 36540,   120,   510 },
    { 36599, -3600, -3420 },
    { 36599, -3420, -2730 },
    { 36599, -2730, -1680 },
    { 36750,  3690,  4020 },
    { 36959,  -900,  -540 },
    { 36959,  -540,     0 },
    { 36959,     0,   120 },
    { 36966,  3570,  3655 },
    { 37020,  1170,  1230 },
    { 37080,  3289,  3655 },
    { 37200,  4020,  4500 },
    { 37499,   120,   360 },
    { 37575,   360,   709 },
    { 37650,  1680,  1740 },
    { 37800,  4800,  5160 },
    { 37800,  5160,  5169 },
    { 37890,   709,  1170 },
    { 38010,   709,   750 },
    { 38250,  1170,  1410 },
    { 38399, -4500, -3600 },
    { 38399, -3000, -2730 },
    { 38399, -2220, -2730 },
    { 38399, -1680, -2220 },
    { 38399, -1680, -1530 },
    { 38399,  -540,  -900 },
    { 38399,   120,   750 },
    { 38550,  1410,  1680 },
    { 38640,   120,   165 },
    { 39000,   105,   165 },
    { 39119,  1680,  2160 },
    { 39360, -1530,  -540 },
    { 39375,  2160,  2625 },
    { 39434,  2625,  2640 },
    { 39540,  2640,  3165 },
    { 39540,  3165,  3289 },
    { 39600, -4050, -3420 },
    { 39600, -3420, -3000 },
    { 39600,   105,   120 },
    { 39600,  2100,  2160 },
    { 39839,  3165,  3300 },
    { 40170,  3300,  3375 },
    { 40950,  -240,     0 },
    { 40950,     0,   120 },
    { 40950,   120,   450 },
    { 41070,  2070,  2100 },
    { 41160,  2070,  3150 },
    { 41160,  3150,  3375 },
    { 41160,  3375,  3544 },
    { 41400, -2220, -1530 },
    { 41400,  5169,  5280 },
    { 41700,  3544,  3780 },
    { 41999, -4500, -4050 },
    { 41999, -3510, -3420 },
    { 41999, -3420, -2400 },
    { 41999, -2400, -2220 },
    { 41999,  3000,  3150 },
    { 42300,  1924,  2070 },
    { 42449,  2880,  3000 },
    { 42449,  3780,  3960 },
    { 42750,  1879,  1924 },
    { 42899, -1530,  -420 },
    { 42899,  -420,  -240 },
    { 42899,   450,   600 },
};

#define	NRA	((int)(sizeof(ra_edges)/sizeof(ra_edges[0])))

/* edges of constant dec */
static struct {
   short dec;			/* degrees * 60 */
   unsigned short ra0, ra1;	/* hours * 1800 */
} dec_edges[] = {
    { -5100,  6300, 13800 },
    { -4950,     0,  6300 },
    { -4950, 13800, 24600 },
    { -4950, 24600, 32400 },
    { -4560,  1350,  2399 },
    { -4500,     0,  1350 },
    { -4500,  6300,  8249 },
    { -4500, 11849, 13800 },
    { -4500, 13800, 16259 },
    { -4500, 16259, 20250 },
    { -4500, 20250, 24600 },
    { -4500, 32400, 38399 },
    { -4500, 38399, 41999 },
    { -4500, 41999,     0 },
    { -4200,  8249, 11849 },
    { -4200, 24600, 26550 },
    { -4200, 30600, 26550 },
    { -4050,  3900,  5760 },
    { -4050,  5760,  8249 },
    { -4050, 26550, 26850 },
    { -4050, 30299, 30600 },
    { -4050, 31500, 30600 },
    { -4050, 31500, 32400 },
    { -4050, 39600, 41999 },
    { -3900, 24300, 24600 },
    { -3900, 30150, 30299 },
    { -3840, 10800, 11849 },
    { -3840, 11849, 12299 },
    { -3840, 12299, 16259 },
    { -3840, 20250, 21299 },
    { -3840, 21299, 23099 },
    { -3840, 23099, 24300 },
    { -3840, 24300, 26159 },
    { -3814, 26850, 27300 },
    { -3814, 29849, 30150 },
    { -3660,  9900, 10800 },
    { -3660, 27300, 27599 },
    { -3660, 29557, 29849 },
    { -3600, 27599, 29557 },
    { -3600, 36599, 38399 },
    { -3540,  7799,  8249 },
    { -3510,  2399,  3900 },
    { -3510,  2399, 41999 },
    { -3510,  3900,  2399 },
    { -3510, 41999,  2399 },
    { -3480, 11700, 12299 },
    { -3450,  6300,  5760 },
    { -3450,  9000,  9900 },
    { -3420, 32400, 31500 },
    { -3420, 32400, 36599 },
    { -3420, 39600, 41999 },
    { -3390,  7200,  7799 },
    { -3390, 15899, 19800 },
    { -3390, 19800, 20250 },
    { -3300, 11100, 11700 },
    { -3300, 21299, 23099 },
    { -3300, 25500, 26159 },
    { -3300, 26159, 27090 },
    { -3300, 27090, 27599 },
    { -3270, 15209, 15899 },
    { -3240,  3900,  4350 },
    { -3240,  8100,  9000 },
    { -3240, 27090, 27599 },
    { -3210,  2399,  2849 },
    { -3190,  6899,  6300 },
    { -3190,  6899,  7200 },
    { -3180, 14700, 15209 },
    { -3150, 10800, 11100 },
    { -3090,  2849,  3299 },
    { -3060,  4350,  4800 },
    { -3060,  7349,  6899 },
    { -3045, 10800, 14400 },
    { -3045, 14400, 14700 },
    { -3000, 38399, 39600 },
    { -2940,  4800,  5400 },
    { -2940,  7680,  7349 },
    { -2940,  7680,  8100 },
    { -2890,  3299,  4199 },
    { -2880, 27599, 28200 },
    { -2790,  8100,  8699 },
    { -2760,  5400,  6150 },
    { -2730, 29557, 32099 },
    { -2730, 32099, 32400 },
    { -2730, 34500, 32400 },
    { -2730, 34500, 36599 },
    { -2730, 38399, 36599 },
    { -2640,  6150,  6960 },
    { -2580,  8699,  9000 },
    { -2580, 10800,  9000 },
    { -2580, 11849, 10800 },
    { -2580, 14400, 15060 },
    { -2520, 25500, 26850 },
    { -2520, 28200, 28800 },
    { -2520, 29557, 28800 },
    { -2400,  3000, 41999 },
    { -2400,  4199,  3000 },
    { -2400,  4199,  5400 },
    { -2400,  6960,  7680 },
    { -2385, 16860, 19800 },
    { -2374,  5400,  6300 },
    { -2220,  8249,  7680 },
    { -2220, 32099, 34500 },
    { -2220, 38399, 41400 },
    { -2220, 41999, 41400 },
    { -2205, 16860, 15060 },
    { -2160,  6300,  6750 },
    { -2100, 19800, 19499 },
    { -2100, 22050, 19800 },
    { -1980, 11010, 11849 },
    { -1980, 13260, 11849 },
    { -1980, 22649, 22050 },
    { -1870, 19499, 19049 },
    { -1800,  8460,  8249 },
    { -1800, 30150, 31680 },
    { -1800, 31680, 32099 },
    { -1770, 26850, 22649 },
    { -1770, 26850, 28200 },
    { -1770, 28800, 28200 },
    { -1750, 19049, 18450 },
    { -1680, 36000, 36599 },
    { -1680, 36599, 38399 },
    { -1635,  8699,  8460 },
    { -1635,  8699,  9000 },
    { -1635,  9000, 11010 },
    { -1590, 18450, 17550 },
    { -1530,  3000, 42899 },
    { -1530, 38399, 39360 },
    { -1530, 41400, 39360 },
    { -1530, 41400, 42899 },
    { -1530, 42899,  3000 },
    { -1530, 42899, 41400 },
    { -1474, 29280, 30150 },
    { -1470, 19499, 21299 },
    { -1470, 21299, 22649 },
    { -1470, 25650, 26850 },
    { -1462,  3000,  4770 },
    { -1462,  4770,  6750 },
    { -1440, 16349, 16860 },
    { -1440, 17550, 16860 },
    { -1320, 22649, 23099 },
    { -1320, 23099, 25650 },
    { -1200, 28200, 28650 },
    { -1155, 29280, 29475 },
    { -1140, 15449, 16349 },
    { -1140, 19350, 19499 },
    { -1095, 29280, 29475 },
    { -1020, 15060, 15449 },
    {  -960, 30900, 31680 },
    {  -960, 32850, 31680 },
    {  -960, 32850, 33960 },
    {  -900, 38399, 36959 },
    {  -870,  8850,  8699 },
    {  -721, 36000, 33960 },
    {  -700, 31649, 31800 },
    {  -660,  9149,  8850 },
    {  -660, 10499,  9149 },
    {  -660, 11010, 10499 },
    {  -660, 11010, 13260 },
    {  -660, 14549, 13260 },
    {  -660, 15060, 14549 },
    {  -660, 17249, 19350 },
    {  -660, 23099, 21299 },
    {  -600, 30900, 31649 },
    {  -600, 31800, 32340 },
    {  -540, 36959, 36000 },
    {  -540, 39360, 38399 },
    {  -480, 26400, 25650 },
    {  -480, 28650, 29280 },
    {  -420,   599, 42899 },
    {  -360, 20730, 19350 },
    {  -360, 21299, 20730 },
    {  -240,  8400,  9149 },
    {  -240, 10499, 11235 },
    {  -240, 32099, 32340 },
    {  -240, 33449, 32850 },
    {  -240, 33960, 33449 },
    {  -240, 40950, 42899 },
    {  -195, 28650, 27149 },
    {  -195, 28650, 29280 },
    {  -105,  4770,  5909 },
    {  -105,  5909,  6449 },
    {     0,  6449,  8310 },
    {     0,  8310,  8400 },
    {     0, 12960, 14549 },
    {     0, 27149, 26400 },
    {     0, 32099, 32850 },
    {    90, 12630, 12960 },
    {   105, 39000, 39600 },
    {   120,   599,  3600 },
    {   120, 33449, 33960 },
    {   120, 36540, 36959 },
    {   120, 36959, 37499 },
    {   120, 37499, 38399 },
    {   120, 38399, 38640 },
    {   120, 39600, 40950 },
    {   165, 38640, 39000 },
    {   180, 32850, 33165 },
    {   240, 28949, 29280 },
    {   240, 29280, 30150 },
    {   270, 33165, 32850 },
    {   330, 12600, 12630 },
    {   360, 37499, 37575 },
    {   375, 32850, 33591 },
    {   375, 33591, 33960 },
    {   420, 14265, 14549 },
    {   420, 14549, 16650 },
    {   420, 16650, 17249 },
    {   420, 17249, 19350 },
    {   450, 40950, 42899 },
    {   480, 24300, 27149 },
    {   510, 36255, 36540 },
    {   595,  3000,  3600 },
    {   595,  3600,  5909 },
    {   600,     0, 42899 },
    {   600, 11235, 11354 },
    {   600, 12479, 12600 },
    {   600, 14054, 14265 },
    {   600, 42899,     0 },
    {   660, 20730, 21360 },
    {   709, 37575, 37890 },
    {   709, 37890, 38010 },
    {   720, 11354, 12479 },
    {   720, 32850, 33591 },
    {   720, 33591, 33960 },
    {   750,     0,   255 },
    {   750, 10080, 10380 },
    {   750, 12600, 13500 },
    {   750, 38010, 38399 },
    {   769, 30150, 31050 },
    {   810, 13500, 14054 },
    {   840, 21360, 23099 },
    {   859, 31050, 32850 },
    {   900, 23099, 24300 },
    {   930,  8310,  8940 },
    {   930,  9599, 10080 },
    {   945, 35699, 36255 },
    {   945, 36255, 36450 },
    {   960,  8940,  9599 },
    {   960, 28650, 28949 },
    {   970, 34200, 35699 },
    {  1050, 11190, 11354 },
    {  1080, 10260, 10380 },
    {  1110, 33960, 34200 },
    {  1140,  5909,  6060 },
    {  1150, 34650, 35699 },
    {  1170, 37020, 37890 },
    {  1170, 37890, 38250 },
    {  1200, 14054, 14189 },
    {  1230, 36450, 37020 },
    {  1260,   255,  1530 },
    {  1264, 33960, 34650 },
    {  1275, 35699, 36450 },
    {  1290, 10589, 11190 },
    {  1320,   120,   255 },
    {  1320, 28650, 28859 },
    {  1369, 10260, 10589 },
    {  1410, 18900, 19350 },
    {  1410, 38250, 38550 },
    {  1425,  1290,  1530 },
    {  1500,  3000,  3450 },
    {  1530, 19350, 19800 },
    {  1530, 33960, 34664 },
    {  1560, 27149, 27329 },
    {  1560, 27329, 28859 },
    {  1560, 28859, 29100 },
    {  1560, 33060, 33960 },
    {  1620, 29100, 29399 },
    {  1635,  3450,  4350 },
    {  1650, 34664, 35400 },
    {  1680,     0,   120 },
    {  1680,  2534,  3000 },
    {  1680, 10589, 11759 },
    {  1680, 14189, 14400 },
    {  1680, 37650, 38550 },
    {  1680, 38550, 39119 },
    {  1710,  8550, 10589 },
    {  1710, 17789, 18900 },
    {  1710, 23850, 24300 },
    {  1710, 24300, 25124 },
    {  1740, 19800, 21360 },
    {  1740, 21360, 21600 },
    {  1740, 35400, 37650 },
    {  1800,  8100,  8550 },
    {  1800, 32715, 33060 },
    {  1800, 34664, 34844 },
    {  1840,  4350,  4890 },
    {  1840,  4890,  6060 },
    {  1840,  6060,  8100 },
    {  1845, 25124, 25259 },
    {  1879,     0, 42750 },
    {  1920, 22199, 23850 },
    {  1924, 42300, 42750 },
    {  1980,  1290,  2534 },
    {  1980, 27329, 27779 },
    {  2010, 13950, 14400 },
    {  2010, 14400, 16650 },
    {  2010, 16650, 17789 },
    {  2040,  4620,  4890 },
    {  2040, 19409, 19800 },
    {  2040, 21600, 22199 },
    {  2070, 41070, 41160 },
    {  2070, 41160, 42300 },
    {  2100,  2534,  3600 },
    {  2100, 39600, 41070 },
    {  2130, 11759, 13260 },
    {  2130, 13260, 13950 },
    {  2160,  8100,  8445 },
    {  2160, 39119, 39375 },
    {  2160, 39375, 39600 },
    {  2190, 34844, 34920 },
    {  2205,  3600,  4530 },
    {  2205,  4530,  4620 },
    {  2385, 16650, 17249 },
    {  2400, 18300, 19409 },
    {  2400, 27779, 28350 },
    {  2400, 28350, 29399 },
    {  2520, 16500, 17249 },
    {  2520, 17249, 18300 },
    {  2610, 34500, 34920 },
    {  2625, 39375, 39434 },
    {  2640, 39434, 39540 },
    {  2670, 12240, 13260 },
    {  2700, 21600, 21749 },
    {  2760,   300,  1560 },
    {  2820,  3000,  3675 },
    {  2820, 15150, 16500 },
    {  2850, 32715, 32819 },
    {  2850, 32819, 34349 },
    {  2850, 34349, 34500 },
    {  2880,   300, 42449 },
    {  2880,  1560,  2010 },
    {  2880, 42449,   300 },
    {  2910, 24300, 25259 },
    {  3000,  2010,  2460 },
    {  3000,  2460,  3000 },
    {  3000, 11700, 12240 },
    {  3000, 41999, 42449 },
    {  3030,  3675,  4530 },
    {  3030, 30600, 32819 },
    {  3090, 28350, 30600 },
    {  3150,  5999,  8445 },
    {  3150,  8445,  9000 },
    {  3150, 41160, 41999 },
    {  3165, 39540, 39839 },
    {  3180, 21749, 24300 },
    {  3180, 27450, 28350 },
    {  3240,  2460,  3060 },
    {  3240, 10980, 11700 },
    {  3289, 37080, 39540 },
    {  3300,  5700,  5999 },
    {  3300, 39839, 40170 },
    {  3330, 25259, 25950 },
    {  3330, 25950, 27450 },
    {  3330, 34349, 34950 },
    {  3360,  9000, 10980 },
    {  3375, 40170, 41160 },
    {  3420,  4379,  5580 },
    {  3420,  5580,  5700 },
    {  3450,  3060,  3434 },
    {  3480, 34950, 35580 },
    {  3510,  3434,  4379 },
    {  3544, 41160, 41700 },
    {  3570, 35580, 36000 },
    {  3570, 36000, 36966 },
    {  3600, 12600, 14340 },
    {  3600, 14340, 15150 },
    {  3655, 36966, 37080 },
    {  3690, 36000, 36750 },
    {  3720, 10980, 12600 },
    {  3780, 24300, 25950 },
    {  3780, 41700, 42449 },
    {  3840, 21600, 24300 },
    {  3960,   599, 42449 },
    {  3960, 25200, 28200 },
    {  3960, 42449,   599 },
    {  3990, 20399, 21600 },
    {  4020, 36750, 37200 },
    {  4080,  5580,  6150 },
    {  4200, 23400, 25200 },
    {  4200, 28200, 29759 },
    {  4410, 14340, 16500 },
    {  4410, 16500, 20399 },
    {  4500, 29759, 31500 },
    {  4500, 36300, 37200 },
    {  4620,   599,  6150 },
    {  4620,  6150,  6314 },
    {  4620, 20700, 23400 },
    {  4620, 24449, 23400 },
    {  4800,  6314,  9000 },
    {  4800, 19200, 20700 },
    {  4800, 26100, 24449 },
    {  4800, 31500, 32400 },
    {  4800, 36300, 37800 },
    {  4920, 16500, 19200 },
    {  5100,  9000, 14400 },
    {  5160, 32400, 37800 },
    {  5169, 37800, 41400 },
    {  5190, 14400, 26100 },
    {  5280,  6300, 14400 },
    {  5280, 41400,  6300 },
};

#define	NDEC	((int)(sizeof(dec_edges)/sizeof(dec_edges[0])))

/* given an epoch, give caller a list of all constellation edges.
 * return count if ok, else -1.
 * N.B. caller should *not* free what we return because we cache it here.
 */
int
cns_edges (double e, double **ra0p, double **dec0p, double **ra1p,
double **dec1p)
{
#define	NEDGES	(NRA+NDEC)
	static double *ra0, *dec0, *ra1, *dec1;
	static double laste = -12345.6;		/* any bogus value */
	double mjd0;
	int i, n;

	/* if same epoch just return the same list */
	if (e == laste) {
	    *ra0p = ra0;
	    *dec0p = dec0;
	    *ra1p = ra1;
	    *dec1p = dec1;
	    return (NEDGES);
	}

	/* get space for arrays, first time only */
	if (!ra0) {
	    ra0 = (double *)malloc (NEDGES * sizeof(double));
	    if (!ra0)
		return (-1);
	    dec0 = (double *)malloc (NEDGES * sizeof(double));
	    if (!dec0) {
		free ((void *)ra0);
		return (-1);
	    }
	    ra1 = (double *)malloc (NEDGES * sizeof(double));
	    if (!ra1) {
		free ((void *)ra0);
		free ((void *)dec0);
		return (-1);
	    }
	    dec1 = (double *)malloc (NEDGES * sizeof(double));
	    if (!dec1) {
		free ((void *)ra0);
		free ((void *)dec0);
		free ((void *)ra1);
		return (-1);
	    }
	}

	/* prepare for precession from 1875 */
	cal_mjd (1, 1.0, 1875, &mjd0);

	/* build the constant-ra edge lists */
	n = 0;
	for (i = 0; i < NRA; i++) {
	    ra0[n] = ra1[n] = hrrad((double)ra_edges[i].ra/1800.0);
	    dec0[n] = degrad((double)ra_edges[i].dec0/60.0);
	    dec1[n] = degrad((double)ra_edges[i].dec1/60.0);
	    precess (mjd0, e, &ra0[n], &dec0[n]);
	    precess (mjd0, e, &ra1[n], &dec1[n]);
	    n++;
	}

	/* add the constant-dec edge lists */
	for (i = 0; i < NDEC; i++) {
	    ra0[n] = hrrad((double)dec_edges[i].ra0/1800.0);
	    ra1[n] = hrrad((double)dec_edges[i].ra1/1800.0);
	    dec0[n] = dec1[n] = degrad((double)dec_edges[i].dec/60.0);
	    precess (mjd0, e, &ra0[n], &dec0[n]);
	    precess (mjd0, e, &ra1[n], &dec1[n]);
	    n++;
	}

	/* sanity check the count */
	if (n != NEDGES) {
	    printf ("cns_edges(): n=%d NEDGES=%ld\n", n, (long)NEDGES);
	    abort();
	}
	
	/* ok */
	*ra0p = ra0;
	*dec0p = dec0;
	*ra1p = ra1;
	*dec1p = dec1;
	laste = e;
	return (NEDGES);
}

/* given an ra, dec and epoch return the list of constellation ids which
 * *may* fall within the given radius of said location.
 * return the number of ids.
 * ids[] need be no larger than 89.
 */
/* ARGSUSED */
int
cns_list (double ra, double dec, double e, double rad, int ids[])
{
	int i;

	/* TODO: this! */
	for (i = 0; i < NCNS; i++)
	    ids[i] = i;
	return (NCNS);
}

/* epoch 2000 RA/Dec of constellation figure end-points.
 * drawcodes: 0=move to; 1=draw to; 2=draw to dashed; -1=end
 */
typedef struct {
    int drawcode;	/* draw code */
    float ra;		/* rads */
    float dec;		/* rads */
} ConFig;

/* array of malloced lists of ConFigs, same order as cns_namemap[]
 */
static ConFig *figmap[NCNS];

/* add one entry to the drawing code lists */
static void
addFigList (ConFig **new, int *nused, int c, int drawcode, double ra, double dec)
{
	ConFig *cp;

	new[c]= (ConFig*) realloc (new[c], (nused[c]+1)*sizeof(ConFig));
	cp = &new[c][nused[c]++];
	cp->drawcode = drawcode;
	cp->ra = (float)hrrad(ra);
	cp->dec = (float)degrad(dec);
}

/* load the given constellation definition file.
 * return 0 if ok else reason why not in msg[] and -1.
 */
int
cns_loadfigs (FILE *fp, char *msg)
{
	char line[1024];		/* one line from the file */
	char cname[1024];		/* constellation name */
	ConFig **new;			/* array of ConFig[] for each cnstn */
	int *nused;			/* number of ConFig[] for each cnstn */
	int c = -1;			/* index, same as cns_namemap[] */
	int s = 0;			/* status */

	/* init the temp lists */
	new = (ConFig **) calloc (NCNS, sizeof(ConFig*));
	nused = (int *) calloc (NCNS, sizeof(int));

	/* read the file */
	while (fgets (line, sizeof(line), fp)) {
	    char rastr[64], decstr[64];
	    char *lp;
	    int code;

	    /* skip leading/trailing whitespace, blank lines and # lines */
	    for (lp = line+strlen(line)-1; lp>=line && isspace(*lp); --lp)
		*lp = '\0';
	    for (lp = line; isspace(*lp); lp++)
		continue;
	    if (*lp == '#' || *lp == '\0')
		continue;

	    /* ok, line looks interesting, look more carefully */
	    if (sscanf (lp, "%d %s %s", &code, rastr, decstr) == 3) {
		/* looks like a drawing line */
		double ra, dec;

		/* must be working on a current constellation */
		if (c < 0) {
		    sprintf (msg,"Found coord line before first constellation");
		    s = -1;
		    break;
		}

		/* check draw code */
		if (code < 0 || code > 2) {
		    sprintf (msg, "Bad draw code in %s: %d", cname, code);
		    s = -1;
		    break;
		}

		/* crack ra dec */
		if (f_scansexa (rastr, &ra) < 0 || ra < 0 || ra >= 24) {
		    sprintf (msg, "Bad RA format in %s: %s", cname, rastr);
		    s = -1;
		    break;
		}
		if (f_scansexa (decstr, &dec) < 0 || dec < -90 || dec > 90) {
		    sprintf (msg, "Bad Dec format in %s: %s", cname, decstr);
		    s = -1;
		    break;
		}

		/* add to list */
		addFigList (new, nused, c, code, ra, dec);

	    } else {
		/* finish previous list, if any */
		if (c >= 0)
		    addFigList (new, nused, c, -1, 0.0, 0.0);

		/* see if it's a recognized constellation name */
		for (c = 0; c < NCNS; c++)
		    if (strcmp (lp, cns_namemap[c]+5) == 0)
			break;
		if (c == NCNS) {
		    sprintf (msg, "Unknown constellation: %s", lp);
		    s = -1;
		    break;
		}
		if (new[c]) {
		    sprintf (msg, "Duplicate definition for %s", lp);
		    s = -1;
		    break;
		}

		/* init its list */
		strcpy (cname, lp);
		new[c] = (ConFig *) malloc (1);     /* realloc seed */
	    }
	}

	/* even if ok check we found all definitions */
	if (s == 0) {
	    int l = 0;

	    /* finish last list */
	    addFigList (new, nused, c, -1, 0.0, 0.0);

	    for (c = 0; c < NCNS; c++)
		if (!new[c])
		    l += sprintf (msg+l, "%s ", cns_namemap[c]+5);
	    if (l > 0) {
		strcat (msg, ": no definition found");
		s = -1;
	    }
	}

	/* handle ok or error */
	if (s < 0) {
	    /* trouble: free temp lists */
	    for (c = 0; c < NCNS; c++)
		if (new[c])
		    free (new[c]);
	} else {
	    /* make temp lists persistent */
	    for (c = 0; c < NCNS; c++) {
		if (figmap[c])
		    free (figmap[c]);
		figmap[c] = new[c];
	    }
	}

	/* done with lists themselves regardless */
	free (new);
	free (nused);

	/* done */
	return (s);
}

/* given a constellation id and epoch, return arrays of ra[] and dec[]
 *   end-points precessed to the desired epoch that, if connected, will form the
 *   given constellation figure.
 * dcodes is 0 if the coord is a "move-to", 1 if a "draw-to" or 2 if a "draw-to
 *   as dotted-line".
 * return the total number of tripples or -1 if id is bogus.
 * the arrays need be no larger than 35 entries.
 */
int
cns_figure (int id, double e, double ra[], double dec[], int dcodes[])
{
	ConFig *cfp;

	if (id < 0 || id >= NCNS)
	    return (-1);

	for (cfp = figmap[id]; cfp->drawcode >= 0; cfp++) {
	    *ra = (double)cfp->ra;
	    *dec = (double)cfp->dec;
	    precess (J2000, e, ra, dec);
	    ra++;
	    dec++;
	    *dcodes++ = cfp->drawcode;
	}

	return (cfp - figmap[id]);
}

