1 // Module to avoid duplication of shape sources between controller and
  2 // editor/formatter. This allows one central dict and dropdown of available
  3 // shapes.
  4 define(['jquery', 'three', 'underscore'], function($, THREE, _) {
  5 
  6   var SPHERE = 'Sphere', SQUARE = 'Square', CONE = 'Cone',
  7       ICOSAHEDRON = 'Icosahedron', CYLINDER = 'Cylinder',
  8       OCTAHEDRON = 'Diamond', RING = 'Ring', STAR = 'Star';
  9 
 10   var shapes = [SPHERE, OCTAHEDRON, CONE, CYLINDER, RING, SQUARE, ICOSAHEDRON,
 11                 STAR];
 12 
 13   /**
 14    *
 15    * Return a correctly sized geometry that matches the plotting space
 16    *
 17    * @param {string} shapeName One of 'Sphere', 'Square', 'Cone',
 18    * 'Icosahedron', 'Cylinder', 'Diamond' and 'Ring'.
 19    * @param {Float} factor Size for the geometries. Usually as determined by
 20    * the DecompositionView object.
 21    *
 22    * @return {THREE.Geometry} The requested geometry object with a size
 23    * appropriate for the data presented on screen.
 24    * @function getGeometry
 25    */
 26   function getGeometry(shapeName, factor) {
 27 
 28     /*
 29      *
 30      * We arbitrarily rotate "flat-facing" geometries to avoid having the color
 31      * of the markers being distorted with the scene's light.
 32      *
 33      */
 34 
 35     switch (shapeName) {
 36       case SPHERE:
 37         return new THREE.SphereGeometry(factor, 8, 8);
 38       case SQUARE:
 39         geom = new THREE.PlaneGeometry(factor * 2, factor * 2, 2, 2);
 40         geom.rotateX(0.3);
 41         return geom;
 42       case CONE:
 43         return new THREE.CylinderGeometry(factor, 0, 2 * factor, 8);
 44       case ICOSAHEDRON:
 45         return new THREE.IcosahedronGeometry(factor, 0);
 46       case OCTAHEDRON:
 47         return new THREE.OctahedronGeometry(factor, 0);
 48       case RING:
 49         // 1.618033 ~= golden ratio
 50         geom = new THREE.RingGeometry(factor / 1.618033, factor);
 51         geom.rotateX(0.3);
 52         return geom;
 53       case STAR:
 54         return StarGeometry(factor * 0.5);
 55       case CYLINDER:
 56         return new THREE.CylinderGeometry(factor, factor, 2 * factor, 10);
 57       default:
 58         throw Error('Unknown geometry requested: ' + shapeName);
 59     }
 60   }
 61 
 62   var $shapesDropdown = $('<select>');
 63   _.each(shapes, function(shape) {
 64     $shapesDropdown.append(new Option(shape, shape));
 65   });
 66 
 67   /**
 68    * Create a star with 6 points.
 69    *
 70    * This code was adapted from:
 71    * https://threejs.org/examples/#webgl_geometry_extrude_shapes
 72    *
 73    * @param {Float} scale The scale to apply to the geometry.
 74    * @return {THREE.ShapeGeometry} The star geometry.
 75    *
 76    */
 77   function StarGeometry(scale) {
 78     var pts = [], numPts = 6, l, a, shape, geometry;
 79 
 80     for (var i = 0; i < numPts * 2; i++) {
 81       l = i % 2 == 1 ? 1 : 2;
 82       a = i / numPts * Math.PI;
 83 
 84       pts.push(new THREE.Vector2(Math.cos(a) * l, Math.sin(a) * l));
 85     }
 86 
 87     shape = new THREE.Shape(pts);
 88     geometry = new THREE.ShapeGeometry(shape);
 89 
 90     geometry.scale(scale, scale, scale);
 91     geometry.rotateX(0.3);
 92     return geometry;
 93   }
 94 
 95   return {$shapesDropdown: $shapesDropdown, getGeometry: getGeometry,
 96           shapes: shapes};
 97 });
 98