//*********************************************************************************
// class BuildConstellations // default package
// Software released under the General Public License (version 2 or later), available at
// http://www.gnu.org/copyleft/gpl.html
//*********************************************************************************
import java.io.*;
import java.util.*;
import tig.Strings;
import tig.Formats;
/******************************************************************
Parsing and building constellation classes of package <CODE>jephem.astro.sky</CODE>.
@author Thierry Graff
@history apr 30 2002 : Creation
@history may 02 2002 : BuildRomanData
@todo
*****************************************************************/
public abstract class BuildConstellations{
//=================================================================================
// CONSTANTS
//=================================================================================
// parameters for 1st argument of main()
private static final String PARAM_BUILD_NAMES = "buildNames";
private static final String PARAM_BUILD_ABBREVIATIONS = "buildAbbreviations";
private static final String PARAM_BUILD_BOUNDARIES = "buildBoundaries";
private static final String PARAM_BUILD_ROMAN = "buildRomanData";
private final static String LS = System.getProperty("line.separator");
private final static String PLUS = "+";
private final static String MINUS = "-";
private final static String COMA = ",";
private final static String POINT = ".";
private final static String BLANK = "";
private final static String SPACE = " ";
//=================================================================================
// PUBLIC METHODS
//=================================================================================
//**************** main ************************
/** Entry point to use this class.
@param args The first parameter indicates which method will be called.
<BR>if equals to "buildNames" or "buildAbbreviations", buildNames() is called.
<BR>if equals to "buildBoundaries", buildBoundaries() is called.
<BR>The following arguments are passed to the called method.
*/
public static void main(String[] args){
// Parameter checking
String paramList = "'" + PARAM_BUILD_NAMES + "' or '" + PARAM_BUILD_ABBREVIATIONS + "' or '" +
PARAM_BUILD_BOUNDARIES + "' or '" + PARAM_BUILD_ROMAN + "'";
if (args.length == 0){
System.out.println("Call to main must have at least one parameter :");
System.out.println(paramList);
System.exit(0);
}
if (args[0].compareToIgnoreCase(PARAM_BUILD_NAMES) == 0 ||
args[0].compareToIgnoreCase(PARAM_BUILD_ABBREVIATIONS) == 0){
if(args.length != 3){
System.out.println("Call to buildNames must be done with 2 arguments :");
System.out.println("input file format, output file name");
System.exit(0);
}
buildNames(args[0], args[1], args[2]);
}
else if (args[0].compareToIgnoreCase(PARAM_BUILD_BOUNDARIES) == 0){
if(args.length != 3){
System.out.println("Call to buildBoundaries must be done with 2 arguments :");
System.out.println("input file format, output file name");
System.exit(0);
}
buildBoundaries(args[1], args[2]);
}
else if (args[0].compareToIgnoreCase(PARAM_BUILD_ROMAN) == 0){
if(args.length != 3){
System.out.println("Call to buildRomanData must be done with 2 arguments :");
System.out.println("input file format, output file name");
System.exit(0);
}
buildRomanData(args[1], args[2]);
}
else{
System.out.println("First parameter must be :");
System.out.println(paramList);
}
}// end main
//**************** buildNames() ************************
/** Used to generate name array for class <CODE>jephem.astro.sky.Constellations</CODE> or
abbreviation constants for interface <CODE>jephem.astro.sky.Constellations</CODE>.
<BR>Original file coming from <A HREF="find the address.com">find the address.com</A>,
manually reformatted.
*/
public static void buildNames(String outputType, String inputFileName, String outputFileName){
int i = 0;
try{
LineNumberReader lnr = new LineNumberReader(new FileReader(new File(inputFileName)));
int NB_LINES = 88; // nb of input lines
String[] tmpArray = new String[3];
String[] res = new String[NB_LINES];
String line;
int tmp;
// *** 1 - Fill the intermediate array.
for(i = 0; i < NB_LINES; i++){
// get nominative
line = lnr.readLine();
tmpArray[1] = line.trim();
// get abbreviation
line = lnr.readLine();
tmpArray[0] = line.trim();
// get abbreviation
line = lnr.readLine();
tmpArray[2] = line.trim();
res[i] = tmpArray[0] + COMA + tmpArray[1] + COMA + tmpArray[2];
//System.out.println(res[i][0] + " - " + res[i][1] + " - " + res[i][2]);
}
lnr.close();
// *** 2 - Sort the intermediate array.
java.util.Arrays.sort(res);
for(i = 0; i < NB_LINES; i++)
System.out.println(res[i]);
// *** 3 - Generate the output
FileOutputStream fos = new FileOutputStream(new File(outputFileName));
StringBuffer buffer = new StringBuffer();
// Write headers
if(outputType.compareToIgnoreCase(PARAM_BUILD_NAMES) == 0){
buffer.append(" /** Contains the abbreviation, nominative and genitive of constellations. */").append(LS);
buffer.append(" private static final String[][] _names = {").append(LS);
}
// Loop
for(i = 0; i < NB_LINES; i++){
tmpArray = Strings.stringToStringArray(res[i]);
if(outputType.compareToIgnoreCase(PARAM_BUILD_ABBREVIATIONS) == 0){
buffer.append(" /** Constant to access to \"");
buffer.append(tmpArray[1]).append("\" constellation. */").append(LS);
buffer.append(" public static final int ").append(tmpArray[0]);
buffer.append(" = ").append(i).append(";").append(LS).append(LS);
}
if(outputType.compareToIgnoreCase(PARAM_BUILD_NAMES) == 0){
buffer.append(" {\"").append(tmpArray[0]).append("\", \"");
buffer.append(tmpArray[1]).append("\", \"");
buffer.append(tmpArray[2]).append("\"}");
if(i < NB_LINES - 1) buffer.append(",");
buffer.append(LS);
}
}// end for
// Write Footers
if(outputType.compareToIgnoreCase(PARAM_BUILD_NAMES) == 0)
buffer.append(" }; // end _names").append(LS);
fos.write(buffer.toString().getBytes());
fos.close();
}
catch(Exception e){
System.out.println("stuck at line " + i);
e.printStackTrace();
}
}// end buildNames()
//**************** buildBoundaries() ************************
/** Used to generate boundary array for class <CODE>jephem.astro.sky.Constellations</CODE> .
<BR>Original file coming from <A HREF="find the address.com">find the address.com</A>,
manually reformatted.
<BR>Serpens must be done manually.
*/
public static void buildBoundaries(String inputFileName, String outputFileName){
int i = 0, j = 0;
try{
LineNumberReader lnr;
String line;
int tmp;
final String MARKER = " I "; // always present at beginning of a constellation.
// *** 1 - First pass, to count the constellations.
lnr = new LineNumberReader(new FileReader(new File(inputFileName)));
while((line = lnr.readLine()) != null){
tmp = line.indexOf(MARKER);
if(tmp != -1){
//System.out.println(line.substring(tmp + 1));
i++;
}
}
final int NB_CONST = i; // = 89 (the 88 + Serpens pb)
System.out.println("========== nb const : " + i);
lnr.close();
lnr = null;
// *** 2 - Second pass, to count the nb of elements in each const.
lnr = new LineNumberReader(new FileReader(new File(inputFileName)));
int[] nbElements = new int[NB_CONST]; // nb of pairs (ra, dec in a given const)
int curConst = 0; // index of the current const.
int curNb = 0; // nb of elements in current constellation
while((line = lnr.readLine()) != null){
i++; // identify the line nb (just for error msg).
tmp = line.indexOf(MARKER);
if(tmp != -1){
if(curConst != 0){
nbElements[curConst - 1] = curNb;
}
curConst ++;
curNb = 0;
//System.out.println(line.substring(tmp + 1));
}
else{
curNb++;
}
}// end while
nbElements[NB_CONST - 1] = curNb;
lnr.close();
lnr = null;
// trace
// for(i = 0; i < NB_CONST; i++){
// System.out.println("const " + i + " : " + elements[i]);
// }
// *** 3 - Third pass, to fill the arrays.
// two arrays : one containing the names, an other one containing the Strings with the coords
String[] names = new String[NB_CONST];
String[][] coords = new String[NB_CONST][];
lnr = new LineNumberReader(new FileReader(new File(inputFileName)));
// skip header lines
for(i = 0; i < 5; i++){
line = lnr.readLine();
}
curConst = 0;
curNb = 0;
i = 0;
while((line = lnr.readLine()) != null){
i++; // identify the line nb (just for error msg).
tmp = line.indexOf(MARKER);
if(tmp != -1){
names[curConst] = line.substring(tmp+2).trim(); // retrieve the name
coords[curConst] = new String[nbElements[curConst]]; // allocate
curConst ++;
curNb = 0;
}
else{
//System.out.println("---- " + line + " curConst = " + curConst + " curNb = " + curNb);
coords[curConst - 1][curNb] = line.substring(0, line.indexOf("V")).trim();
curNb++;
}
}// end while
lnr.close();
// trace
for(i = 0; i < NB_CONST; i++){
System.out.println(" ==== const " + i + " : " + names[i]);
// for(j = 0; j < nbElements[i]; j++){
// System.out.println(" " + coords[i][j]);
// }
}
// *** 4 - Build the output from the arrays.
final int OFFICIAL_NB = 88; // the nb of const in the other arrays of class Constellations
FileOutputStream fos = new FileOutputStream(new File(outputFileName));
StringBuffer strRes = new StringBuffer();
int k;
strRes.append(" /** Boundaries of the constellations.").append(LS);
strRes.append(" <BR>Values in radians, for mean equator and equinox 1875.0.").append(LS);
strRes.append(" <BR>WARNING : _boundaries[Ser] contains data for serpens caput.").append(LS);
strRes.append(" Data for serpens cauda are at _boundaries[NB_CONSTELLATIONS].").append(LS);
strRes.append(" */").append(LS);
strRes.append(" private final static double[][][] _boundaries = {").append(LS);
// method : scan the "official" array (_names), find the corresponding element of
// temp arrays (names and coords). The output is then ordered correctly ; serpens cauda is put at the end
for(i = 0; i < OFFICIAL_NB; i++){
for(j = 0; j < NB_CONST; j++){
if(_names[i][1].equalsIgnoreCase(names[j]) ||
_names[i][1].equals("Serpens") && names[j].equals("SERPENS CAPUT")){
strRes.append(" { // data for ");
if(_names[i][1].equals("Serpens")) strRes.append("Serpens Caput").append(LS);
else strRes.append(_names[i][1]).append(LS);
for(k = 0; k < nbElements[j]; k++){
strRes.append(" {");
strRes.append(getRa(coords[j][k].substring(0, 8)));
strRes.append(", ");
strRes.append(getDec(coords[j][k].substring(9)));
if(k == nbElements[j] - 1) strRes.append("}").append(LS);
else strRes.append("},").append(LS);
}// end for k
strRes.append(" },").append(LS);
}// end if
}// end for j
}// end for i
// add data for serpens cauda ...
strRes.append(" { // data for Serpens Cauda").append(LS);
final int serCaudaIdx = 48; // (found in trace of step 3)
for(k = 0; k < nbElements[serCaudaIdx]; k++){
strRes.append(" {");
strRes.append(getRa(coords[serCaudaIdx][k].substring(0, 8)));
strRes.append(", ");
strRes.append(getDec(coords[serCaudaIdx][k].substring(9)));
if(k == nbElements[serCaudaIdx] - 1) strRes.append("}").append(LS);
else strRes.append("},").append(LS);
}// end for k
strRes.append(" }").append(LS);
// ... and finish
strRes.append(" }; // end _boundaries").append(LS);
fos.write(strRes.toString().getBytes());
fos.close();
}
catch(Exception e){
System.out.println("stuck at line " + i);
e.printStackTrace();
}
} // end buildBoundaries
//**************** buildRomanData() ************************
/** Used to generate arrays for class <CODE>jephem.astro.sky.Constellations</CODE> ; these arrays
contain data to find a constellation from a position (cf N. G. Roman work).
*/
public static void buildRomanData(String inputFileName, String outputFileName){
int i = 0;
try{
LineNumberReader lnr = new LineNumberReader(new FileReader(new File(inputFileName)));
int NB_LINES = 357; // nb of input lines
String line;
StringBuffer strRes1 = new StringBuffer();
StringBuffer strRes2 = new StringBuffer();
String strTmp;
// 1 - write headers
strRes1.append(" /** Contains the numeric data used to compute a constellation from a position.").append(LS);
strRes1.append(" <BR>_romanDoubles[i][] contains the data named \"RAl\", \"RAu\", \"Decl\" ");
strRes1.append("in the original work.").append(LS);
strRes1.append(" <BR>All the values are stored in radians, and related to the 1875.0 equator and equinox.").append(LS);
strRes1.append(" <BR>This array is used with _romanStrings. */").append(LS);
strRes1.append(" private static final double[][] _romanDoubles = {").append(LS);
strRes2.append(" /** Contains the String data used to compute a constellation from a position.").append(LS);
strRes2.append(" <BR>_romanStrings[i] contains the data named \"Con\" in the original work.").append(LS);
strRes2.append(" <BR>This array is used with _romanDoubles. */").append(LS);
strRes2.append(" private static final String[] _romanStrings = {").append(LS);
// 2 - parse the file
for(i = 0; i < NB_LINES; i++){
//for(i = 0; i < 10; i++){
line = lnr.readLine();
strRes1.append(" {");
// compute RAl
strTmp = reformatRA(line.substring(0, 8).trim());
strRes1.append(getRa(strTmp)).append(", ");
// compute RAu
strTmp = reformatRA(line.substring(9, 16).trim());
strRes1.append(getRa(strTmp)).append(", ");
// compute Decl
strTmp = reformatDec(line.substring(17, 26).trim());
strRes1.append(getDec2(strTmp)).append("}");
// compute Con
strRes2.append(" \"").append(line.substring(26).trim()).append("\"");
//System.out.println((i+1) + " : " + strTmp);
if(i < NB_LINES - 1){
strRes1.append(COMA);
strRes2.append(COMA);
}
strRes1.append(LS);
strRes2.append(LS);
}
lnr.close();
// 3 - Write footers
strRes1.append(" }; // end _romanDoubles" + LS);
strRes2.append(" }; // end _romanStrings" + LS);
FileOutputStream fos = new FileOutputStream(new File(outputFileName));
fos.write(strRes1.toString().getBytes());
fos.write(LS.getBytes());
fos.write(strRes2.toString().getBytes());
fos.close();
}
catch(Exception e){
System.out.println("stuck at line " + i);
e.printStackTrace();
}
}// end buildRomanData()
//=================================================================================
// AUXILIARY METHODS FOR buildBoundaries
//=================================================================================
//*************************************************
/** Auxiliary method which converts ra from input file to <B>radians</B>.
@param str Contains the ra as formatted in the input file : HH MM SS
*/
// adapted from BuildBSC5 to the format of ConstBoundary.dat
private static double getRa(String str){
try{
double hours = Double.parseDouble(str.substring(0,2));
// System.out.println("ra - parsed hours : " + hours);
double minuts = Double.parseDouble(str.substring(3,5))/60.0; // convert minuts to decimal hours
// System.out.println("ra - parsed minuts : " + minuts);
double seconds = Double.parseDouble(str.substring(5))/3600.0; // convert seconds to decimal hours
// System.out.println("ra - parsed seconds : " + seconds);
double res = hours + minuts + seconds;
res *= 15.0; // convert to degrees
return Math.toRadians(res);
}catch (NumberFormatException nfe){
System.out.println("getRa - Unable to parse '" + str + "'");
return 0.0;
}
}// end getRa
//*************************************************
/** Auxiliary method which converts dec from input file format to <B>radians</B>.
@param str Contains the dec as formatted in the input file : sDDMM (s = sign).
*/
// adapted from BuildBSC5 to the format of ConstBoundary.dat
// also used by buildRomanData()
private static double getDec(String str){
try{
double deg = Double.parseDouble(str.substring(0,3));
// System.out.println("dec - parsed deg : " + deg);
double minuts = Double.parseDouble(str.substring(4))/60.0; // convert minuts to decimal degrees
// System.out.println("dec - parsed minuts " + minuts);
double res = deg + minuts;
return Math.toRadians(res);
}catch (NumberFormatException nfe){
System.out.println("getDec - Unable to parse '" + str + "'");
return 0.0;
}
}// end getDec
//=================================================================================
// AUXILIARY METHODS FOR buildRomanData
//=================================================================================
//**************** reformatRA() ************************
/** Auxiliary method of buildRomanData.*/
private static String reformatRA(String ra){
int tmp = ra.indexOf(POINT);
int nbHours = Integer.parseInt(ra.substring(0, tmp));
int decPart = Integer.parseInt(ra.substring(tmp + 1));
double dblSec = 0.36*decPart; // 0.36 = 3600 / 10E4 ; dblSec = exact nb of hour sec in ra
int nbMin = (int)Math.floor(dblSec/60);
int nbSec = (int)Math.round(dblSec - (double)nbMin*60);
if(nbSec == 60){
nbSec = 0;
nbMin ++;
if(nbMin==60){
nbMin = 0;
nbHours ++;
}
}
boolean traceCheck = false;
// first check : dec. part of dblSec
double dblSecDecPart = dblSec - Math.floor(dblSec);
if(traceCheck && dblSecDecPart != 0) System.out.println("dblSecDecPart = " + dblSecDecPart);
// second check : difference between Roman file value and reformated value
if(traceCheck){
double ra1 = Double.parseDouble(ra);
double ra2 = (double)nbHours + (double)nbMin/60 + (double)nbSec/3600;
if(ra2 - ra1 != 0)
System.out.println("ra1 : " + ra1 + " ra2 : " + ra2 + " ra2 - ra1 : " + (ra2 - ra1));
}
return Formats.addZero(nbHours) + SPACE + Formats.addZero(nbMin) + SPACE + Formats.addZero(nbSec);
}// end reformatRA
//**************** reformatDec() ************************
/** Auxiliary method of buildRomanData.*/
private static String reformatDec(String dec){
int tmp = dec.indexOf(POINT);
int nbDeg = Integer.parseInt(dec.substring(0, tmp));
int decPart = Integer.parseInt(dec.substring(tmp + 1));
double dblSec= 0.36*decPart; // 0.36 = 3600 / 10E4 - dblSec = exact nb of arc sec in dec
int nbMin = (int)Math.floor(dblSec/60);
int nbSec = (int)Math.round(dblSec - (double)nbMin*60);
if(nbSec == 60){
nbSec = 0;
nbMin ++;
if(nbMin==60){
nbMin = 0;
nbDeg ++;
}
}
boolean traceCheck = false;
// first check : dec. part of dblSec
double dblSecDecPart = dblSec - Math.floor(dblSec);
if(traceCheck && dblSecDecPart != 0) System.out.println("dblSecDecPart = " + dblSecDecPart);
// second check : difference between Roman file value and reformated value
if(traceCheck){
double dec1 = Double.parseDouble(dec);
double dec2 = (double)nbDeg + (nbDeg > 0 ? (double)nbMin/60 + (double)nbSec/3600 : -(double)nbMin/60 - (double)nbSec/3600);
if(dec2 - dec1 != 0)
System.out.println("dec1 : " + dec1 + " dec2 : " + dec2 + " dec2 - dec1 : " + (dec2 - dec1) + LS);
}
String strRes = BLANK;
if(nbDeg > 0) strRes += PLUS + Formats.addZero(nbDeg);
else if(nbDeg == 0) strRes += " 00";
else strRes += MINUS + Formats.addZero(-nbDeg);
return strRes + SPACE + Formats.addZero(nbMin) + SPACE + Formats.addZero(nbSec);
}// end reformatDec
//*************************************************
/** Auxiliary method which converts dec from input file format to <B>radians</B>.
@param str Contains the dec as formatted in the input file : sDDMM (s = sign).
*/
// adapted from BuildBSC5 for buildRomanData
private static double getDec2(String str){
try{
double deg = Double.parseDouble(str.substring(0,3));
double minuts = Double.parseDouble(str.substring(4, 6))/60.0;
double seconds = Double.parseDouble(str.substring(7))/3600.0;
//System.out.println("getDec2 - str = " + str + " deg = " + deg + " min = " + minuts + " sec : " + seconds);
double res = deg + minuts + seconds;
return Math.toRadians(res);
}catch (NumberFormatException nfe){
System.out.println("getDec - Unable to parse '" + str + "'");
throw nfe;
}
}// end getDec2
//=================================================================================
// COPIED FROM CLASS jephem.astro.sky.Constellations
// (array generated by buildNames())
//=================================================================================
/** Contains the abbreviation, nominative and genitive of constellations. */
private static final String[][] _names = {
{"And", "Andromeda", "Andromedae"},
{"Ant", "Antlia", "Antliae"},
{"Aps", "Apus", "Apodis"},
{"Aql", "Aquila", "Aquilae"},
{"Aqr", "Aquarius", "Aquarii"},
{"Ara", "Ara", "Arae"},
{"Ari", "Aries", "Arietis"},
{"Aur", "Auriga", "Aurigae"},
{"Boo", "Bootes", "Bootis"},
{"CMa", "Canis Major", "Canis Majoris"},
{"CMi", "Canis Minor", "Canis Minoris"},
{"CVn", "Canes Venatici", "Canum Venaticorum"},
{"Cae", "Caelum", "Caeli"},
{"Cam", "Camelopardalis", "Camelopardalis"},
{"Cap", "Capricornus", "Capricorni"},
{"Car", "Carina", "Carinae"},
{"Cas", "Cassiopeia", "Cassiopeiae"},
{"Cen", "Centaurus", "Centauri"},
{"Cep", "Cepheus", "Cephei"},
{"Cet", "Cetus", "Ceti"},
{"Cha", "Chamaeleon", "Chamaeleontis"},
{"Cir", "Circinus", "Circini"},
{"Cnc", "Cancer", "Cancri"},
{"Col", "Columba", "Columbae"},
{"Com", "Coma Berenices", "Comae Berenices"},
{"CrA", "Corona Austrina", "Coronae Austrinae"},
{"CrB", "Corona Borealis", "Coronae Borealis"},
{"Crt", "Crater", "Crateris"},
{"Cru", "Crux", "Crucis"},
{"Crv", "Corvus", "Corvi"},
{"Cyg", "Cygnus", "Cygni"},
{"Del", "Delphinus", "Delphini"},
{"Dor", "Dorado", "Doradus"},
{"Dra", "Draco", "Draconis"},
{"Equ", "Equuleus", "Equulei"},
{"Eri", "Eridanus", "Eridani"},
{"For", "Fornax", "Fornacis"},
{"Gem", "Gemini", "Geminorum"},
{"Gru", "Grus", "Gruis"},
{"Her", "Hercules", "Herculis"},
{"Hor", "Horologium", "Horologii"},
{"Hya", "Hydra", "Hydrae"},
{"Hyi", "Hydrus", "Hydri"},
{"Ind", "Indus", "Indi"},
{"LMi", "Leo Minor", "Leonis Minoris"},
{"Lac", "Lacerta", "Lacertae"},
{"Leo", "Leo", "Leonis"},
{"Lep", "Lepus", "Leporis"},
{"Lib", "Libra", "Librae"},
{"Lup", "Lupus", "Lupi"},
{"Lyn", "Lynx", "Lyncis"},
{"Lyr", "Lyra", "Lyrae"},
{"Men", "Mensa", "Mensae"},
{"Mic", "Microscopium", "Microscopii"},
{"Mon", "Monoceros", "Monocerotis"},
{"Mus", "Musca", "Muscae"},
{"Nor", "Norma", "Normae"},
{"Oct", "Octans", "Octantis"},
{"Oph", "Ophiuchus", "Ophiuchi"},
{"Ori", "Orion", "Orionis"},
{"Pav", "Pavo", "Pavonis"},
{"Peg", "Pegasus", "Pegasi"},
{"Per", "Perseus", "Persei"},
{"Phe", "Phoenix", "Phoenicis"},
{"Pic", "Pictor", "Pictoris"},
{"PsA", "Piscis Austrinus", "Piscis Austrini"},
{"Pse", "Pisces", "Piscium"},
{"Pup", "Puppis", "Puppis"},
{"Pyx", "Pyxis", "Pyxidis"},
{"Ret", "Reticulum", "Reticuli"},
{"Scl", "Sculptor", "Sculptoris"},
{"Sco", "Scorpius", "Scorpii"},
{"Sct", "Scutum", "Scuti"},
{"Ser", "Serpens", "Serpentis"},
{"Sex", "Sextans", "Sextantis"},
{"Sge", "Sagitta", "Sagittae"},
{"Sgr", "Sagittarius", "Sagittarii"},
{"Tau", "Taurus", "Tauri"},
{"Tel", "Telescopium", "Telescopii"},
{"TrA", "Triangulum Australe", "Trianguli Australis"},
{"Tri", "Triangulum", "Trianguli"},
{"Tuc", "Tucana", "Tucanae"},
{"UMa", "Ursa Major", "Ursae Majoris"},
{"UMi", "Ursa Minor", "Ursae Minoris"},
{"Vel", "Vela", "Velorum"},
{"Vir", "Virgo", "Virginis"},
{"Vol", "Volans", "Volantis"},
{"Vul", "Vulpecula", "Vulpeculae"}
}; // end _names
}//end class BuildConstellations