JSDoc: Source: draw.js

# Source: draw.js

    /** @module draw */
    define(['underscore', 'three'], function(_, THREE) {
      /**
       *
       * @class EmperorTrajectory
       *
       * This class represents the internal logic for a linearly interpolated
       * tube/trajectory in THREE.js
       *
       * [This answer]{@link http://stackoverflow.com/a/18580832/379593} on
       * StackOverflow helped a lot.
       * @return {EmperorTrajectory}
       * @extends THREE.Curve
       */
      THREE.EmperorTrajectory = THREE.Curve.create(
          function(points) {
            this.points = (points == undefined) ? [] : points;
          },

          function(t) {
            var points = this.points;
            var index = (points.length - 1) * t;
            var floorIndex = Math.floor(index);

            if (floorIndex == points.length - 1) {
              return points[floorIndex];
            }

            var floorPoint = points[floorIndex];
            var ceilPoint = points[floorIndex + 1];

            return floorPoint.clone().lerp(ceilPoint, index - floorIndex);
          }
          );

      /** @private */
      THREE.EmperorTrajectory.prototype.getUtoTmapping = function(u) {
        return u;
      };

      /**
       *
       * Create a generic THREE.Line object
       *
       * @param {float[]} start The x, y and z coordinates of one of the ends
       * of the line.
       * @param {float[]} end The x, y and z coordinates of one of the ends
       * of the line.
       * @param {integer} color Hexadecimal base that specifies the color of the
       * line.
       * @param {float} width The width of the line being drawn.
       * @param {boolean} transparent Whether the line will be transparent or not.
       *
       * @return {THREE.Line}
       * @function makeLine
       */
      function makeLine(start, end, color, width, transparent) {
        // based on the example described in:
        // https://github.com/mrdoob/three.js/wiki/Drawing-lines
        var material, geometry, line;

        // make the material transparent and with full opacity
        material = new THREE.LineBasicMaterial({color: color, linewidth: width});
        material.matrixAutoUpdate = true;
        material.transparent = transparent;
        material.opacity = 1.0;

        // add the two vertices to the geometry
        geometry = new THREE.Geometry();
        geometry.vertices.push(new THREE.Vector3(start[0], start[1], start[2]));
        geometry.vertices.push(new THREE.Vector3(end[0], end[1], end[2]));

        // the line will contain the two vertices and the described material
        line = new THREE.Line(geometry, material);

        return line;
      }

      /**
       *
       * Create a THREE object that displays 2D text, this implementation is based
       * on the answer found
       * [here]{@link http://stackoverflow.com/a/14106703/379593}
       *
       * @param {float[]} position The x, y, and z location of the label.
       * @param {string} text with the text to be shown on screen.
       * @param {integer} Color Hexadecimal base that represents the color of
       * the text.
       * @param {float} [1] factor An optional scaling factor to determine the size
       * of the labels.
       *
       * @return {THREE.Sprite} Object with the text displaying in it.
       * @function makeLabel
       **/
      function makeLabel(position, text, color, factor) {
        var canvas = document.createElement('canvas');
        var size = 512;

        factor = (factor === undefined ? 1 : factor);

        canvas.width = size;
        canvas.height = size;
        var context = canvas.getContext('2d');
        context.fillStyle = '#ffffff';
        context.textAlign = 'center';
        context.font = (30 * factor) + 'px Arial';
        context.fillText(text, size / 2, size / 2);

        var amap = new THREE.Texture(canvas);
        amap.needsUpdate = true;

        var mat = new THREE.SpriteMaterial({
            map: amap,
            transparent: true,
            color: color
        });

        var sp = new THREE.Sprite(mat);
        sp.position.set(position[0], position[1], position[2]);

        return sp;
      }

      /**
       *
       * Format an SVG string with labels and colors.
       *
       * @param {string[]} labels The names for the label.
       * @param {integer[]} colors The colors for each label.
       *
       * @return {string} SVG string with the labels and colors values formated as
       * a legend.
       * @function formatSVGLegend
       */
      function formatSVGLegend(labels, colors) {
        var labels_svg = '', pos_y = 1, increment = 40, max_len = 0, rect_width,
        font_size = 12;

        for (var i = 0; i < labels.length; i++) {
          // add the rectangle with the corresponding color
          labels_svg += '<rect height="27" width="27" y="' + pos_y +
            '" x="5" style="stroke-width:1;stroke:rgb(0,0,0)" fill="' +
            colors[i] + '"/>';

          // add the name of the category
          labels_svg += '<text xml:space="preserve" y="' + (pos_y + 20) +
            '" x="40" font-size="' + font_size +
            '" stroke-width="0" stroke="#000000" fill="#000000">' + labels[i] +
            '</text>';

          pos_y += increment;
        }

        // get the name with the maximum number of characters and get the length
        max_len = _.max(labels, function(a) {return a.length}).length;

          // duplicate the size of the rectangle to make sure it fits the labels
          rect_width = font_size * max_len * 2;

        labels_svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' +
          rect_width + '" height="' + (pos_y - 10) + '"><g>' + labels_svg +
          '</g></svg>';

        return labels_svg;
      }

      return {'formatSVGLegend': formatSVGLegend, 'makeLine': makeLine,
              'makeLabel': makeLabel};
    });