import java.awt.*; import java.awt.event.*; import java.applet.*; import java.util.*; import java.net.*; import java.io.*; //import com.sun.java.swing.*; import javax.swing.*; // aspire made imports class NightSkyComponent extends JComponent { public Image buffer; public Graphics bufferG; public SkySeasonsMixApplet seasonsApplet; public NightSkyApplet nightskyapp; public NightSkyComponent(SkySeasonsMixApplet applet, int Xpos, int Ypos, int width, int height) { this.seasonsApplet = applet; this.setBounds(Xpos, Ypos, width, height); this.nightskyapp = new NightSkyApplet(); this.nightskyapp.TopLeftX = 0; //Xpos; this.nightskyapp.TopLeftY = 0; //Ypos; this.nightskyapp.width = width; this.nightskyapp.height = height; this.nightskyapp.setBounds(0,0, this.getBounds().width, this.getBounds().height); this.nightskyapp.init_external(this.seasonsApplet); this.nightskyapp.buf = applet.createImage(width, height); this.nightskyapp.gBuf = this.nightskyapp.buf.getGraphics(); this.nightskyapp.start_external(applet); } public Graphics getBufferGraphics() { // make image buffer and associated graphics object int width = getBounds().width; int height = getBounds().height; if (buffer == null || (buffer.getWidth(this) != width || buffer.getHeight(this) != height)) { buffer = createImage(width, height); bufferG = buffer.getGraphics(); } return bufferG; } public void paintComponent(Graphics g) { getBufferGraphics(); // bufferG.drawRect(12,14,4,2); if (g != null) { nightskyapp.paint_me(g); } else { System.out.println("NULL g found "); } } } // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** /** * NightSky.java * * @ Authors: * * @ Joseph Snow * @ Date: July 22, 2000 * @ Aspire Pro, University of Utah, Cosmic Ray Physics * @ * @ Copyright 2000, All Rights Reserved * * note: The idea for this code design was partially taken from * Chris Dolan (dolan@astro.wisc.edu) Nov 25, 1998 */ /* There are three classes in this applet: - NightSkyApplet The main body which includes all of the initialization and event handling. - SkyWidget The canvas on which all of the graphics are produced. This includes the double-buffered rendering which displays the stars. The primary entrance is the paintSky function. This class also handles a small bit of mouse interactivity. - LoadThread The code that loads the databases of stars, constellation names, and constellation lines. This code runs in a parallel background thread so the user can interact with the applet while the data is being downloaded. This thread runs once at the beginning and then becomes inactive. The LoadThread also precalculates the trigonometric functions needed to project the stars and constellation lines onto the sky. This data is used in the SkyWidget functions. */ // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** class NightSkyApplet extends Applet { // constants public final static int NEW_STUFF = 10000; public final static int NEW_STARS = 10001; public final static int MAX_X = 360; public final static int MIN_X = 0; public final static int MAX_Y = 90; public final static int MIN_Y = -90; public final static double tilt = 23.45; // custom variables // Variables used as parameters: must be predefined here! public int TopLeftX = 0; public int TopLeftY = 0; public double ra = 5.6324920; // Right Ascension and Declination public double dec = 6.7487873; public double fov = 75.0; // field of view angle public double angle; //will be determined from fov public int speed = 5; private double animation_speed = 4; public int dataset = 0, linedataset = 2, altlinedataset = 3; public int expand; public double dexpand; // Global variables public double stars[][], stars_math[][]; public int numstars, usestars, starlists[], loadedlists = 0; public int width, height; public double lines[][], lines_math[][]; public int numlines; public double altlines[][], altlines_math[][]; public int altnumlines; public boolean uselines, usealtlines; public String constnames[]; public double constcoords[][], constcoords_math[][]; public int numconst; public boolean usenames; // Double buffering Objects public Image buf; // bitmap for double buffering public Graphics gBuf; // gc to draw on bitmap public SkySeasonsMixApplet skyseasonapp; private LoadThread theLoadThread; public SkyWidget skyWidget; public Font font; public void init() { init_both(); } private void init_both() { Dimension d = size(); width = d.width; height = d.height; setBackground(Color.gray); setFont(font = new Font("Helvetica", Font.PLAIN, 10)); setLayout(new BorderLayout()); // getParams(); if (buf == null) { buf = createImage(width, height-100); if (buf != null) { gBuf = buf.getGraphics(); } } stars = new double[10000][3]; stars_math = new double[10000][4]; starlists = new int[7]; numstars = 0; usestars = 0; lines = new double[1000][4]; lines_math = new double[1000][8]; numlines = 0; altlines = new double[1000][4]; altlines_math = new double[1000][8]; altnumlines = 0; uselines = true; usealtlines = false; constnames = new String[100]; constcoords = new double[100][2]; constcoords_math = new double[100][4]; numconst = 0; usenames = true; expand = 1; // this is the size scale of the scroll bar thumb dexpand = (double)expand; } public void init_external(SkySeasonsMixApplet skyseasonapp) { this.init_both(); Panel center = new Panel(); // the skyWidget needs to be in the panel, in order to handle events correctly center.add("Center", skyWidget = new SkyWidget(this)); add("Center", center); angle = fov*Math.PI/180.0; // this.fov = angle*180.0/Math.PI; this.skyWidget.setBounds(0,0, this.getBounds().width, this.getBounds().height); //this.skyWidget.STANDALONE = false; this.skyseasonapp = skyseasonapp; } public void start() { if (numstars == 0) { Thread theThread; Thread.currentThread().setPriority(Thread.MAX_PRIORITY); theLoadThread = new LoadThread(this); theThread = new Thread(theLoadThread); theThread.setPriority(Thread.MIN_PRIORITY); theThread.start(); } } public void start_external(Applet baseApp) { if (numstars == 0) { Thread theThread; theLoadThread = new LoadThread(this, baseApp); theThread = new Thread(theLoadThread); theThread.setPriority(Thread.MIN_PRIORITY); theThread.start(); } } public void destroy() { gBuf.dispose(); } public synchronized boolean handleEvent(Event event) { if (event.id == NEW_STARS) { starlists[loadedlists++] = numstars; if (loadedlists <= speed) { usestars = numstars; } skyWidget.update(skyWidget.getGraphicsGBuf()); return true; } else if (event.id == NEW_STUFF) { skyWidget.update(skyWidget.getGraphicsGBuf()); return true; } else { return super.handleEvent(event); } } // Get parameters (for ra, dec, lat, long) public void getParams() { boolean stub_valid = true; try { if (getParameter("ra") != null) { stub_valid = true; } } catch (NullPointerException e) { stub_valid = false; } if (stub_valid && getParameter("ra") != null) { ra = new Double(new String(getParameter("ra"))).doubleValue(); if (ra < 0.0) ra = 0.0; else if (ra > 24.0) ra = 24.0; ra = ra * Math.PI / 12.0; } else { ra = ra * Math.PI / 12.0; } if (stub_valid && getParameter("dec") != null) { dec = new Double(new String(getParameter("dec"))).doubleValue(); if (dec < -90.0) dec = -90.0; else if (dec > 90.0) dec = 90.0; dec = dec * Math.PI / 180.0; } else { dec = dec * Math.PI / 180.0; } if (stub_valid && getParameter("angle") != null) { angle = new Double(new String(getParameter("angle"))).doubleValue(); if (angle < 0.00001) angle = 0.00001; else if (angle > 360.0) angle = 360.0; angle = angle * Math.PI / 180.0; } else { angle = angle * Math.PI / 180.0; } if (stub_valid && getParameter("speed") != null) { speed = new Integer(new String(getParameter("speed"))).intValue(); if (speed < 1) speed = 1; if (speed > 7) speed = 7; } if (stub_valid && getParameter("data") != null) { String s = getParameter("data"); if (s.compareTo("bsc") == 0) { dataset = 0; System.out.println("Using catalog \"" + s + "\""); } else if (s.compareTo("YBS") == 0) { dataset = 1; System.out.println("Using catalog \"" + s + "\""); } else { System.out.println("Invalid data set \"" + s + "\" requested"); System.out.println("Using default catalog"); dataset = 0; } } if (stub_valid && getParameter("lines") != null) { int s = new Integer(new String(getParameter("lines"))).intValue(); if (s >= 0) { linedataset = s; } } if (stub_valid && getParameter("altlines") != null) { int s = new Integer(new String(getParameter("altlines"))).intValue(); if (s >= 0) { altlinedataset = s; } } } // http://www.dur.ac.uk/~dph0jrl/one_lab/pm_coord.html -- has some helpful info // center: Ra: 11 h 10m, Dec:+55d 23', 5/4/96 2:00PM, lat: +21d 19' 0.0", Long: +157d 52' 0.0" public void simulate_time(int start_time, int len, boolean forwards) { double step = animation_speed; double amp; double wavelen; double lat_org = this.skyseasonapp.system.getLatitude(); double long_org = this.skyseasonapp.system.getLongitude(); amp = tilt * (1- Math.abs( lat_org / MAX_Y )); wavelen = 24.0 * Math.PI / 365.25; if (forwards == false) { step = -step; } double y; double theta = start_time; for (int i=0; i= 0; i--) { b = (int)top.stars[i][2]; b = b < 0 ? 0 : (b > 6 ? 6 : b); g.setColor(Color.getHSBColor((float)0.0, (float)0.0, (float)brightnesses[b])); sr0 = top.stars_math[i][0]; cr0 = top.stars_math[i][1]; sd0 = top.stars_math[i][2]; cd0 = top.stars_math[i][3]; ez = cd*cd0*(cr*cr0 + sr*sr0) + sd*sd0; if (ez > 0.1) { ey = -sd*cd0*(cr*cr0 + sr*sr0) + cd*sd0; ex = -cd0*(sr*cr0 - cr*sr0); x = xmid + (int)(-dist * ex/ez); y = ymid + (int)(-dist * ey/ez); switch (b) { case 0: g.drawLine(x-1,y,x+1,y); g.drawLine(x,y-1,x,y+1); break; case 1: case 2: g.drawLine(x,y,x+1,y); g.drawLine(x,y-1,x+1,y-1); break; default: g.drawLine(x,y,x,y); break; } } } } protected void paintNames(Graphics g) { int i, x, y; double dist, ex, ey, ez; double cr, sr, cd, sd, cr0, sr0, cd0, sd0; dist = (double)Math.min(xmid,ymid)/Math.tan(top.angle/2.0); g.setColor(Color.red); sr = Math.sin(top.ra); cr = Math.cos(top.ra); sd = Math.sin(top.dec); cd = Math.cos(top.dec); for (i = top.numconst-1; i >= 0; i--) { sr0 = top.constcoords_math[i][0]; cr0 = top.constcoords_math[i][1]; sd0 = top.constcoords_math[i][2]; cd0 = top.constcoords_math[i][3]; ez = cd*cd0*(cr*cr0 + sr*sr0) + sd*sd0; if (ez > 0.1) { ey = -sd*cd0*(cr*cr0 + sr*sr0) + cd*sd0; ex = -cd0*(sr*cr0 - cr*sr0); x = xmid + (int)(-dist * ex/ez); y = ymid + (int)(-dist * ey/ez); drawCenteredString(g, top.constnames[i], x, y); } } } protected void paintLines(Graphics g) { int i, x1, x2, y1, y2; double dist, ex1, ex2, ey1, ey2, ez1, ez2; double cr, sr, cd, sd, cr1, sr1, cd1, sd1, cr2, sr2, cd2, sd2; dist = (double)Math.min(xmid,ymid)/Math.tan(top.angle/2.0); g.setColor(Color.blue); sr = Math.sin(top.ra); cr = Math.cos(top.ra); sd = Math.sin(top.dec); cd = Math.cos(top.dec); for (i = top.numlines-1; i >= 0; i--) { sr1 = top.lines_math[i][0]; cr1 = top.lines_math[i][1]; sd1 = top.lines_math[i][2]; cd1 = top.lines_math[i][3]; sr2 = top.lines_math[i][4]; cr2 = top.lines_math[i][5]; sd2 = top.lines_math[i][6]; cd2 = top.lines_math[i][7]; ez1 = cd*cd1*(cr*cr1 + sr*sr1) + sd*sd1; ez2 = cd*cd2*(cr*cr2 + sr*sr2) + sd*sd2; if (ez1 > 0.1 && ez2 > 0.1) { ey1 = -sd*cd1*(cr*cr1 + sr*sr1) + cd*sd1; ey2 = -sd*cd2*(cr*cr2 + sr*sr2) + cd*sd2; ex1 = -cd1*(sr*cr1 - cr*sr1); ex2 = -cd2*(sr*cr2 - cr*sr2); x1 = xmid + (int)(-dist * ex1/ez1); x2 = xmid + (int)(-dist * ex2/ez2); y1 = ymid + (int)(-dist * ey1/ez1); y2 = ymid + (int)(-dist * ey2/ez2); g.drawLine(x1,y1,x2,y2); } } } protected void paintAltLines(Graphics g) { int i, x1, x2, y1, y2; double dist, ex1, ex2, ey1, ey2, ez1, ez2; double cr, sr, cd, sd, cr1, sr1, cd1, sd1, cr2, sr2, cd2, sd2; dist = (double)Math.min(xmid,ymid)/Math.tan(top.angle/2.0); g.setColor(Color.blue); sr = Math.sin(top.ra); cr = Math.cos(top.ra); sd = Math.sin(top.dec); cd = Math.cos(top.dec); for (i = top.altnumlines-1; i >= 0; i--) { sr1 = top.altlines_math[i][0]; cr1 = top.altlines_math[i][1]; sd1 = top.altlines_math[i][2]; cd1 = top.altlines_math[i][3]; sr2 = top.altlines_math[i][4]; cr2 = top.altlines_math[i][5]; sd2 = top.altlines_math[i][6]; cd2 = top.altlines_math[i][7]; ez1 = cd*cd1*(cr*cr1 + sr*sr1) + sd*sd1; ez2 = cd*cd2*(cr*cr2 + sr*sr2) + sd*sd2; if (ez1 > 0.1 && ez2 > 0.1) { ey1 = -sd*cd1*(cr*cr1 + sr*sr1) + cd*sd1; ey2 = -sd*cd2*(cr*cr2 + sr*sr2) + cd*sd2; ex1 = -cd1*(sr*cr1 - cr*sr1); ex2 = -cd2*(sr*cr2 - cr*sr2); x1 = xmid + (int)(-dist * ex1/ez1); x2 = xmid + (int)(-dist * ex2/ez2); y1 = ymid + (int)(-dist * ey1/ez1); y2 = ymid + (int)(-dist * ey2/ez2); g.drawLine(x1,y1,x2,y2); } } } protected void paintSky(Graphics g) { // pre-clear the bitmap or the applet // remove this if you paint the entire area anyway d = size(); xmid = d.width/2; ymid = d.height/2; g.setColor(Color.black); g.fillRect(0, 0, d.width, d.height); if (top.uselines) if (top.usealtlines) paintAltLines(g); else paintLines(g); if (top.usenames) paintNames(g); paintStars(g); } public void paint(Graphics g) { if (doubleBuffer) { paintSky(top.gBuf); if (top.buf != null) { g.drawImage(top.buf, top.TopLeftX, top.TopLeftY, this); } else { System.out.println("Null top.buf found !"); } } else { paintSky(g); } } public void update(Graphics g) { // override this because the default implementation always // calls clearRect first, causing unwanted flicker top.dec = top.skyseasonapp.system.getLatitude(); paint(g); } public boolean mouseDown(Event evt, int x, int y) { Dimension d; double ra, dec, dy, dx, r, rr; double dist, ex, ey, ez; double cr, sr, cd, sd; int rah,ram,ras,decd,decm,decs,xmid,ymid; String sign; Graphics g = this.getGraphicsGBuf(); d = size(); xmid = d.width/2; ymid = d.height/2; dist = (double)Math.min(xmid,ymid)/Math.tan(top.angle/2.0); dx = -(double)(x-xmid); dy = -(double)(y-ymid); sr = Math.sin(top.ra); cr = Math.cos(top.ra); sd = Math.sin(top.dec); cd = Math.cos(top.dec); r = Math.sqrt(dx*dx + dy*dy + dist*dist); ex = ( dx*cr - dy*sd*sr + dist*cd*sr)/r; ey = ( dy*cd + dist*sd )/r; ez = (-dx*sr - dy*cr*sd + dist*cd*cr)/r; rr = Math.sqrt(ex*ex + ez*ez); ra = Math.atan2(ex,ez)*12.0/Math.PI; dec = Math.atan2(ey,rr)*180.0/Math.PI; if (ra < 0.0) ra += 24.0; rah = (int)ra; ra = (ra-(double)rah)*60.0; ram = (int)ra; ra = (ra-(double)ram)*60.0; ras = (int)ra; if (dec < 0.0) { sign = "-"; dec = -dec; } else { sign = "+"; } decd = (int)dec; dec = (dec-(double)decd)*60.0; decm = (int)dec; dec = (dec-(double)decm)*60.0; decs = (int)dec; g.setColor(Color.green); g.drawString("RA "+rah+":"+ram+" Dec "+sign+decd+":"+decm, x, y); return true; } public boolean mouseUp(Event evt, int x, int y) { Graphics g = this.getGraphicsGBuf(); if (doubleBuffer) { g.drawImage(top.buf, 0, 0, this); } else { paintSky(g); } return true; } public boolean mouseDrag(Event evt, int x, int y) { mouseUp(evt,x,y); mouseDown(evt,x,y); return true; } } // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** class LoadThread implements Runnable { private NightSkyApplet theApp; private Applet theBaseApp; public LoadThread(NightSkyApplet app) { super(); theApp = app; theBaseApp = app; } public LoadThread(NightSkyApplet app, Applet BaseApp) { super(); theApp = app; theBaseApp = BaseApp; } public void getStdLines() { theApp.numlines = getLines(theApp.linedataset, theApp.lines, theApp.lines_math); } public void getAltLines() { if (theApp.linedataset == theApp.altlinedataset) { if (theApp.numlines == 0) { theApp.uselines = false; } } else { theApp.altnumlines = getLines(theApp.altlinedataset, theApp.altlines, theApp.altlines_math); if (theApp.numlines == 0) { theApp.usealtlines = true; if (theApp.altnumlines == 0 ) { theApp.uselines = false; } } theApp.deliverEvent(new Event(this, theApp.NEW_STUFF, this)); } } public int getLines(int catalog, double lines[][], double lines_math[][]) { int i = 0, j = 0; String s; try { if (catalog == 0) s = "data/lines.dat"; else s = "data/lines" + String.valueOf(catalog) + ".dat"; System.out.println("Opening file " + s); URL url = new URL(theBaseApp.getCodeBase(), s); URLConnection urlConnection = url.openConnection(); urlConnection.connect(); // if the file does not exist, the following will throw an exception: InputStream is = urlConnection.getInputStream(); StreamTokenizer st = new StreamTokenizer(is); while (st.nextToken() != st.TT_EOF) { lines[j][i] = st.nval; lines_math[j][2*i] = Math.sin(st.nval); lines_math[j][2*i+1] = Math.cos(st.nval); if ((++i) == 4) { j++; i = 0; } } } catch (Exception ex) { return 0; } System.out.println(String.valueOf(j) + " constellation lines added"); return j; } public void getConsts() { int i = 0, j = 0; String s; try { s = "data/averagebdys.dat"; URL url = new URL(theBaseApp.getCodeBase(), s); URLConnection urlConnection = url.openConnection(); urlConnection.connect(); // if the file does not exist, the following will throw an exception: InputStream is = urlConnection.getInputStream(); StreamTokenizer st = new StreamTokenizer(is); while (st.nextToken() != st.TT_EOF) { if (i == 0) { theApp.constnames[j] = st.sval; } else if (i == 1) { theApp.constcoords[j][0] = st.nval*Math.PI/12.0; theApp.constcoords_math[j][0] = Math.sin(theApp.constcoords[j][0]); theApp.constcoords_math[j][1] = Math.cos(theApp.constcoords[j][0]); } else { theApp.constcoords[j][1] = st.nval*Math.PI/180.0; theApp.constcoords_math[j][2] = Math.sin(theApp.constcoords[j][1]); theApp.constcoords_math[j][3] = Math.cos(theApp.constcoords[j][1]); j++; i = -1; } i++; } } catch (Exception ex) { theApp.numconst = 0; theApp.usenames = false; return; } theApp.numconst = j; System.out.println(String.valueOf(theApp.numconst) + " constellations added"); theApp.deliverEvent(new Event(this, theApp.NEW_STUFF, this)); } public void getData(int n) { int i; String url; switch (theApp.dataset) { case 0: if (n == 0) url = "data/bsc.dat"; else url = "data/bsc" + String.valueOf(n) + ".dat"; break; case 1: if (n == 0) url = "data/YBS.dat"; else url = "data/YBS" + String.valueOf(n) + ".dat"; break; default: System.out.println("Invalid data set requested"); return; } i = getFile(url, theApp.stars, theApp.numstars); if (i > 0) { theApp.numstars += i; System.out.println(String.valueOf(theApp.numstars) + " stars in database"); theApp.deliverEvent(new Event(this, theApp.NEW_STARS, this)); } } public int getFile(String s, double a[][], int n) { Double f; int i, j; try { URL url = new URL(theBaseApp.getCodeBase(), s); URLConnection urlConnection = url.openConnection(); urlConnection.connect(); // if the file does not exist, the following will throw an exception: InputStream is = urlConnection.getInputStream(); StreamTokenizer st = new StreamTokenizer(is); i = 0; j = 0; while (st.nextToken() != st.TT_EOF) { a[n+j][i] = st.nval; if (i != 2) { theApp.stars_math[n+j][2*i] = Math.sin(st.nval); theApp.stars_math[n+j][2*i+1] = Math.cos(st.nval); } if ((++i) == 3) { j++; i = 0; } } } catch (Exception ex) { return 0; } return j; } public void run() { int num =1; try { getData(1); num++; getData(2); num++; getConsts(); getData(3); num++; getStdLines(); getData(4); num++; getAltLines(); getData(5); num++; getData(6); num++; getData(7); num++; System.out.println("Done loading stars"); System.out.flush(); } catch (Exception e) { System.out.println("Error loading stars at: " + num + "! - " + e.getMessage() ); } return; } } // ***************************************************************************** // ***************************************************************************** // ***************************************************************************** // *****************************************************************************