      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