cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              * {
  font-family: Arial, Helvetica, sans-serif;
  color: black;
  font-size: small;
  }
p {
  font-size: medium;
}

input {
    height: 15px;
    width: 15px;
  
}
}
            
          
!
            
              /*
Copyright 2018 Simon Shack, Patrik Holmqvist

The TYCHOSIUM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


The TYCHOSIUM is a simulator of Simon Shack's solar system model called "the TYCHOS". Simon's book (that explains this model) is available at the www.Tychos.info website-

TYCHOSIUM Planetarium - DESCRIPTION 

Frame "0" in the Tychosium planetarium corresponds to JUNE 21, 2000.
 
About the TYCHOS OPTIMAL MODE (and its “0.9999605429” value ):
This setting determines that 1 year equals 365.2205695 days - the ideal / most desirable year count (as computed in the TYCHOS model): this optimal year count ensures that the SUN remains “synched” to EARTH’s motion around its PVP orbit. Since EARTH moves ‘clockwise’ by about 14036 km each year, the Sun’s ‘anticlockwise’ motion needs to be shortened by that amount” (which equals 0.0014932 % of the Sun’s annual motion).    
In fact, the Tychos Optimal value of “0.9999605429” is precisely 0.0039457% less than “1” (i.e. 360° in the Tychosim). This 0.0039457 value represents Earth’s annual motion as ‘projected’ onto the Sun’s larger orbit.  

ABOUT THE TYCHOSIUM GREGORIAN MODE (and its “1.00001978285” value): 
This setting determines that 1 year equals 365.24219 days - i.e. the current Gregorian year count. It is this imperfect Gregorian year count that causes the Sun to revolve slightly more than one full revolution around Earth each year.  

THE TYCHOSIUM in "Gregorian mode":
In order to faithfully simulate the Gregorian year count (what with its OBSERVED Eastwardly solar procession of 1 hour of RA every 2112 years - i.e. 0.02840909 min of RA per solar revolution), the TychoSium makes the Sun drift (Eastwards / i.e. anticlockwise) by 0.02840909 min of RA per year. (Note that 25,344 years X 0.002.840909 min = 720 min, i.e. half of 1440 min, our full celestial sphere. As it is, under the Gregorian calendar count, the Sun will (undesirably) end up on the opposite side of our system in 25,344 years. 

In the Tychosium, we therefore simulate this (Gregorian) yearly drift by making the Sun return annually to a point corresponding to an extra 0.02840909 min of Right Ascension. Now, 0.02840909min = 0.00197285347% of 1440 min (our full celestial sphere). This is the reason for our  “1.0000197825347” value for the Gregorian year - since this value is 0.00197285347% larger than “1” (or 360°) 

Note that 0.00197285% of 9,250,560 (the number of days in a 25344-year Great Year of 365 integer calendar days) = 182.5 days - i.e. exactly ½ of 365 calendar days. The Sun will thus end up at the opposed side of the system in 25344 year - under the Gregorian year count.

Note that 0.0039457 % (difference btw a “360° year” and a “Tychos Optimal” year) + 0.00197285% (difference btw the “360°” and the Gregorian year) = 0.00591855 % : this is the total difference between the Tychos Optimal and Gregorian year. And in fact, 0.00591855% of 25344 = 1.5 years. Since Earth completes 1 “clockwise” revolution in 25344 years, these 1.5 years represent the ONE revolution that Earth ‘subtracts’ from the Sun + the ½  year that the imperfect Gregorian year count adds to the Sun’s motion.  

The Tychos Optimal value should also (although this needs further study) ideally keep the Sun's inclination on June 21 at around the current 'midway' tilt of circa 23.3°. In fact, astronomy literature states that "the angle of the Earth's axial tilt with respect to the orbital plane (the obliquity of the ecliptic) varies between 22.1° and 24.5°, over a cycle of about 40,000 years". (Note that 23.3° is 'midway' between 22.1° and 24.5°). Of course, in the TYCHOS model, Earth's axis is not tilted : all the orbits of our surrounding planets are (incl. the Sun). Now, since 40,000 years equals circa 1.5 X 25,344 - and since the Gregorian year count causes the Sun to end up on the opposite side of our system, we may assume that this "40,000 year" figure has been erroneously estimated - and that the true variation (22.1° > 24.5°) spans instead across circa 25,344 years. Hence, by "locking" the Sun's and Earth's respective motions with each other FROM NOW ON (i.e. epoch 2000) would seem to be an ideal way to obtain a desirable long-term "calendar-stability" of our seasons, for a number of obvious (agricultural / statistical / climate-related)  reasons.    

ABOUT THE SPEED OF MARS:
Mars's average "sidereal period" is 686.95 days. This is the MEAN time period needed for Mars to revolve ONCE AROUND THE SUN. 
We shall therefore divide it by the solar sidereal period (365.253636 days).

Now, 686.95/ 365.256363 = 1.8807338340605444839300444986362

Mars's relative speed is obtained by dividing 25344 (the number of years in a Tychos Great Year) with this value:
25344 / 1.8807338340605444839300444986362 = 13475.5


ABOUT THE SPEED OF VENUS:
Venus revolves once around the Sun in a mean period of  224.701 days.  We shall therefore divide this value by the solar sidereal year period (365.256363 days)

Now, 224.701/ 365.256363= 0.61518709257913735509653530662791

Venus's relative speed is obtained by dividing 25344 (the number of years in a TGY) with this value:
25344 / 0.61518709257913735509653530662791 = 41197.22326


ABOUT THE SPEED OF MERCURY :
Mercury revolves once around the Sun in a mean period of 87.969 days.  We shall therefore divide this value by the solar sidereal year period (365.256363 days).

Now, 87.969 / 365.256363= 0.2408418002015751331346416544152

Mercury's relative speed is obtained by dividing 25344 (the number of years in a TGY) with this value:
25344 / 0.2408418002015751331346416544152= 105230.902521

ABOUT THE SPEED OF THE MOON
Our Moon circles Earth once every 27.32165days (its sidereal period) Therefore, in the TychoSim, the Moon’s speed is set at :
365.256363 (our sidereal year) / 27.32165 (Moon's sidereal period)= 13.36875

ABOUT THE VARIOUS ORBITAL DIMENSIONS:
 The dimension of the Sun's orbit is set at "100". 
These are the known orbital diameters our surrounding celestial companions:

SUN orbital  Ø : 299,193,439 km
MARS orbital Ø: 456,800,000 km
VENUS orbital Ø : 216,400,000 km
MERCURY orbital Ø : 115,818,454 km  
EARTH orbital Ø : 113,230,656 km
MOON orbital Ø: 763.095 km

Accordingly, the sizes of the orbits of the Sun's companions are set as follows:

(SUN: 100)
MARS: 152.677
VENUS: 72.327789
MERCURY: 38.710225
EARTH : 37.8453 (size of "PVP" orbit) 
MOON: not to scale (due to graphic constraints)

The entire TYCHOS PLANETARIUM starts on June 21, 2000 (FRAME "0"). On June 21, 2000, the observed / relative startPos values of each of our celestial companions were as follows:

StartPOS of SOL: 0
StartPOS of MARS: 4
StartPOS of VENUS:  -1
StartPOS of Mercury: -144
StartPOS of MOON: 127 

ABOUT the “BROWN DISC”: this is the virtual disc (or circular area) inside which the Sun’s orbit precesses in 25344 years. You can toggle it on or off with the ‘Brown disc’ button.

ABOUT THE STARS:
Earth is currently (in epoch J2000) transiting underneath star Polaris. About 4800 years ago, Thuban was our North star. In about 10,800 years, Vega will be our North star.


*/


const framesPerYear = 365.24219;

const startDate = "2000-06-21";
const startDateNumber = dateToDays(startDate);


const TGY = 25344; //Tychos Great Year
const gregorianYear = 1.0000197;     
const patriciusYear = 1;   
const simonShackYear = 0.999960543;         

var yearFact = simonShackYear;
var yearType = 'Tychos Optimal';
const EarthSize = 10;  

const twoPI = Math.PI*2;

var earth = {
  size: 10,   
  startPos:0,    
  speed: -twoPI/TGY,    
  radius: 37.8453,
  color: [87, 139, 124],
  drawOrbit: true,
  inc: 0,
  positions: [],
  show: true
};

var sol = {
  size: 20,   
  startPos:0,    
  speed: twoPI,    
  radius: 100,
  offsetx: -0.5, 
  offsety: -1,  
  color: [254, 169, 13],
  drawOrbit: true,
  tracing: true,
  tracingAlpha: 200,
  tracingStrokeW: 2,
  inc: 0,
  positions: [],
  show: true
};

var moon = {
  size: 2,   
  startPos: 127,                        
  speed:  13.36875 * twoPI,                                                                  
  radius: 10,
  offsetx: 0, 
  offsety: 0,  
  color: [134,132,133],
  drawOrbit: true,
  inc: 0,
  positions: [],
  show: true
};


var mercuryDef = {
  size: 3, 
  startPos:0,                                       
  speed: twoPI,                          
  radius: 100,         
  orbitx:-4,                                 
  orbity:7,                              
  drawOrbit: true,    
  inc: 0,
  positions: []
};


var mercury = {
  size: 5,
  startPos:-142,                                                                                                                                
  speed: 105230.902521*twoPI/TGY,                        
  //(105228/TGY*2)*Math.PI
  //105228*Math.PI*2/TGY
  //26.0877139955766069

  radius: 38.710225,                                           
  color: [134,132,133], //Color of the planet and its trace as RGB
  drawOrbit: true,     
  tracing: true, //Trace orbit (true/false)
  tracingAlpha: 200, //Opacity of the trace line (0-255) 255=strongest
  tracingStrokeW: 1, //Width of trace. Higher number = wider
  inc: 0,
  positions: [],
  show: true
};

var venusDef = {
  size: 3,
  startPos: 2,                                            
  speed: twoPI,                                     
  radius: 100,         
  orbitx:-1,                             
  orbity:-2,                   
  drawOrbit: true,     
  inc: 0,
  positions: []
};


var venus = {
  size: 9,   
  startPos:-4,                                                                             
  speed: 41197.22326*twoPI/TGY,                                      
  //41196.7*twoPI/TGY
  //10.2133310330794604140690075862150947765656220346790587352907883
  radius: 72.327789, 
  color: [165,124,27], //Color of the planet and its trace as RGB
  drawOrbit: true,  
  tracing: true, //Trace orbit (true/false)
  tracingAlpha: 200, //Opacity of the trace line (0-255) 255=strongest
  tracingStrokeW: 1, //Width of trace. Higher number = wider
  inc: 0,
  positions: [],
  show: true
};


var marsDef = {
  size: 3,  
  startPos: 0,                              
  speed: twoPI,       
  radius: 100, 
  orbitx: -11,                
  orbity: -12,                             
  drawOrbit: true,
  inc: 0,
  positions: []

};

var mars = {
  size: 6,  
  startPos:3,                 
  speed: 13475.5*twoPI/TGY,                                             
  //13475.5     
  radius: 152.673,   
  drawOrbit: true,  
  tracing: true,   
  tracingAlpha: 200,
  tracingStrokeW: 1.5,  
  inc: 0,
  positions: [],
  show: true
};


var stars = {
  show: true,
  color: [170,170,170], //Color as RGB
  polarisx: 0.5, //x position
  polarisy: -39, //y position
  polarisSize: 6, //size
  vegax: 20,
  vegay: 42,
  vegaSize: 6,
  thubanx: -35,
  thubany: -15,
  thubanSize: 6
};
var moreStars = [
  {
    show: false, //Show/hide star when stars is checked
    name: "A star", //Star name
    namex: 10, //Name pos in relation to star
    namey: 0,   
    color: [170,170,170], //Color as RGB
    x: 0, //Star x position
    y: -100, //Star y position
    size: 6, //Star size
  },
  {
    show: false,
    name: "A smaller star",
    namex: 5, 
    namey: 0,   
    color: [170,170,170], //Color as RGB
    x: 0, //x position
    y: -200, //y position
    size: 3, //size
  }
];



var disc = {
  show: false,
  color: [82, 60, 15],
  x: 0, 
  y: 0, 
  size: sol.radius*2 + earth.radius *2
}

var monthRing = {
  show: false,
  x: 0, //x axis placement
  y: 0, //y axis placement
  pos: 0, // Rotation start pos
  gregorianSpeed: -(Math.PI/TGY), //How much shall the ring rotate during different years
  patriciusSpeed: 0,      //Math.PI = 180 degrees, Math.PI*2 = 360 degrees
  tychosSpeed: twoPI/TGY,    
  size: 0.4, //size
  img: "" 
}

var zodiacRing = {
  show: false,
  x: 0,    
  y: -11,     
  pos: 0,
  size: 0.96, 
  img: ""
}


//const tracing = false; //Trace Mars orbit (true/false)
//const tracingAlpha = 200; //Opacity of the Mars trace line (0-255) 255=strongest
//const tracingStrokeW = 2; //Width of trace. Higher number = wider

var traceOn = false;
var reverseOn = false;
var pause = true;
var light = false;
var drawDisc = false;
var drawDeferent = false;
var drawOrbits = true;
var progTrace = false;
var drawFrame = true;
var calcFrame = true;
var frame = 0;
var speedFact = 1;

const initMaxFrames = 1800*3.65;
var maxFrames;
var zoomLevel;

function setup() {
  maxFrames = initMaxFrames;
  //createCanvas(windowWidth, windowHeight);
  createCanvas(900, 700);
  earth.startPos = radians(earth.startPos-90);
  sol.startPos = radians(sol.startPos-90);
  moon.startPos = radians(moon.startPos-90);
  mercuryDef.startPos = radians(mercuryDef.startPos-90);  
  mercury.startPos = radians(mercury.startPos-90);
  venusDef.startPos = radians(venusDef.startPos-90);  
  venus.startPos = radians(venus.startPos-90);
  marsDef.startPos = radians(marsDef.startPos-90);
  mars.startPos = radians(mars.startPos-90);
  
  //https://s3-us-west-2.amazonaws.com/s.cdpn.io/1127272/MONTH_RING.png
  //https://s3-us-west-2.amazonaws.com/s.cdpn.io/1127272/ZODIAC_RING.png
  
  //monthRing.img = loadImage("https://s3-us-west-2.amazonaws.com/s.cdpn.io/1127272/mRing.png");
  monthRing.img = loadImage("https://s3-us-west-2.amazonaws.com/s.cdpn.io/1127272/mRing.png");
  zodiacRing.img = loadImage("https://s3-us-west-2.amazonaws.com/s.cdpn.io/1127272/zRing.png");
  setupGUI();

  
}

function draw() {
  
  
  setSpeed();
  if (calcFrame) {
    if (!progTrace) {
      while (mars.positions.length < maxFrames) {
        fCalcFrame(frame - (maxFrames - mars.positions.length)*speedFact);
      };
    };
    fCalcFrame(frame);      
  };

  if (drawFrame) {
    //Lets draw
    if (light) {background(230)} else {background(60, 64, 67)};// clear the screen
    fill(color(192,192,192));
    stroke('grey');
    rect(0, 0, 210, height);
    let softWhite = color(255,250,250);
    fill(softWhite);stroke(softWhite);
    //Type some text in the upper left corner
    textSize(15);
    //currZoom.elt.innerHTML = zoomLevel.toString() + "%";
    let nCurrDay = Math.trunc(frame);
    currDay.html(nCurrDay);

    currDate.html(daysToDate(startDateNumber + nCurrDay));
    //text('Current year.frame: ' + Math.trunc(frame/framesPerYear), 10, 110);
//    text('Current daynumber: ' + Math.trunc(frame), 10, 110);
    //text('Frame: ' + frame, 10, 500);
    //text('Speed: ' + Math.round(speedFact*100) + "%", 10, 200);

    currSpeed.elt.innerHTML = speedSlider.value() + "%";
    //text('Speed: ' + speedSlider.value() + "%", 10, 200);
    //console.log(zSlider.value());
    
    translate(width/2+100, height/2);
    let ePos = earth.positions[earth.positions.length - 1];

    if (disc.show) {
      noStroke();
      fill(disc.color);
      ellipse(disc.x, disc.y, disc.size, disc.size);
    };
    //Draw Zodiac and Month ring
    if (zodiacRing.show) {
      rotate(zodiacRing.pos);
      image(zodiacRing.img, zodiacRing.x - zodiacRing.img.width/2*zodiacRing.size, 
            zodiacRing.y - zodiacRing.img.height/2*zodiacRing.size, 
            zodiacRing.img.width*zodiacRing.size, zodiacRing.img.height*zodiacRing.size);
    }


    //trace mercury
    if (traceOn && mercury.show) {
      noFill();
      beginShape();
      stroke(mercury.color, mercury.tracingAlpha);
      strokeWeight(mercury.tracingStrokeW);
      for (let i = 0; i < mercury.positions.length; i++) {
        let pos = mercury.positions[i];
        vertex(pos.x, pos.y) 
      }
      endShape();
      strokeWeight(1);
    };

    //trace venus
    if (traceOn && venus.show) {
      noFill();
      beginShape();
      stroke(venus.color,venus.tracingAlpha);
      strokeWeight(venus.tracingStrokeW);
      for (let i = 0; i < venus.positions.length; i++) {
        let pos = venus.positions[i];
        vertex(pos.x, pos.y) //draw trace
      }
      endShape();
      strokeWeight(1);
    };
    //trace Mars
    if (traceOn && mars.show) {
      noFill();
      beginShape();
      stroke(255,0,0,mars.tracingAlpha);
      strokeWeight(mars.tracingStrokeW);
      for (let i = 0; i < mars.positions.length; i++) {
        let pos = mars.positions[i];
        vertex(pos.x, pos.y) //draw trace
      }
      endShape();
      strokeWeight(1);
    };

    //draw Earth orbit
    noFill();
    stroke(earth.color);
    ellipse(0.5, 1,  earth.radius*2, earth.radius*2);
    fill(earth.color);
    let trix = 0.5 - earth.radius;
    let triy = 1;    
    triangle(trix-5, triy, trix, triy-5, trix+5, triy, )
    trix = 0.5 + earth.radius;
    triangle(trix+5, triy, trix, triy+5, trix-5, triy, )
    //draw Earth
    ellipse(ePos.x, ePos.y, earth.size, earth.size);

    //draw Moon
    let moonPos = moon.positions[moon.positions.length - 1];
    if (moon.show) {
      noFill();
      stroke(moon.color);
      if (drawOrbits) {
        ellipse(ePos.x + moon.offsetx, ePos.y + moon.offsety, moon.radius*2, moon.radius*2)
      };
      fill(moon.color);
      ellipse(moonPos.x, moonPos.y, moon.size, moon.size);
    };
   //draw Sol
    let sPos = sol.positions[sol.positions.length - 1];
    if (sol.show) {
      noFill(); //The next circle should not be filled since its an orbit
      stroke(sol.color);
      if (drawOrbits) {
        ellipse(ePos.x + sol.offsetx, ePos.y + sol.offsety, sol.radius*2, sol.radius*2);
        fill(sol.color);
        let trix = ePos.x + sol.offsetx - sol.radius;
        let triy = ePos.y + sol.offsety;    
        triangle(trix+5, triy, trix, triy+5, trix-5, triy, )
        trix = ePos.x + sol.offsetx + sol.radius;
        triangle(trix-5, triy, trix, triy-5, trix+5, triy, )
      };
      fill(sol.color);
      ellipse(sPos.x, sPos.y, sol.size, sol.size);
    };
    //draw Mercury deferent orbit
    let mercdPos = mercuryDef.positions[mercuryDef.positions.length -1];
    if (drawDeferent && mercury.show) {
      noFill();
      stroke(mercury.color, 255);
      ellipse(ePos.x + mercuryDef.orbitx, ePos.y + mercuryDef.orbity, mercuryDef.radius*2, mercuryDef.radius*2)
      fill(mercury.color);
      ellipse(mercdPos.x, mercdPos.y, mercuryDef.size, mercuryDef.size);
    };
    let mercPos = mercury.positions[mercury.positions.length - 1];
    if (mercury.show){
      //draw Mercury
      noFill();
      stroke(mercury.color, 255);
      if (drawOrbits) {ellipse(mercdPos.x, mercdPos.y, mercury.radius*2, mercury.radius*2)}
      fill(mercury.color);
      ellipse(mercPos.x, mercPos.y, mercury.size, mercury.size);
    };
    //draw Venus deferent orbit
    let venusdPos = venusDef.positions[venusDef.positions.length -1];
    if (drawDeferent && venus.show) {
      noFill();
      stroke(venus.color, 255);
      ellipse(ePos.x + venusDef.orbitx, ePos.y + venusDef.orbity, venusDef.radius*2, venusDef.radius*2)
      fill(venus.color);
      ellipse(venusdPos.x, venusdPos.y, venusDef.size, venusDef.size);
    };
    //draw Venus
    let vPos = venus.positions[venus.positions.length - 1];
    if (venus.show){    
      noFill();
      stroke(venus.color, 255);
      if (drawOrbits) {ellipse(venusdPos.x, venusdPos.y, venus.radius*2, venus.radius*2)};
      fill(venus.color);
      ellipse(vPos.x, vPos.y, venus.size, venus.size);
    };
    //draw Mars deferent orbit
    noFill();
    stroke(color('green'), 255);
    let mdPos = marsDef.positions[marsDef.positions.length - 1];
    if (drawDeferent && mars.show) {
      ellipse(ePos.x + marsDef.orbitx, ePos.y + marsDef.orbity, marsDef.radius*2, marsDef.radius*2)
      fill('green');
      ellipse(mdPos.x, mdPos.y, marsDef.size, marsDef.size);
    };
    let mPos = mars.positions[mars.positions.length - 1];
    //draw Mars
    if (mars.show){    
      noFill();
      stroke(color('red'), 255);
      if (drawOrbits) {
        ellipse(mdPos.x, mdPos.y, mars.radius*2, mars.radius*2)
        fill('red');
        let trix = mdPos.x - mars.radius;
        let triy = mdPos.y;    
        triangle(trix+5, triy, trix, triy+5, trix-5, triy, )
        trix = mdPos.x + mars.radius;
        triangle(trix-5, triy, trix, triy-5, trix+5, triy, )

      }
      fill('red');
      ellipse(mPos.x, mPos.y, mars.size, mars.size); //draw Mars
    };
    //draw Stars
    if (stars.show) {
      drawStars();
    }
    if (monthRing.show) {
      push();
      translate(ePos.x, ePos.y);
      let rotFact = monthRing.pos;
      //translate(width*0.5, height*0.5);
      if (yearFact === gregorianYear){
        rotFact = rotFact + monthRing.gregorianSpeed*yearFact/framesPerYear*frame;
      };
      if (yearFact === patriciusYear){
        rotFact = rotFact + monthRing.patriciusSpeed*yearFact/framesPerYear*frame;
      };
      if (yearFact === simonShackYear){
        rotFact = rotFact + monthRing.tychosSpeed*yearFact/framesPerYear*frame;
      };
      rotate(rotFact);
      image(monthRing.img, 
            monthRing.x - monthRing.img.width/2*monthRing.size, 
            monthRing.y - monthRing.img.height/2*monthRing.size, 
            monthRing.img.width*monthRing.size, monthRing.img.height*monthRing.size);
      /*
      image(monthRing.img, 
            (monthRing.x + ePos.x) - monthRing.img.width/2*monthRing.size, 
            (monthRing.y + ePos.y) - monthRing.img.height/2*monthRing.size, 
            monthRing.img.width*monthRing.size, monthRing.img.height*monthRing.size);
      rotate(rotFact);
       */
      pop();
    }

  } //if (drawFrame)
  if (!pause) { // If not paused increase frameToDisp
    if (reverseOn) {
      decFrame();
    } else {
      incFrame();    }
  } else {
    drawFrame = false;
    calcFrame = false;
  }
}

function keyReleased() {
  if (key === " ") {  
    startstop();
  }
};

function startstop() {
  pause = !pause;
  //startButton.value = "hello";
  //startButton.html = "banan";
  //startButton.attribute('value', 'blä');
  if (pause) {
    startButton.html("Start");
    //fButton.removeAttribute('disabled');
    //bButton.removeAttribute('disabled');
  } else {
    startButton.html("Stop");
    //fButton.attribute('disabled', '');
    //bButton.attribute('disabled', '');
  }
};

function stepBack() {
  if (!pause) {startstop()};
  decFrame();
};
function stepForward() {
  if (!pause) {startstop()};
  incFrame();
};

function decFrame() {
  frame = frame - 1*speedFact;
  if (earth.positions.length > 1) {
    earth.positions.pop();
    sol.positions.pop();
    moon.positions.pop();
    mercuryDef.positions.pop();
    mercury.positions.pop();
    venusDef.positions.pop();
    venus.positions.pop();
    marsDef.positions.pop();
    mars.positions.pop();
    drawFrame = true;
    calcFrame = false;
  } else {
    changeFrame(); 
  }
};



function incFrame() {
  frame = frame + 1*speedFact;
  drawFrame = true;
  calcFrame = true;
};

function goToYearDay() {
  let numArr = ydInput.value().split(".");
  frame = Number(numArr[0]) * framesPerYear + (Number(numArr[1]) || 0);
  changeFrame();
};


function changeFrame() {
  earth.positions = [];
  sol.positions = [];
  moon.positions = [];
  mercuryDef.positions = [];
  mercury.positions = [];
  venusDef.positions = [];
  venus.positions = [];
  marsDef.positions = [];
  mars.positions = [];
  drawFrame = true;
  calcFrame = true;
};

function darkLight() {
  light = !light;
  drawFrame = true;
}

function mySelectEvent() {
  yearType = sel.value();
  if (yearType === 'Gregorian'){yearFact = gregorianYear};
  if (yearType === 'Patricius'){yearFact = patriciusYear};
  if (yearType === 'Tychos Optimal'){yearFact = simonShackYear};
  changeFrame();
  /*
  const gregorianYear = 1.0000197834894846796643780982030908;
  const patriciusYear = 1;
  const simonShackYear = 0.999960542929292935;
  */
}
function selSpeedEvent() {
  if (selSpeed.value() === '1'){speedFact = 1};
  if (selSpeed.value() === '1/2'){speedFact = 1/2};
  if (selSpeed.value() === '1/4'){speedFact = 1/4};
  if (selSpeed.value() === '1/8'){speedFact = 1/8};
  if (selSpeed.value() === '1/16'){speedFact = 1/16};
  if (selSpeed.value() === '1/32'){speedFact = 1/32};
  maxFrames = Math.trunc(initMaxFrames/speedFact);
  changeFrame();
  
}

function planetCheckedEvent() {
  if (reverseCB.checked()){reverseOn = true}else{reverseOn = false};
  if (traceCB.checked()){traceOn = true}else{traceOn = false};
  if (lightCB.checked()){light = true}else{light = false};
  
  if (solCB.checked()){sol.show = true}else{sol.show = false};
  if (moonCB.checked()){moon.show = true}else{moon.show = false};
  if (marsCB.checked()){mars.show = true}else{mars.show = false};
  if (venusCB.checked()){venus.show = true}else{venus.show = false};
  if (mercuryCB.checked()){mercury.show = true}else{mercury.show = false};
  if (drawDiscCB.checked()){disc.show = true}else{disc.show = false};
  if (drawDefCB.checked()){drawDeferent = true}else{drawDeferent = false};
  if (starsCB.checked()){stars.show = true}else{stars.show = false};
  if (orbitsCB.checked()){drawOrbits = true}else{drawOrbits = false};
  if (monthCB.checked()){monthRing.show = true}else{monthRing.show = false};
  if (zodiacCB.checked()){zodiacRing.show = true}else{zodiacRing.show = false};
  if (progTraceCB.checked()){
    progTrace = true;
        //traceCB.attribute('checked', '');
    //startButton.removeAttribute('disabled');

    traceOn = true;
    /*//traceCB.value("on");
    traceCB.elt.click();
    traceCB.checked = true;*/
    changeFrame();
  } else {
    progTrace = false; changeFrame();
  };


  drawFrame = true;
  /*   solCB = createCheckbox('Sol', true);
  marsCB = createCheckbox('Mars', true);
  venusCB = createCheckbox('Venus', true);
  mercuryCB = createCheckbox('Mercury', true);
  */
};
function drawStars() {
  stroke(stars.color);
  fill(stars.color);
  textSize(10);
  drawStar(stars.polarisx, stars.polarisy, stars.polarisSize);
  text('Polaris', stars.polarisx-15, stars.polarisy-10);
  drawStar(stars.vegax, stars.vegay, stars.vegaSize);
  text('Vega', stars.vegax+10, stars.vegay+5);
  drawStar(stars.thubanx, stars.thubany, stars.thubanSize);
  text('Thuban', stars.thubanx-45, stars.thubany+5);

  for (let i = 0; i < moreStars.length; i++) { 
    if (moreStars[i].show) {
      drawStar(moreStars[i].x, moreStars[i].y, moreStars[i].size);
      text(moreStars[i].name, moreStars[i].x + moreStars[i].namex,
           moreStars[i].y + moreStars[i].namey);   
    };
  };
};
function drawStar(x, y, s) {
  line(x - s, y, x + s, y);
  line(x, y - s, x, y + s);
  line(x - s/2, y - s/2, x + s/2, y + s/2);
  line(x + s/2, y - s/2, x - s/2, y + s/2);
};
function setSpeed() {
  if (speedSlider.value()/100 != speedFact) {
    //speedSlider has changed (uses negative values)
    //then we flush the trace and set new speed and trace length
    speedFact = speedSlider.value()/100;
    maxFrames = Math.trunc(initMaxFrames/speedFact);
    changeFrame();
  }
};

function fCalcFrame(inFrame) {

  if (inFrame === 0) {
    earth.inc = earth.startPos;
    sol.inc = sol.startPos;
    moon.inc = moon.startPos;
    mercuryDef.inc = mercuryDef.startPos;
    mercury.inc = mercury.startPos;
    venusDef.inc = venusDef.startPos;
    venus.inc = venus.startPos;
    marsDef.inc = marsDef.startPos;
    mars.inc = mars.startPos;
  } else {
    earth.inc = earth.startPos-earth.speed*yearFact/framesPerYear*inFrame;
    sol.inc = sol.startPos-sol.speed*yearFact/framesPerYear*inFrame;
    moon.inc = moon.startPos-moon.speed*yearFact/framesPerYear*inFrame;
    mercuryDef.inc = mercuryDef.startPos-mercuryDef.speed*yearFact/framesPerYear*inFrame;  
    mercury.inc = mercury.startPos-mercury.speed*yearFact/framesPerYear*inFrame;
    venusDef.inc = venusDef.startPos-venusDef.speed*yearFact/framesPerYear*inFrame;  
    venus.inc = venus.startPos-venus.speed*yearFact/framesPerYear*inFrame;
    marsDef.inc = marsDef.startPos-marsDef.speed*yearFact/framesPerYear*inFrame;
    mars.inc = mars.startPos-mars.speed*yearFact/framesPerYear*inFrame;
  }

  if (earth.positions.length > maxFrames) {
  //if (earth.positions.length > maxFrames/speedFact) {
    earth.positions.shift();
    sol.positions.shift();
    moon.positions.shift();
    mercuryDef.positions.shift();
    mercury.positions.shift();
    venusDef.positions.shift();
    venus.positions.shift();
    marsDef.positions.shift();
    mars.positions.shift();
  };

  let ex = cos(earth.inc) * earth.radius; 
  let ey = sin(earth.inc) * earth.radius;    
  earth.positions.push(createVector(ex, ey));
  //Calculate Sol
  let sx = cos(sol.inc) * sol.radius + ex + sol.offsetx; 
  let sy = sin(sol.inc) * sol.radius + ey + sol.offsety;
  sol.positions.push(createVector(sx, sy));
  //Calculate Moon
  let moonx = cos(moon.inc) * moon.radius + ex + moon.offsetx; 
  let moony = sin(moon.inc) * moon.radius + ey + moon.offsety;
  moon.positions.push(createVector(moonx, moony));

  //Calculate MercuryDef
  let mercdx = (cos(mercuryDef.inc) * mercuryDef.radius) + mercuryDef.orbitx + ex; 
  let mercdy = (sin(mercuryDef.inc) * mercuryDef.radius) + mercuryDef.orbity + ey;
  mercuryDef.positions.push(createVector(mercdx, mercdy));
  //Calculate Mercury
  let mercx = mercdx + cos(mercury.inc) * mercury.radius
  let mercy = mercdy + sin(mercury.inc) * mercury.radius
  mercury.positions.push(createVector(mercx, mercy));
  //Calculate venusDef
  let venusdx = (cos(venusDef.inc) * venusDef.radius) + venusDef.orbitx + ex; 
  let venusdy = (sin(venusDef.inc) * venusDef.radius) + venusDef.orbity + ey;
  venusDef.positions.push(createVector(venusdx, venusdy));
  //Calculate Venus
  let vx = venusdx + cos(venus.inc) * venus.radius; 
  let vy = venusdy + sin(venus.inc) * venus.radius;
  venus.positions.push(createVector(vx, vy));
  //Calculate MarsDef
  let dx = (cos(marsDef.inc) * marsDef.radius) + marsDef.orbitx + ex;
  let dy = (sin(marsDef.inc) * marsDef.radius) + marsDef.orbity + ey;
  marsDef.positions.push(createVector(dx, dy));
  //Calculate Mars
  let mx = dx + cos(mars.inc) * mars.radius;
  let my = dy + sin(mars.inc) * mars.radius;
  mars.positions.push(createVector(mx, my));
};

/*// dynamically adjust the canvas to the window
function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  drawFrame = true;
};*/

function setupGUI() {

 //text('TYCHOS Planetarium v. 2π', 10, 25);
  p = createP('TYCHOSIUM 2-D 1.0'); 
  p.position(15, 5);
  p = createP('Year type:');
  p.position(15, 26);
  p = createP('1 year = ' + framesPerYear + ' days');
  p.position(15, 50);
  p = createP('Day 0 = 2000-06-21');
  p.position(15, 70);

    //text('1 year = ' + framesPerYear + ' frames/days', 10, 70);
    //text('Day 0 = JUNE 21, 2000',10, 90);
    //text('Current daynumber: ' + Math.trunc(frame), 10, 110);
  p = createP('Current day:');
  p.position(15, 90);
  currDay = createP();
  currDay.position(105, 90);

  p = createP('Date:');
  p.position(15, 110);
  currDate = createP();
  currDate.position(55, 110);

  sel = createSelect();
  sel.position(90, 42);
  sel.option('Tychos Optimal');
  //sel.option('Patricius');
  sel.option('Gregorian');
  sel.changed(mySelectEvent);

  
  startButton = createButton('Start');
  startButton.position(58, 160);
  startButton.mousePressed(startstop);
  if (!pause) {startButton.attribute('disabled', '')}
  
  reverseCB = createCheckbox('Reverse', reverseOn);
  reverseCB.position(startButton.x + 50, startButton.y+2);
  reverseCB.changed(planetCheckedEvent);
  

  /*
  stopButton = createButton('Stop');
  stopButton.position(startButton.x + 50, startButton.y);
  stopButton.mousePressed(startstop);
  if (pause) {stopButton.attribute('disabled', '')}
  */
  
  bButton = createButton('< Step back');
  bButton.position(startButton.x-43, startButton.y+28);
  bButton.mousePressed(stepBack);
  if (!pause) {bButton.attribute('disabled', '')}
  
  fButton = createButton('Step forward >');
  fButton.position(startButton.x + 50, startButton.y + 28);
  fButton.mousePressed(stepForward);
  if (!pause) {fButton.attribute('disabled', '')}

  
  speedSlider = createSlider(5, 400, 100, 5);
  speedSlider.position(startButton.x-43, startButton.y + 50);
  speedSlider.style('width', '190px');
  
  p = createP("Speed:");
  p.position(15, speedSlider.y+8);
  currSpeed = createP();
  currSpeed.position(70, speedSlider.y+8);
  
  /*  //Zoom
  zSlider = createSlider(0, 200, 100);
  zSlider.position(startButton.x-43, startButton.y + 350);
  zSlider.style("width", "190px");
  ///*  
  pZoom = createP("Zoom:");
  pZoom.position(15, zSlider.y+8);
  currZoom = createP();
  currZoom.position(70, zSlider.y+8);
  */
  

  frameInput = createInput();
  frameInput.position(startButton.x-43, startButton.y+140);
  frameInput.size(100);
  frameInput.value("yyyy-mm-dd")
  frameInput.elt.onfocus = dateInputFocus;
  frameSubmit = createButton('Go to date');
  frameSubmit.position(frameInput.x + frameInput.width + 5, frameInput.y);
  frameSubmit.mousePressed(goToFrame);
  frameSubmit.elt.onfocus 
  /*
  ydInput = createInput();
  ydInput.position(frameInput.x, frameInput.y - 25);
  ydInput.size(85);
  ydSubmit = createButton('Go to Year.Day');
  ydSubmit.position(ydInput.x + ydInput.width + 5, ydInput.y);
  ydSubmit.mousePressed(goToYearDay);
  */

  
  
  
  traceCB = createCheckbox('Trace', traceOn);
  traceCB.position(10, speedSlider.y + 120);
  traceCB.changed(planetCheckedEvent);
    
  progTraceCB = createCheckbox('Progressive', progTrace);  
  progTraceCB.position(90, traceCB.y);
  progTraceCB.changed(planetCheckedEvent);

  solCB = createCheckbox('Sun', sol.show);
  solCB.position(10, traceCB.y+20);
  solCB.changed(planetCheckedEvent);

  moonCB = createCheckbox('Moon', moon.show);
  moonCB.position(solCB.x + 55, solCB.y);
  moonCB.changed(planetCheckedEvent);

  marsCB = createCheckbox('Mars', mars.show);
  marsCB.position(solCB.x + 120, solCB.y);
  marsCB.changed(planetCheckedEvent);

  venusCB = createCheckbox('Venus', venus.show);
  venusCB.position(solCB.x, solCB.y + 20);
  venusCB.changed(planetCheckedEvent);

  mercuryCB = createCheckbox('Mercury', mercury.show);
  mercuryCB.position(solCB.x + 110, solCB.y + 20);
  mercuryCB.changed(planetCheckedEvent);

  orbitsCB = createCheckbox('Orbits', drawOrbits);
  orbitsCB.position(solCB.x, solCB.y + 40);
  orbitsCB.changed(planetCheckedEvent);

  starsCB = createCheckbox('Stars', stars.show);
  starsCB.position(solCB.x + 110, solCB.y + 40);
  starsCB.changed(planetCheckedEvent);

  drawDiscCB = createCheckbox('Brown disc', disc.show);  
  drawDiscCB.position(solCB.x, solCB.y + 60);
  drawDiscCB.changed(planetCheckedEvent);

  drawDefCB = createCheckbox('Deferents', drawDeferent);  
  drawDefCB.position(solCB.x + 110, solCB.y + 60);
  drawDefCB.changed(planetCheckedEvent);

  monthCB = createCheckbox('Month ring', monthRing.show);
  monthCB.position(solCB.x, solCB.y + 80);
  monthCB.changed(planetCheckedEvent);

  zodiacCB = createCheckbox('Zodiac', zodiacRing.show);
  zodiacCB.position(solCB.x + 110, solCB.y + 80);
  zodiacCB.changed(planetCheckedEvent);

  lightCB = createCheckbox('Light', light);
  lightCB.position(solCB.x, solCB.y + 100);
  lightCB.changed(planetCheckedEvent);

  /*
  selSpeed = createSelect();
  selSpeed.position(90, 360);
  selSpeed.option('1');
  selSpeed.option('1/2');
  selSpeed.option('1/4');
  selSpeed.option('1/8');
  selSpeed.option('1/16');
  selSpeed.option('1/32');
  
  selSpeed.changed(selSpeedEvent);
*/
};
/*
function dateToDays(inDate) {
  const _MS_PER_DAY = 1000 * 60 * 60 * 24;
  const a = startDate;
  const b = new Date(inDate); 

  // Discard the time and time-zone information.
  var utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
  var utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());

  return Math.floor((utc2 - utc1) / _MS_PER_DAY);
}
function addDays(date, days) {
  var result = new Date(date);
  result.setDate(result.getDate() + days);
  return result;
};

function formatDate(d) {
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

    if (month.length < 2) month = '0' + month;
    if (day.length < 2) day = '0' + day;

    return [year, month, day].join('-');
};
*/
function goToFrame() {
  //check input
  let valid = true;
  let aDate = frameInput.value().split("-");
  if (aDate.length > 3) {
    //assume we had a minus sign first
    aDate.shift();
  }
  if (!Number.isInteger(parseInt(aDate[0],10))) {
    valid = false;
    console.log('one fired ' + aDate[0]);
  }
  if (!Number.isInteger(parseInt(aDate[1],10)) || aDate[1]>12) {
    valid = false;
  }
  if (!Number.isInteger(parseInt(aDate[2],10)) || aDate[2]>31) {
    valid = false;
  }
  if (!valid) {
    frameInput.value("yyyy-mm-dd");
    return;
  }
  
  frame = dateToDays(frameInput.value()) - startDateNumber;
  changeFrame();
};


function dateToDays(sDate) {
  //Calculates the number of days passed since 0000-03-01 for a date. Positive or negative
  //Taken from https://alcor.concordia.ca/~gpkatch/gdate-algorithm.html
  let aDate = sDate.split("-");
  let y,m,d;
  if (aDate.length > 3) {
    //we had a minus sign first (A BC date)
    y = -Number(aDate[1]); m = Number(aDate[2]); d = Number(aDate[3]);

  } else {
    y = Number(aDate[0]); m = Number(aDate[1]); d = Number(aDate[2]);
  };
  
  m = (m + 9) % 12;
  y = y - Math.floor(m/10);
  return 365*y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400) + Math.floor((m*306 + 5)/10) + ( d - 1 );
};

function daysToDate(g) {
  let y = Math.floor((10000*g + 14780)/3652425);
  let ddd = g - (365*y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400));
  if (ddd < 0) {
    y = y - 1
    ddd = g - (365*y + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400));
  };
  let mi = Math.floor((100*ddd + 52)/3060);
  let mm = (mi + 2)%12 + 1
  y = y + Math.floor((mi + 2)/12);
  let dd = ddd - Math.floor((mi*306 + 5)/10) + 1
  
  mm = ("0" + mm).slice(-2);
  dd = ("0" + dd).slice(-2);
  
  return y + "-" + mm + "-" + dd;
};

function dateInputFocus() {
    if (frameInput.value() === "yyyy-mm-dd") {
      frameInput.value("");
    }
}
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console