- Qt 5.5
- Qt Canvas 3D
- Planets Example
- planets.js Example File
- Qt 5.5.1 Reference Documentation

# planets.js Example File

canvas3d/threejs/planets/planets.js

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the QtCanvas3D module of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL3$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 3 as published by the Free Software
    ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
    ** packaging of this file. Please review the following information to
    ** ensure the GNU Lesser General Public License version 3 requirements
    ** will be met: https://www.gnu.org/licenses/lgpl.html.
    **
    ** GNU General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU
    ** General Public License version 2.0 or later as published by the Free
    ** Software Foundation and appearing in the file LICENSE.GPL included in
    ** the packaging of this file. Please review the following information to
    ** ensure the GNU General Public License version 2.0 requirements will be
    ** met: http://www.gnu.org/licenses/gpl-2.0.html.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    Qt.include("three.js")
    Qt.include("threex.planets.js")

    var SUN = 0;
    var MERCURY = 1;
    var VENUS = 2;
    var EARTH = 3;
    var MARS = 4;
    var JUPITER = 5;
    var SATURN = 6;
    var URANUS = 7;
    var NEPTUNE = 8;
    var NUM_SELECTABLE_PLANETS = 9;
    var MOON = 9;
    var SOLAR_SYSTEM = 100;

    var camera, scene, renderer;
    var planetCanvas, mouse, raycaster;

    var daysPerFrame;
    var daysPerFrameScale;
    var planetScale;
    var cameraDistance;

    var objects = []; // Planet objects
    var planets = []; // Planet data info

    var commonGeometry;
    var solarDistance = 2600000;
    var saturnOuterRadius = 120.700;
    var uranusOuterRadius = 40;

    var qmlView;

    var oldFocusedPlanetPosition;
    var oldCameraPosition;
    var defaultCameraPosition;

    var y = 2000;
    var m = 1;
    var D = 1;
    // Time scale formula based on http://www.stjarnhimlen.se/comp/ppcomp.html
    var startD = 367 * y - 7 * (y + (m + 9) / 12) / 4 + 275 * m / 9 + D - 730530;
    var oldTimeD = startD;
    var currTimeD = startD;

    var auScale = 149597.870700; // AU in thousands of kilometers

    var focusedScaling = false;
    var focusedMinimumScale = 20;
    var actualScale;

    function initializeGL(canvas, eventSource, mainView) {

        planetCanvas = canvas;
        qmlView = mainView;

        camera = new THREE.PerspectiveCamera(45, canvas.width / canvas.height, 2500000, 20000000);
        defaultCameraPosition = new THREE.Vector3(solarDistance, solarDistance, solarDistance);
        camera.position.set(defaultCameraPosition.x, defaultCameraPosition.y, defaultCameraPosition.z);

        scene = new THREE.Scene();

        var starSphere = THREEx.Planets.createStarfield(8500000);
        scene.add(starSphere);

        var light = new THREE.PointLight(0x777777, 2);
        light.position.set(0, 0, 0);
        scene.add(light);

        scene.add(new THREE.AmbientLight(0x111111));

        loadPlanetData();
        createPlanets();
        setScale(1200);

        camera.lookAt(objects[0].position); // look at the Sun

        raycaster = new THREE.Raycaster();
        mouse = new THREE.Vector2();

        renderer = new THREE.Canvas3DRenderer(
                    { canvas: canvas, antialias: true, devicePixelRatio: canvas.devicePixelRatio });

        renderer.setPixelRatio(canvas.devicePixelRatio);
        renderer.setSize(canvas.width, canvas.height);
        eventSource.mouseDown.connect(onDocumentMouseDown);
    }

    function loadPlanetData() {

        // Planet Data
        // radius - planet radius
        // tilt - planet axis angle
        // N1/2 - longitude of the ascending node
        // i1/2 - inclination to the ecliptic (plane of the Earth's orbit)
        // w1/2 - argument of perihelion
        // a1/2 - semi-major axis, or mean distance from Sun
        // e1/2 - eccentricity (0=circle, 0-1=ellipse, 1=parabola)
        // M1/2 - mean anomaly (0 at perihelion; increases uniformly with time)
        // period - sidereal rotation period
        // centerOfOrbit - the planet in the center of the orbit
        // (orbital elements based on http://www.stjarnhimlen.se/comp/ppcomp.html)

        var sun = { radius: 694.439, tilt: 63.87, period: 25.05 };
        planets.push(sun);
        var mercury = {
            radius: 2.433722, tilt: 0.04, N1: 48.3313, N2: 0.0000324587,
            i1: 7.0047, i2: 0.0000000500, w1: 29.1241, w2: 0.0000101444,
            a1: 0.387098, a2: 0, e1: 0.205635, e2: 0.000000000559,
            M1: 168.6562, M2: 4.0923344368, period: 58.646,
            centerOfOrbit: SUN
        };
        planets.push(mercury);
        var venus = {
            radius: 6.046079, tilt: 177.36, N1: 76.6799, N2: 0.0000246590,
            i1: 3.3946, i2: 0.0000000275, w1: 54.8910, w2: 0.0000138374,
            a1: 0.723330, a2: 0, e1: 0.006773, e2: -0.000000001302,
            M1: 48.0052, M2: 1.6021302244, period: 243.0185,
            centerOfOrbit: SUN
        };
        planets.push(venus);
        var earth = {
            radius: 6.371, tilt: 25.44, N1: 174.873, N2: 0,
            i1: 0.00005, i2: 0, w1: 102.94719, w2: 0,
            a1: 1, a2: 0, e1: 0.01671022, e2: 0,
            M1: 357.529, M2: 0.985608, period: 0.997,
            centerOfOrbit: SUN
        };
        planets.push(earth);
        var mars = {
            radius: 3.389372, tilt: 25.19, N1: 49.5574, N2: 0.0000211081,
            i1: 1.8497, i2: -0.0000000178, w1: 286.5016, w2: 0.0000292961,
            a1: 1.523688, a2: 0, e1: 0.093405, e2: 0.000000002516,
            M1: 18.6021, M2: 0.5240207766, period: 1.025957,
            centerOfOrbit: SUN
        };
        planets.push(mars);
        var jupiter = {
            radius: 71.41254, tilt: 3.13, N1: 100.4542, N2: 0.0000276854,
            i1: 1.3030, i2: -0.0000001557, w1: 273.8777, w2: 0.0000164505,
            a1: 5.20256, a2: 0, e1: 0.048498, e2: 0.000000004469,
            M1: 19.8950, M2: 0.0830853001, period: 0.4135,
            centerOfOrbit: SUN
        };
        planets.push(jupiter);
        var saturn = {
            radius: 60.19958, tilt: 26.73, N1: 113.6634, N2: 0.0000238980,
            i1: 2.4886, i2: -0.0000001081, w1: 339.3939, w2: 0.0000297661,
            a1: 9.55475, a2: 0, e1: 0.055546, e2: -0.000000009499,
            M1: 316.9670, M2: 0.0334442282, period: 0.4395,
            centerOfOrbit: SUN
        };
        planets.push(saturn);
        var uranus = {
            radius: 25.5286, tilt: 97.77, N1: 74.0005, N2: 0.000013978,
            i1: 0.7733, i2: 0.000000019, w1: 96.6612, w2: 0.000030565,
            a1: 19.18171, a2: -0.0000000155, e1: 0.047318, e2: 0.00000000745,
            M1: 142.5905, M2: 0.011725806, period: 0.71833,
            centerOfOrbit: SUN
        };
        planets.push(uranus);
        var neptune = {
            radius: 24.73859, tilt: 28.32, N1: 131.7806, N2: 0.000030173,
            i1: 1.7700, i2: -0.000000255, w1: 272.8461, w2: 0.000006027,
            a1: 30.05826, a2: 0.00000003313, e1: 0.008606, e2: 0.00000000215,
            M1: 260.2471, M2: 0.005995147, period: 0.6713,
            centerOfOrbit: SUN
        };
        planets.push(neptune);
        var moon = {
            radius: 1.5424, tilt: 28.32, N1: 125.1228, N2: -0.0529538083,
            i1: 5.1454, i2: 0, w1: 318.0634, w2: 0.1643573223,
            a1: 0.273, a2: 0, e1: 0.054900, e2: 0,
            M1: 115.3654, M2: 13.0649929509, period: 27.321582,
            centerOfOrbit: EARTH
        };
        planets.push(moon);

    }

    function createPlanets() {

        objects = [];

        commonGeometry = new THREE.BufferGeometry().fromGeometry(new THREE.SphereGeometry(1, 64, 64));

        var ringSegments = 70;
        var mesh, innerRadius, outerRadius, ring;

        for (var i = 0; i < planets.length; i ++) {
            switch (i) {
            case SUN:
                mesh = createSun(planets[i]["radius"]);
                mesh.position.set(0, 0, 0);
                break;
            case MERCURY:
                mesh = createPlanet(planets[i]["radius"], 0.005, 'images/mercurymap.jpg',
                                    'images/mercurybump.jpg');
                break;
            case VENUS:
                mesh = createPlanet(planets[i]["radius"], 0.005, 'images/venusmap.jpg',
                                    'images/venusbump.jpg');
                break;
            case EARTH:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/earthmap1k.jpg',
                                    'images/earthbump1k.jpg', 'images/earthspec1k.jpg');
                var cloud = createEarthCloud();
                mesh.add(cloud);
                break;
            case MARS:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/marsmap1k.jpg',
                                    'images/marsbump1k.jpg');
                break;
            case JUPITER:
                mesh = createPlanet(planets[i]["radius"], 0.02, 'images/jupitermap.jpg',
                                    'images/jupitermap.jpg');
                break;
            case SATURN:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/saturnmap.jpg',
                                    'images/saturnmap.jpg');
                innerRadius = (planets[i]["radius"] + 6.630) / planets[i]["radius"];
                outerRadius = (planets[i]["radius"] + saturnOuterRadius) / planets[i]["radius"];
                ring = createRing(innerRadius, outerRadius, ringSegments,
                                      'qrc:images/saturnringcolortrans.png');
                ring.receiveShadow = true;
                ring.castShadow = true;
                mesh.add(ring);
                break;
            case URANUS:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/uranusmap.jpg',
                                    'images/uranusmap.jpg');
                innerRadius = (planets[i]["radius"] + 2) / planets[i]["radius"];
                outerRadius = (planets[i]["radius"] + uranusOuterRadius) / planets[i]["radius"];
                ring = createRing(innerRadius, outerRadius, ringSegments,
                                      'qrc:images/uranusringcolortrans.png');
                ring.receiveShadow = true;
                ring.castShadow = true;
                mesh.add(ring);
                break;
            case NEPTUNE:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/neptunemap.jpg',
                                    'images/neptunemap.jpg');
                break;
            case MOON:
                mesh = createPlanet(planets[i]["radius"], 0.05, 'images/moonmap1k.jpg',
                                    'images/moonbump1k.jpg');
                break;
            }

            objects.push(mesh);
            scene.add(mesh);
        }

    }

    function createSun(radius) {

        var texture = THREE.ImageUtils.loadTexture('images/sunmap.jpg');
        var material = new THREE.MeshBasicMaterial({
                                                       map: texture,
                                                       bumpMap: texture,
                                                       bumpScale: 0.05
                                                   });
        var mesh = new THREE.Mesh(commonGeometry, material);
        mesh.scale.set(radius, radius, radius);

        mesh.receiveShadow = false;
        mesh.castShadow = false;

        return mesh;
    }

    function createPlanet(radius, scale, mapTexture, bumpTexture, specularTexture) {

        var material = new THREE.MeshPhongMaterial({
                                                       map: THREE.ImageUtils.loadTexture(mapTexture),
                                                       bumpMap: THREE.ImageUtils.loadTexture(bumpTexture),
                                                       bumpScale: scale
                                                   });

        if (specularTexture) {
            material.specularMap = THREE.ImageUtils.loadTexture(specularTexture);
            material.specular = new THREE.Color('grey');
            material.shininess = 50.0;
        } else {
            material.shininess = 1.0;
        }

        var mesh = new THREE.Mesh(commonGeometry, material);
        mesh.scale.set(radius, radius, radius);

        return mesh;

    }

    function createEarthCloud() {

        var material = new THREE.MeshPhongMaterial({
                                                       map: THREE.ImageUtils.loadTexture('qrc:images/earthcloudmapcolortrans.png'),
                                                       side: THREE.DoubleSide,
                                                       transparent: true,
                                                       opacity: 0.8
                                                   });
        var mesh = new THREE.Mesh(commonGeometry, material);

        return mesh;

    }

    function createRing(radius, width, height, texture) {

        var geometry = new THREE.BufferGeometry().fromGeometry(
                    new THREEx.Planets._RingGeometry(radius, width, height));

        var material = new THREE.MeshPhongMaterial({
                                                       map: THREE.ImageUtils.loadTexture(texture),
                                                       side: THREE.DoubleSide,
                                                       transparent: true,
                                                       opacity: 0.8
                                                   });
        material.map.minFilter = THREE.NearestFilter;
        var mesh = new THREE.Mesh(geometry, material);
        mesh.lookAt(new THREE.Vector3(0, 90, 0));

        return mesh;

    }

    function createStarfield(radius) {

        var texture = THREE.ImageUtils.loadTexture('images/galaxy_starfield.png')
        var material = new THREE.MeshBasicMaterial({
                                                       map: texture,
                                                       side: THREE.BackSide
                                                   })
        var geometry = new THREE.BufferGeometry().fromGeometry(new THREE.SphereGeometry(radius, 32, 32));
        var mesh = new THREE.Mesh(geometry, material)

        return mesh

    }

    function onResizeGL(canvas) {

        if (camera === undefined) return;

        camera.aspect = canvas.width / canvas.height;
        camera.updateProjectionMatrix();
        renderer.setPixelRatio(canvas.devicePixelRatio);
        renderer.setSize(canvas.width, canvas.height);

    }

    function onSpeedChanged(value) {

        daysPerFrameScale = value;

    }

    function setScale(value, focused) {

        // Save actual scale in focus mode
        if (!focused)
            actualScale = value;

        // Limit minimum scaling in focus mode to avoid jitter caused by rounding errors
        if (value <= focusedMinimumScale && (focusedScaling || focused)) {
            planetScale = focusedMinimumScale;
        } else {
            planetScale = actualScale;
        }

        for (var i = 0; i < objects.length; i++) {
            var object = objects[i];
            // first reset scale
            object.scale.set(planets[i]["radius"], planets[i]["radius"], planets[i]["radius"]);
            if (i === SUN) {
                object.scale.multiplyScalar(planetScale / 100);
            } else {
                object.scale.multiplyScalar(planetScale);
            }
        }

    }

    function setOldPlanet() {

        oldCameraPosition = camera.position.clone();

        var planet = 0;
        if (qmlView.oldPlanet !== SOLAR_SYSTEM)
            planet = qmlView.oldPlanet;
        oldFocusedPlanetPosition = objects[planet].position.clone();
        qmlView.oldPlanet = qmlView.focusedPlanet;

        if (qmlView.focusedPlanet !== SOLAR_SYSTEM && actualScale <= focusedMinimumScale) {
            // Limit minimum scaling in focus mode to avoid jitter caused by rounding errors
            planetScale = focusedMinimumScale;
            setScale(focusedMinimumScale, true);
            focusedScaling = true;
        } else if (focusedScaling === true) {
            // Restore normal scaling
            focusedScaling = false;
            setScale(actualScale);
        }

    }

    function setCameraDistance(distance) {

        cameraDistance = distance;

    }

    function setLookAtOffset() {

        var offset = oldFocusedPlanetPosition.clone();

        var planet = 0;
        if (qmlView.focusedPlanet !== SOLAR_SYSTEM)
            planet = qmlView.oldPlanet;

        var focusedPlanetPosition = objects[planet].position.clone();
        offset.sub(focusedPlanetPosition);

        qmlView.xLookAtOffset = offset.x;
        qmlView.yLookAtOffset = offset.y;
        qmlView.zLookAtOffset = offset.z;

    }

    function setCameraOffset() {

        var offset = oldCameraPosition.clone();

        var planet = 0;
        if (qmlView.focusedPlanet !== SOLAR_SYSTEM)
            planet = qmlView.focusedPlanet;

        var newCameraPosition = getNewCameraPosition(getOuterRadius(planet));

        if (qmlView.focusedPlanet !== SUN)
            offset.sub(newCameraPosition);

        if (qmlView.focusedPlanet === SUN && qmlView.oldPlanet === SOLAR_SYSTEM) {
            qmlView.xCameraOffset = Math.abs(offset.x);
            qmlView.yCameraOffset = Math.abs(offset.y);
            qmlView.zCameraOffset = Math.abs(offset.z);
        } else { // from a planet to another
            qmlView.xCameraOffset = offset.x;
            qmlView.yCameraOffset = offset.y;
            qmlView.zCameraOffset = offset.z;
        }

    }

    function getNewCameraPosition( radius ) {

        var position;
        if (qmlView.focusedPlanet === SOLAR_SYSTEM) {
            position = defaultCameraPosition.clone();
            position.multiplyScalar(cameraDistance);
        } else if (qmlView.focusedPlanet === SUN) {
            position = new THREE.Vector3(radius * planetScale * 2,
                                         radius * planetScale * 2,
                                         radius * planetScale * 2);
            position.multiplyScalar(cameraDistance);

        } else {
            var vec1 = objects[qmlView.focusedPlanet].position.clone();
            var vec2 = new THREE.Vector3(0, 1, 0);
            vec1.normalize();
            vec2.cross(vec1);
            vec2.multiplyScalar(radius * planetScale * cameraDistance * 4);
            vec2.add(objects[qmlView.focusedPlanet].position);
            vec1.set(0, radius * planetScale, 0);
            vec2.add(vec1);
            position = vec2;
        }
        return position;
    }

    function onDocumentMouseDown(x, y) {

        // Mouse selection for planets and Solar system, not for the Moon

        mouse.set((x / planetCanvas.width) * 2 - 1, - (y / planetCanvas.height ) * 2 + 1);

        raycaster.setFromCamera(mouse, camera);

        var intersects = raycaster.intersectObjects(objects);
        var selectedPlanet;

        if (intersects.length > 0) {
            var intersect = intersects[0];

            var i = 0;
            while (i < objects.length - 1) {
                if (intersect.object === objects[i]) {
                    selectedPlanet = i;
                    break;
                }
                i++;
            }
            if (selectedPlanet < NUM_SELECTABLE_PLANETS) {
                qmlView.focusedPlanet = selectedPlanet;
                // Limit minimum scaling in focus mode to avoid jitter caused by rounding errors
                if (actualScale <= focusedMinimumScale) {
                    planetScale = focusedMinimumScale;
                    setScale(focusedMinimumScale, true);
                }
                focusedScaling = true;
            }
        } else {
            qmlView.focusedPlanet = SOLAR_SYSTEM;
            // Restore normal scaling
            if (focusedScaling === true) {
                focusedScaling = false;
                setScale(actualScale);
            }
        }

    }

    function paintGL(canvas) {

        if (qmlView.focusedPlanet === SOLAR_SYSTEM)
            daysPerFrame = daysPerFrameScale * 10;
        else
            daysPerFrame = daysPerFrameScale * planets[qmlView.focusedPlanet]["period"] / 100;

        // Advance the time in days
        oldTimeD = currTimeD;
        currTimeD = currTimeD + daysPerFrame;
        var deltaTimeD = currTimeD - oldTimeD;

        // Position the planets orbiting the sun
        for (var i = 1; i < objects.length; i ++) {
            var object = objects[i];
            var planet = planets[i];

            // Bumpmaps of mercury, venus, jupiter and moon need special handling
            if (i == MERCURY || i == VENUS || i == JUPITER || i == MOON)
                object.material.bumpScale = 0.03 * planetScale;
            else
                object.material.bumpScale = 0.3 * planetScale;

            // Calculate the planet orbital elements from the current time in days
            var N =  (planet["N1"] + planet["N2"] * currTimeD) * Math.PI / 180;
            var iPlanet = (planet["i1"] + planet["i2"] * currTimeD) * Math.PI / 180;
            var w =  (planet["w1"] + planet["w2"] * currTimeD) * Math.PI / 180;
            var a = planet["a1"] + planet["a2"] * currTimeD;
            var e = planet["e1"] + planet["e2"] * currTimeD;
            var M = (planet["M1"] + planet["M2"] * currTimeD) * Math.PI / 180;
            var E = M + e * Math.sin(M) * (1.0 + e * Math.cos(M));

            var xv = a * (Math.cos(E) - e);
            var yv = a * (Math.sqrt(1.0 - e * e) * Math.sin(E));
            var v = Math.atan2(yv, xv);

            // Calculate the distance (radius)
            var r = Math.sqrt(xv * xv + yv * yv);

            // From http://www.davidcolarusso.com/astro/
            // Modified to compensate for the right handed coordinate system of OpenGL
            var xh = r * (Math.cos(N) * Math.cos(v + w)
                          - Math.sin(N) * Math.sin(v + w) * Math.cos(iPlanet));
            var zh = -r * (Math.sin(N) * Math.cos(v + w)
                           + Math.cos(N) * Math.sin(v + w) * Math.cos(iPlanet));
            var yh = r * (Math.sin(w + v) * Math.sin(iPlanet));

            // Apply the position offset from the center of orbit to the bodies
            var centerOfOrbit = objects[planet["centerOfOrbit"]];
            object.position.set(centerOfOrbit.position.x + xh * auScale,
                                centerOfOrbit.position.y + yh * auScale,
                                centerOfOrbit.position.z + zh * auScale);

            // Calculate and apply the appropriate axis tilt to the bodies
            // and rotate them around the axis
            var radians = planet["tilt"] * Math.PI / 180; // tilt in radians
            object.rotation.order = 'ZXY';
            object.rotation.x = 0;
            object.rotation.y += (deltaTimeD / planet["period"]) * 2 * Math.PI;
            object.rotation.z = radians;
            object.updateMatrix();

        }

        // rotate the Sun
        var sun = objects[SUN];
        sun.rotation.order = 'ZXY';
        sun.rotation.x = 0;
        sun.rotation.y += (deltaTimeD / planets[SUN]["period"]) * 2 * Math.PI;
        sun.rotation.z = planets[SUN]["tilt"] * Math.PI / 180; // tilt in radians
        sun.updateMatrix();

        // calculate the outer radius of the focused item
        var outerRadius = getOuterRadius(qmlView.focusedPlanet);

        // get the appropriate near plane position for the camera and animate it with QML animations
        qmlView.cameraNear = outerRadius;

        camera.near = qmlView.cameraNear;
        camera.updateProjectionMatrix();

        // Calculate and set camera position
        var cameraPosition = getNewCameraPosition(outerRadius);
        var cameraOffset = new THREE.Vector3(qmlView.xCameraOffset,
                                             qmlView.yCameraOffset,
                                             qmlView.zCameraOffset);
        cameraPosition.add(cameraOffset);
        camera.position.set(cameraPosition.x, cameraPosition.y, cameraPosition.z);

        // Calculate and set camera look-at point
        var lookAtPlanet = SUN;
        if (qmlView.focusedPlanet !== SOLAR_SYSTEM)
            lookAtPlanet = qmlView.focusedPlanet;
        var cameraLookAt = objects[lookAtPlanet].position.clone();
        var lookAtOffset = new THREE.Vector3(qmlView.xLookAtOffset,
                                             qmlView.yLookAtOffset,
                                             qmlView.zLookAtOffset);
        cameraLookAt.add(lookAtOffset);
        camera.lookAt(cameraLookAt);

        // Render the scene
        renderer.render(scene, camera);

    }

    function getOuterRadius( planet ) {

        var outerRadius = solarDistance;
        if (planet !== SOLAR_SYSTEM) {
            outerRadius = planets[planet]["radius"];
            if (planet === SATURN) {
                outerRadius =+ saturnOuterRadius;
            } else if (planet === URANUS) {
                outerRadius =+ uranusOuterRadius;
            } else if (planet === SUN) {
                outerRadius = planets[planet]["radius"] / 100;
            }
        }

        return outerRadius;
    }