001    import java.awt.*;
002    import java.awt.event.*;
003    import java.util.*;
004    import javax.swing.*;
005    import java.io.*;
006    import java.lang.*;
007    
008    /**
009    * This class is a sub class of <code>JFrame</code> and is responsible for the GUI and 
010    * for displaying the space objects and there orbits. 
011    * It is doing most of the work.
012    * @author Markus Signitzer
013    */
014    public class Display extends JFrame{
015        /**
016        * The integrator will hold a instance of <code>SolarIntegrator</code> and 
017        * will be needed by the paint() method.
018        */
019        SolarIntegrator integrator;
020        /**
021        * Is the screen where the Space Objects and their orbits will be displayed. 
022        */
023        ScreenOne screenOne;
024        /**
025        * The JSlider will be used to zoom in and out of the solar system. 
026        */
027        JSlider scaleSlider;
028        /**
029        * Will hold all the positon data for all Space Objects in the HELIO Centric case. 
030        */
031        Vector oldDataH = new Vector();
032        /**
033        * Will hold all the positon data for cruithne in the special "second moon view". 
034        */
035        Vector oldSecondMoon = new Vector();
036        /**
037        * Will hold all the positon data for cruithne in the special "second moon view". 
038        */
039        Vector oldCoRotational = new Vector();
040        
041        /**
042        * Will hold all the positon data for all Space Objects in the GEO Centric case. 
043        */
044        Vector oldData = new Vector();
045        /**
046        * The array of Space Objects making up my Solar System. 
047        */
048        SpaceObject[] objects;
049        
050        /**
051        * Constructs a <code>Display</code> which will act as my main GUI.
052        *
053        * @param objects the array of Space Objects making up my Solar System. 
054        * @param startPoint the initial positons and velocities of all Space Objects.
055        */
056        public Display(SpaceObject[] objects, PointN startPoint){
057            
058            this.objects = objects;
059            //initialize Window
060            setBackground(Color.lightGray);
061            setTitle("Solar-System-Simulator by Markus Signitzer");
062            Dimension screenSize = getToolkit().getScreenSize();
063            setSize(550, screenSize.height-35);
064            //setSize(500, 700);
065            //setResizable(false);
066            
067            getContentPane().setLayout(new BorderLayout());
068            
069            // create a Panel to draw onto
070            screenOne = new ScreenOne(objects, startPoint);
071            
072            screenOne.setBorder(BorderFactory.createLineBorder(Color.green, 2));
073            // some Buttons and panels which are needed for the GUI
074            JPanel buttonPanel = new JPanel();
075            buttonPanel.setLayout(new GridLayout(2, 3));
076            
077            JButton pause = new JButton("Run/Pause");
078            pause.addMouseListener(new PausePressed());
079            
080            JButton write = new JButton("Display selected orbits ON/OFF");
081            write.addMouseListener(new WritePressed());
082            
083            JButton clear = new JButton("Clear Orbits");
084            clear.addMouseListener(new ClearPressed());
085            
086            JButton helio = new JButton("SWITCH VIEWS");
087            helio.addMouseListener(new HelioPressed());
088            
089            JButton momentumChange = new JButton("Change Cruithnes Momentum");
090            momentumChange.addMouseListener(new MomentumChange());
091            
092            JButton importUpdatedMomentum = new JButton("Import Updated Momentum");
093            importUpdatedMomentum.addMouseListener(new ImportUpdatedMomentum());
094            
095            scaleSlider = new JSlider(JSlider.VERTICAL, 1, 30, 1);
096            scaleSlider.setMajorTickSpacing(1);
097            scaleSlider.setPaintTicks(true);
098            scaleSlider.setPaintLabels(true);
099            
100            // Pull-down menu bar to select which space object should
101            // display their trajectory
102            JMenuBar menubar = new JMenuBar();
103            menubar.add(createMenu()); 
104            setJMenuBar(menubar);
105            
106            // add the buttons 
107            buttonPanel.add(pause);
108            buttonPanel.add(write);
109            buttonPanel.add(clear);
110            buttonPanel.add(helio);
111            buttonPanel.add(momentumChange);
112            buttonPanel.add(importUpdatedMomentum);
113            
114            // add everything on to the main Frame
115            getContentPane().add(screenOne, BorderLayout.CENTER);
116            getContentPane().add(buttonPanel, BorderLayout.SOUTH);
117            getContentPane().add(scaleSlider, BorderLayout.EAST);
118        }
119        
120        /**
121        * Method for creating a pull down Menu.
122        * Will allow the user to select which orbits should be displayed.
123        * @return <code>JMenu</code> a pull down menu, ready to be attached to the main frame.
124        */
125        private JMenu createMenu(){
126            JMenu menu = new JMenu("CLICK HERE to select which orbits you want displayed");
127            JCheckBoxMenuItem sun = new JCheckBoxMenuItem("Sun", false);
128            sun.setBackground(Color.yellow);
129            sun.addMouseListener(new SunPressed());
130            menu.add(sun);
131            
132            JCheckBoxMenuItem mercury = new JCheckBoxMenuItem("Mercury", false);
133            mercury.setBackground(Color.gray);
134            mercury.addMouseListener(new MercuryPressed());
135            menu.add(mercury);
136            
137            JCheckBoxMenuItem venus = new JCheckBoxMenuItem("Venus", false);
138            venus.setBackground(Color.orange);
139            venus.addMouseListener(new VenusPressed());
140            menu.add(venus);
141            
142            JCheckBoxMenuItem earth = new JCheckBoxMenuItem("Earth", false);
143            earth.setBackground(Color.blue);
144            earth.addMouseListener(new EarthPressed());
145            menu.add(earth);
146            
147            JCheckBoxMenuItem mars = new JCheckBoxMenuItem("Mars",false);
148            mars.setBackground(Color.red);
149            mars.addMouseListener(new MarsPressed());
150            menu.add(mars);
151            
152            JCheckBoxMenuItem jupiter = new JCheckBoxMenuItem("Jupiter",false);
153            jupiter.setBackground(Color.orange);
154            jupiter.addMouseListener(new JupiterPressed());
155            menu.add(jupiter);
156            
157            JCheckBoxMenuItem saturn = new JCheckBoxMenuItem("Saturn", false);
158            saturn.setBackground(Color.cyan);
159            saturn.addMouseListener(new SaturnPressed());
160            menu.add(saturn);
161            
162            JCheckBoxMenuItem uranus = new JCheckBoxMenuItem("Uranus", false);
163            uranus.setBackground(Color.green);
164            uranus.addMouseListener(new UranusPressed());
165            menu.add(uranus);
166            
167            JCheckBoxMenuItem neptune = new JCheckBoxMenuItem("Neptune",false);
168            neptune.setBackground(Color.blue);
169            neptune.addMouseListener(new NeptunPressed());
170            menu.add(neptune);
171            
172            JCheckBoxMenuItem cruithne = new JCheckBoxMenuItem("Cruithne",true);
173            cruithne.setBackground(Color.white);
174            cruithne.addMouseListener(new CruithnePressed());
175            menu.add(cruithne);
176            
177            return menu;
178        }
179        
180        
181        /**
182        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
183        * pull down menu interactive. i.e. this class changes the 
184        * visibility of the orbit of a certain space object.
185        */
186        class SunPressed extends MouseAdapter{
187            public void mousePressed(MouseEvent e){
188                //Button Pressed
189                if (objects[0].getDisplay()){
190                    objects[0].setDisplay(false);
191                }else{
192                    objects[0].setDisplay(true);
193                }
194                
195            }
196        }
197        /**
198        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
199        * pull down menu interactive. i.e. this class changes the 
200        * visibility of the orbit of a certain space object.
201        */
202        class MercuryPressed extends MouseAdapter{
203            public void mousePressed(MouseEvent e){
204                //Button Pressed
205                if (objects[1].getDisplay()){
206                    objects[1].setDisplay(false);
207                }else{
208                    objects[1].setDisplay(true);
209                }
210                
211            }
212        }
213        /**
214        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
215        * pull down menu interactive. i.e. this class changes the 
216        * visibility of the orbit of a certain space object.
217        */
218        class VenusPressed extends MouseAdapter{
219            public void mousePressed(MouseEvent e){
220                //Button Pressed
221                if (objects[2].getDisplay()){
222                    objects[2].setDisplay(false);
223                }else{
224                    objects[2].setDisplay(true);
225                }
226                
227            }
228        }
229        /**
230        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
231        * pull down menu interactive. i.e. this class changes the 
232        * visibility of the orbit of a certain space object.
233        */
234        class EarthPressed extends MouseAdapter{
235            public void mousePressed(MouseEvent e){
236                //Button Pressed
237                if (objects[3].getDisplay()){
238                    objects[3].setDisplay(false);
239                }else{
240                    objects[3].setDisplay(true);
241                }
242                
243            }
244        }
245        /**
246        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
247        * pull down menu interactive. i.e. this class changes the 
248        * visibility of the orbit of a certain space object.
249        */
250        class MarsPressed extends MouseAdapter{
251            public void mousePressed(MouseEvent e){
252                //Button Pressed
253                if (objects[4].getDisplay()){
254                    objects[4].setDisplay(false);
255                }else{
256                    objects[4].setDisplay(true);
257                }
258                
259            }
260        }
261        /**
262        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
263        * pull down menu interactive. i.e. this class changes the 
264        * visibility of the orbit of a certain space object.
265        */
266        class JupiterPressed extends MouseAdapter{
267            public void mousePressed(MouseEvent e){
268                //Button Pressed
269                if (objects[5].getDisplay()){
270                    objects[5].setDisplay(false);
271                }else{
272                    objects[5].setDisplay(true);
273                }
274                
275            }
276        }
277        /**
278        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
279        * pull down menu interactive. i.e. this class changes the 
280        * visibility of the orbit of a certain space object.
281        */
282        class SaturnPressed extends MouseAdapter{
283            public void mousePressed(MouseEvent e){
284                //Button Pressed
285                if (objects[6].getDisplay()){
286                    objects[6].setDisplay(false);
287                }else{
288                    objects[6].setDisplay(true);
289                }
290                
291            }
292        }
293        /**
294        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
295        * pull down menu interactive. i.e. this class changes the 
296        * visibility of the orbit of a certain space object.
297        */
298        class UranusPressed extends MouseAdapter{
299            public void mousePressed(MouseEvent e){
300                //Button Pressed
301                if (objects[7].getDisplay()){
302                    objects[7].setDisplay(false);
303                }else{
304                    objects[7].setDisplay(true);
305                }
306                
307            }
308        }
309        /**
310        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
311        * pull down menu interactive. i.e. this class changes the 
312        * visibility of the orbit of a certain space object.
313        */
314        class NeptunPressed extends MouseAdapter{
315            public void mousePressed(MouseEvent e){
316                //Button Pressed
317                if (objects[8].getDisplay()){
318                    objects[8].setDisplay(false);
319                }else{
320                    objects[8].setDisplay(true);
321                }
322                
323            }
324        }
325        /**
326        * A little nested class which extends <code>MouseAdapter</code>. Makes the 
327        * pull down menu interactive. i.e. this class changes the 
328        * visibility of the orbit of a certain space object.
329        */
330        class CruithnePressed extends MouseAdapter{
331            public void mousePressed(MouseEvent e){
332                //Button Pressed
333                if (objects[9].getDisplay()){
334                    objects[9].setDisplay(false);
335                }else{
336                    objects[9].setDisplay(true);
337                }
338                
339            }
340        }
341        
342        
343        /**
344        * A little nested class which extends <code>MouseAdapter</code>.
345        * Listens to button presses on the main GUI.
346        * Switches the Applet between Pause and Run modus
347        */
348        class PausePressed extends MouseAdapter{
349            public void mousePressed(MouseEvent e){
350                //Button Pressed
351                if(screenOne.pause == false){
352                    screenOne.pause = true;
353                }else{
354                    screenOne.pause = false;
355                    screenOne.repaint();
356                }
357            }
358        }
359        
360        
361        /**
362        * A little nested class which extends <code>MouseAdapter</code>.
363        * Listens to button presses on the main GUI.
364        * Will display selected orbits if pressed.
365        */
366        class WritePressed extends MouseAdapter{
367            public void mousePressed(MouseEvent e){
368                //Button Pressed
369                if(screenOne.write == false){
370                    screenOne.write = true;
371                }else{
372                    screenOne.write = false;
373                }
374            }
375        }
376        
377        /**
378        * A little nested class which extends <code>MouseAdapter</code>.
379        * Listens to button presses on the main GUI.
380        * Deletes the so far collected orbit data (history of all past positions).
381        * Primarily used to free up some memory and to accelerate the applet.
382        */
383        class ClearPressed extends MouseAdapter{
384            public void mousePressed(MouseEvent e){
385                //Button Pressed
386                if(screenOne.view == 1){
387                    oldDataH.clear();
388                }else if(screenOne.view == 2){
389                    oldData.clear();
390                }else if(screenOne.view == 3){
391                    oldSecondMoon.clear();
392                    oldDataH.clear();
393                    oldData.clear();
394                }else{
395                    oldCoRotational.clear();
396                }
397                
398                
399                
400            }
401        }
402        
403        /**
404        * A little nested class which extends <code>MouseAdapter</code>.
405        * Listens to button presses on the main GUI.
406        * Allows to switch between the different view options of the simulation.
407        */
408        class HelioPressed extends MouseAdapter{
409            public void mousePressed(MouseEvent e){
410                //Button Pressed
411                //oldDataH.clear();
412                //oldData.clear();
413                if(screenOne.view == 1){
414                    screenOne.view = 2;
415                }else if(screenOne.view == 2){
416                    screenOne.view = 3;
417                }else if(screenOne.view == 3){
418                    screenOne.view = 4;
419                }else{
420                    screenOne.view = 1;
421                }
422                
423            }
424        }
425        
426        /**
427        * A little nested class which extends <code>MouseAdapter</code>.
428        * Listens to button presses on the main GUI.
429        * Allows to change cruithnes velocities and mass.
430        */
431        class MomentumChange extends MouseAdapter{
432            public void mousePressed(MouseEvent e){
433                screenOne.changeMomentum = true;
434                
435            }
436        }
437        
438        /**
439        * A little nested class which extends <code>MouseAdapter</code>.
440        * Listens to button presses on the main GUI.
441        * Allows to import cruithnes velocities and mass.
442        */
443        class ImportUpdatedMomentum extends MouseAdapter{
444            public void mousePressed(MouseEvent e){
445                screenOne.now = screenOne.changer.getUpdatedVelocities();
446                objects[9].setM(screenOne.changer.getUpdatedMass());
447                screenOne.changer.terminate();
448                screenOne.pause = false;
449                screenOne.repaint();
450                
451                
452                
453            }
454        }
455        
456        
457        
458        
459        
460        
461        /**
462        * A nested class which extends <code>JPanel</code> and implements <code>Runnable</code>.
463        * Used to create the a painting area in which the planets and their orbits will be displayed.
464        * Runnable was implemented to use different threads for drawing orbits and calculating
465        * new data, but it was so far not necessary to use it due to the "double buffer" option
466        * on Swing grafik components.
467        */
468        class ScreenOne extends JPanel implements Runnable{
469            /**
470            * Will hold the updated coordinates and velocities of all space objects after integration. 
471            */
472            PointN now;
473            /**
474            * A linear correction factor that scalls down the distance between planets to a few pixel. 
475            */
476            double distPerPixel;
477            /**
478            * The horizontal center of the display panel on which the planets and orbits will be drawn (a x coordinate). 
479            */
480            int middleX;
481            /**
482            * The vertical center of the display panel on which the planets and orbits will be drawn (a x coordinate). 
483            */
484            int middleY;
485            int middleZ;
486            /**
487            * Number of earth days that that the simulations is running so far. 
488            */
489            int days = 0;
490            /**
491            * Holding different colors for differnet space objects. 
492            */
493            Color[] colours = new Color[10];
494            /**
495            * If true, then the simulations is in Pause mode. 
496            */
497            boolean pause = false;
498            /**
499            * If true, then the orbits are displayed. 
500            */
501            boolean write = false;
502            /**
503            * Can take three different integer values, each one corresponding 
504            * to special view mode of the simulation.
505            * 1 = helio centric;   2 = geo centric;   3 = special second moon view;
506            */
507            int view = 1; // can take 3 values: 1=helio; 2=geo; 3=coRot;
508            /**
509            * If true, then the the momentum change option comes up before the next integration step. 
510            */
511            boolean changeMomentum = false;
512            /**
513            * Needed to get the data out.
514            */
515            FileWriter out;
516            /**
517            * Needed to get the data out.
518            */
519            BufferedWriter myWriter;
520            /**
521            * Instance of MomentumChanger class which allows to change cruithnes momentum during the simulation
522            */
523            MomentumChanger changer;
524            /**
525            * A counter which will keep the orbit data low. Only every 3 earth days
526            * the coordinates will be added to the vector holding old positons. So 
527            * this integer will count to 3, data will be stored, and the reset to 0.
528            */
529            int countTillThree = 1;
530            
531            
532            // the CONSTRUCTOR
533            /**
534            * Constructs a <code>ScreenOne</code> which will act as my drawing bord for planets and orbits.
535            *
536            * @param objects the array of Space Objects making up my Solar System. 
537            * @param startPoint the initial positons and velocities of all Space Objects.
538            */
539            public ScreenOne(SpaceObject[] objects, PointN startPoint){
540                setBackground(Color.black);
541                
542                now = startPoint;
543                
544                colours[0] = Color.yellow; //sun
545                colours[1] = Color.gray;   //mercury
546                colours[2] = Color.orange; //venus
547                colours[3] = Color.blue;   //earth
548                colours[4] = Color.red;    //mars   
549                colours[5] = Color.orange; //juptier
550                colours[6] = Color.cyan;   //saturn
551                colours[7] = Color.green;  //uranus
552                colours[8] = Color.blue;   //neptun
553                colours[9] = Color.white;   //cruithne
554                
555                
556            }
557            /**
558            * A little method to calculate the scaling factor for drawing the planets.
559            * It will update the <code>distPerPixel</code> field in <code>ScreenOne</code>.
560            * @param w the width of the ScreenOne I am drawing onto. It's size is defind by layout managers. 
561            */
562            public void scaling(){
563                // this is a scalling for the inner 8 planets
564                // such that neptunes orbit will max. screensize
565                double neptuneDistance = 4495.1*Math.pow(10,9);
566                int scale = scaleSlider.getValue();
567                middleX = getWidth()/2;
568                middleY = getHeight()*4/10;
569                middleZ = getHeight()*9/10;
570                if (middleX >= middleY){
571                    distPerPixel = neptuneDistance/((middleY - 10)*scale);
572                }else{
573                    distPerPixel = neptuneDistance/((middleX - 10)*scale);
574                }
575                
576            }
577            
578            
579            
580            /**
581            * The Paint() method is the heart of the simulation. Carrying out all the drawing, saving old
582            * coordinates and creating new integrators (one per earth day) in a infinite loop.
583            * @param g the Graphics Object on which we paint. 
584            */
585            
586            public void paint(Graphics g){
587                //can do the scaling calc now, as I only know now the window size
588                scaling();
589                
590                super.paint(g);
591                
592                double xEarth = now.coordinate(3*6+0);
593                double yEarth = now.coordinate(3*6+1);
594                double zEarth = now.coordinate(3*6+2);
595                // stuff for the co rotational view
596                double thetaEarth = Math.atan2(yEarth,xEarth); // result in range -PI to +PI
597                if (thetaEarth < 0.0)
598                    thetaEarth = thetaEarth + 2*Math.PI;
599                
600                
601                for (int i = 0; i < objects.length; i++){
602                    double x = now.coordinate(i*6+0);
603                    double y = now.coordinate(i*6+1);
604                    double z = now.coordinate(i*6+2);
605                    
606                    
607                    if (countTillThree == 3){ // this is data collection for orbit display
608                        oldDataH.add(new Double(x));
609                        oldDataH.add(new Double(y));
610                        oldDataH.add(new Double(z));
611                        
612                        oldData.add(new Double(x - xEarth));
613                        oldData.add(new Double(y - yEarth));
614                        oldData.add(new Double(z - zEarth));
615                        if (i == 9){ //cruithne: special vectors to store special views
616                            oldSecondMoon.add(new Double(x-xEarth));
617                            oldSecondMoon.add(new Double(y-yEarth));
618                            oldSecondMoon.add(new Double(z-zEarth));
619                            double r = Math.sqrt(x*x+y*y);
620                            double theta = Math.atan2(y,x);
621                            if (theta < 0.0)
622                                theta = theta + 2*Math.PI;
623                            
624                            theta = theta - thetaEarth;
625                            double xCoRot = r*Math.cos(theta);
626                            double yCoRot = r*Math.sin(theta);
627                            
628                            oldCoRotational.add(new Double(xCoRot));
629                            oldCoRotational.add(new Double(yCoRot));
630                            oldCoRotational.add(new Double(z));
631                            
632                        }
633                        
634                    }
635                    
636                    
637                    if (view == 1){ //helio centric
638                        g.setColor(Color.yellow);
639                        g.fillOval(middleX-2, middleY-2, 4, 4);
640                        g.fillOval(middleX-2, middleZ-2, 4, 4);
641                        g.setColor(Color.white);
642                        g.drawString("Days: "+days, 8, 12);
643                        g.drawString("Heli centric view", 8, 22); 
644                        
645                        x = x/distPerPixel;
646                        y = y/distPerPixel;
647                        z = z/distPerPixel;
648                        
649                        int xx = middleX + (int)x; // adapt cordinates
650                        int yy = middleY + (int)y;
651                        int zz = middleZ + (int)z;
652                        
653                        g.setColor(colours[i]);
654                        g.fillOval(xx-2, yy-2, 4, 4);
655                        g.fillOval(xx-2, zz-2, 4, 4);
656                        
657                        
658                    }
659                    if (view == 2){ // this is GEO CENTRIC
660                        g.setColor(Color.blue);
661                        g.fillOval(middleX-2, middleY-2, 4, 4);
662                        g.fillOval(middleX-2, middleZ-2, 4, 4);
663                        g.setColor(Color.white);
664                        g.drawString("Days: "+days, 8, 12);
665                        g.drawString("Geo centric view", 8, 22); 
666                        
667                        if(i != 3){ // this excludes earth, is i have draw it manually already
668                            
669                            x = x - xEarth;
670                            y = y - yEarth;
671                            z = z - zEarth;
672                            
673                            x = x/(distPerPixel);
674                            y = y/(distPerPixel);
675                            z = z/(distPerPixel);
676                            
677                            int xx = middleX + (int)x; // adapt coordinates
678                            int yy = middleY + (int)y;
679                            int zz = middleZ + (int)z;
680                            
681                            g.setColor(colours[i]);
682                            g.fillOval(xx-2, yy-2, 4, 4);
683                            g.fillOval(xx-2, zz-2, 4, 4);
684                        }
685                        
686                        
687                    }
688                    
689                    
690                    if (view == 3){ // this is the special moon view
691                        if (i == 9){
692                            g.setColor(Color.white);
693                            g.drawString("Days: "+days, 8, 12);
694                            g.drawString("Earth's second moon view", 8, 22); 
695                            //sun
696                            g.setColor(Color.yellow);
697                            g.fillOval(middleX-2, middleY-2, 4, 4);
698                            g.fillOval(middleX-2, middleZ-2, 4, 4);
699                            //earth
700                            //double d = Math.sqrt(xEarth*xEarth + yEarth*yEarth);
701                            //d = d/(distPerPixel);
702                            //adapt coordinates
703                            int ex = (int) (xEarth/distPerPixel);
704                            int ey = (int) (yEarth/distPerPixel);
705                            int ez = (int) (zEarth/distPerPixel);
706                            
707                            g.setColor(Color.blue);
708                            g.fillOval(middleX+ex-2, middleY+ey-2, 4, 4);
709                            g.fillOval(middleX+ex-2, middleZ+ez-2, 4, 4);
710                            //cruithne
711                            x = (x)/(distPerPixel);
712                            y = (y)/(distPerPixel);
713                            z = (z)/(distPerPixel);
714                            g.setColor(Color.white);
715                            g.fillOval((int)(middleX+x-2), (int)(middleY+y-2), 4, 4);
716                            g.fillOval((int)(middleX+x-2), (int)(middleZ+z-2), 4, 4);
717                            // draw history lines if "write" is pressed
718                            
719                        }
720                    }
721                    if (view == 4){ //Co Rotational frame
722                        g.setColor(Color.yellow);
723                        g.fillOval(middleX-2, middleY-2, 4, 4);
724                        g.fillOval(middleX-2, middleZ-2, 4, 4);
725                        g.setColor(Color.white);
726                        g.drawString("Days: "+days, 8, 12);
727                        g.drawString("Co Rotational view", 8, 22); 
728                        
729                        double r = Math.sqrt(x*x+y*y);
730                        double theta = Math.atan2(y,x);
731                        if (theta < 0.0)
732                            theta = theta + 2*Math.PI;
733                        
734                        theta = theta - thetaEarth;
735                        x = r*Math.cos(theta);
736                        y = r*Math.sin(theta);
737                        
738                        x = x/distPerPixel;
739                        y = y/distPerPixel;
740                        z = z/distPerPixel;
741                        
742                        int xx = middleX + (int)x; // adapt cordinates
743                        int yy = middleY + (int)y;
744                        int zz = middleZ + (int)z;
745                        
746                        g.setColor(colours[i]);
747                        g.fillOval(xx-2, yy-2, 4, 4);
748                        g.fillOval(xx-2, zz-2, 4, 4);
749                        
750                        
751                    }
752                }
753                // draw history lines if "write" is pressed for the helio centric view
754                if (write && view == 1){ //write
755                    int length = oldDataH.size();
756                    int sectionLength = (objects.length)*3;
757                    int numberOfSections = length/sectionLength;
758                    for(int j = 0; j < (numberOfSections-1); j++){
759                        for (int i = 1; i < objects.length; i++){
760                            if(objects[i].getDisplay()){
761                                g.setColor(colours[i]);
762                                // get start point of line
763                                double x = ((Double) oldDataH.get(3*i + j*sectionLength)).doubleValue();
764                                double y = ((Double) oldDataH.get(3*i+1+j*sectionLength)).doubleValue();
765                                double z = ((Double) oldDataH.get(3*i+2+j*sectionLength)).doubleValue();
766                                
767                                x = x/(distPerPixel);
768                                y = y/(distPerPixel);
769                                z = z/(distPerPixel);
770                                
771                                g.fillRect((int)x+middleX, (int)y+middleY, 1, 1);
772                                g.fillRect((int)x+middleX, (int)z+middleZ, 1, 1);
773                            }
774                        }
775                    }
776                }
777                // draw history lines if "write" is pressed for the geo centric view
778                if (write && view == 2){
779                    int length = oldData.size();
780                    int sectionLength = (objects.length)*3;
781                    int numberOfSections = length/sectionLength;
782                    
783                    for(int j = 0; j < (numberOfSections-1); j++){
784                        for (int i = 0; i < objects.length; i++){
785                            if(i != 3 && objects[i].getDisplay()){ // the unequal 3 is to skip earth
786                                g.setColor(colours[i]);
787                                
788                                double x = ((Double) oldData.get(3*i + j*sectionLength)).doubleValue();
789                                double y = ((Double) oldData.get(3*i+1+j*sectionLength)).doubleValue();
790                                double z = ((Double) oldData.get(3*i+2+j*sectionLength)).doubleValue();
791                                x = x/(distPerPixel);
792                                y = y/(distPerPixel);
793                                z = z/(distPerPixel);
794                                g.fillRect((int)x+middleX, (int)y+middleY, 1, 1);
795                                g.fillRect((int)x+middleX, (int)z+middleZ, 1, 1);
796                                
797                            }
798                        }
799                    }
800                }
801                //special second moon view
802                if (write && view == 3){ 
803                    int length = oldSecondMoon.size();
804                    int numberOfSections = length/3;
805                    for(int j = 0; j < (numberOfSections-1); j++){
806                        
807                        g.setColor(Color.red);
808                        double x = ((Double) oldSecondMoon.get(3*j+0)).doubleValue();
809                        double y = ((Double) oldSecondMoon.get(3*j+1)).doubleValue();
810                        double z = ((Double) oldSecondMoon.get(3*j+2)).doubleValue();
811                        x = x/(distPerPixel);
812                        y = y/(distPerPixel);
813                        z = z/(distPerPixel);
814                        
815                        int ex = (int) (xEarth/distPerPixel);
816                        int ey = (int) (yEarth/distPerPixel);
817                        int ez = (int) (zEarth/distPerPixel);
818                        
819                        g.fillRect((int)x+ex+middleX, (int)y+ey+middleY, 1, 1);
820                        g.fillRect((int)x+ex+middleX, (int)z+ez+middleZ, 1, 1);
821                        
822                    }
823                    length = oldDataH.size();
824                    int sectionLength = (objects.length)*3;
825                    numberOfSections = length/sectionLength;
826                    for(int j = 0; j < (numberOfSections-1); j++){
827                        for (int i = 3; i <= 9; i=i+6){ //only earth and cruithne
828                            if(objects[i].getDisplay()){
829                                g.setColor(colours[i]);
830                                // get start point of line
831                                double x = ((Double) oldDataH.get(3*i + j*sectionLength)).doubleValue();
832                                double y = ((Double) oldDataH.get(3*i+1+j*sectionLength)).doubleValue();
833                                double z = ((Double) oldDataH.get(3*i+2+j*sectionLength)).doubleValue();
834                                
835                                x = x/(distPerPixel);
836                                y = y/(distPerPixel);
837                                z = z/(distPerPixel);
838                                
839                                g.fillRect((int)x+middleX, (int)y+middleY, 1, 1);
840                                g.fillRect((int)x+middleX, (int)z+middleZ, 1, 1);
841                            }
842                        }
843                    }
844                }
845                // special co rotating view
846                if (write && view == 4){ 
847                    int length = oldCoRotational.size();
848                    int sectionLength = 3; // only x/y/z coordinates of cruithne 
849                    int numberOfSections = length/sectionLength;
850                    for(int j = 0; j < numberOfSections; j++){
851                        if(objects[9].getDisplay()){
852                            g.setColor(colours[9]);
853                            
854                            double x = ((Double) oldCoRotational.get(j*sectionLength)).doubleValue();
855                            double y = ((Double) oldCoRotational.get(1+j*sectionLength)).doubleValue();
856                            double z = ((Double) oldCoRotational.get(2+j*sectionLength)).doubleValue();
857                            
858                            x = x/(distPerPixel);
859                            y = y/(distPerPixel);
860                            z = z/(distPerPixel);
861                            
862                            g.fillRect((int)x+middleX, (int)y+middleY, 1, 1);
863                            g.fillRect((int)x+middleX, (int)z+middleZ, 1, 1);
864                        }
865                    }
866                }
867                
868                
869                
870                
871                // momentum change of cruithne
872                if (changeMomentum){
873                    pause = true;
874                    // get cruithnes mass
875                    double m = objects[9].getM();
876                    // bring up a new window
877                    changer = new MomentumChanger(now, m);
878                    changer.setVisible(true);
879                    changer.repaint();
880                    
881                    changeMomentum = false;
882                }
883                
884                // watch the free memory of the machine and clear the old
885                // orbit data if I am short on memory
886                Runtime r = Runtime.getRuntime();
887                long freeMemory = r.freeMemory();
888                if (freeMemory <= 102400){
889                    oldSecondMoon.clear();
890                    oldDataH.clear();
891                    oldData.clear();
892                    oldCoRotational.clear();
893                    System.gc();
894                    
895                }
896                                
897                
898                // make another integrator, for another day and increase the number of days by one.
899                SolarIntegrator integ = new SolarIntegrator(objects, 0.0, 86400.0, now, 7);
900                if(pause == false){
901                    now = (PointN) integ.integrate();
902                    days = days + 1;
903                    countTillThree++;
904                    
905                    if (countTillThree == 4)
906                        countTillThree = 1;
907                    
908                    repaint();
909                    
910                }else{
911                    g.setColor(Color.white);
912                    g.drawString("SIMULATION PAUSED !!!", 38, 84); 
913                }
914                
915            }
916            
917            // little method to calc the distance between the current object and an other space object
918            /**
919            * calculates the distance of a <code>SpaceObject</code> s from a certain position in 3D.
920            * @param s a <code>SpaceObject</code>.
921            * @param x cartesian x coordinate of a point in 3D.
922            * @param y cartesian y coordinate of a point in 3D.
923            * @param z cartesian z coordinate of a point in 3D.
924            * @return the distace beetween the <code>SpaceObject</code> s and the point in 3D.
925            */
926            public double getDistance(SpaceObject s, double x, double y, double z){
927                PointN pos = s.getC();
928                double sx = pos.coordinate(0);
929                double sy = pos.coordinate(1);
930                double sz = pos.coordinate(2);
931                double xx = sx-x;
932                double yy = sy-y;
933                double zz = sz-z;
934                return Math.sqrt((Math.pow(xx, 2) + Math.pow(yy, 2) + Math.pow(zz, 2)));
935            }
936            
937            
938            /**
939            * not needed as it turned out that I don't need seperate Threads
940            */
941            public void run(){
942            }
943        }
944    }
945    
946    
947    
948    
949    
950    
951    
952    
953    
954