Source: primitives/lines2.js

const THREE = require('three');
const toBufferGeometry = require('../utilities').toBufferGeometry;
const LineSegments2 = require("../three/line/LineSegments2").LineSegments2;
const LineMaterial = require("../three/line/LineMaterial").LineMaterial;
const LineSegmentsGeometry = require("../three/line/LineSegmentsGeometry").LineSegmentsGeometry;

/**
 * Provides an object which stores lines.
 * This is created when a valid json file containing lines is read into a {@link Zinc.Scene}
 * object.
 * 
 * @class
 * @author Alan Wu
 * @return {Lines}
 */
const Lines2 = function () {
  (require('./lines').Lines).call(this);
	this.isLines2 = true;
  let positions = new Array(300);

  /**
   * Create the line segements using geometry and material.
   * 
   * @param {Array} arrayIn - Geometry of lines to be rendered.
   * @param {THREE.Material} materialIn - Material to be set for the lines.
   * @param {Object} options - Provide various options
   * @param {Boolean} options.localTimeEnabled - A flag to indicate either the lines is
   * time dependent.
   * @param {Boolean} options.localMorphColour - A flag to indicate either the colour is
   * time dependent.
   */
	this.createLineSegment = (arrayIn, materialIn, options) => {
		if (arrayIn && materialIn) {
      const linesGeometry = new LineSegmentsGeometry();
      linesGeometry.setPositions(arrayIn);
      linesGeometry.colorsNeedUpdate = true;
      const line = new LineSegments2(linesGeometry, materialIn);
      line.scale.set(1, 1, 1);
      line.computeLineDistances();
      this.setMesh(line, options.localTimeEnabled, options.localMorphColour);
		}
	}

  /**
   * Set the width for the lines.
   * 
   * @param {Number} width - Width of the lines.
   */
	this.setWidth = width => {
		if (this.morph && this.morph.material) {
			this.morph.material.linewidth = width;
			this.morph.material.needsUpdate = true;
		}
	}

  /**
   * Add new vertices into the array
   */
  this.addVertices = function(coords) {
    if (coords && coords.length) {
      let mesh = this.getMorph();
      if (!mesh) {
        this.drawRange = 0;
      }
      let index = this.drawRange * 3;
      coords.forEach(coord => {
        positions[index++] = coord[0];
        positions[index++] = coord[1];
        positions[index++] = coord[2];
        this.drawRange++;
      });
      //fill the rest of the array.
      if (!mesh) {
        while (index < 300) {
          positions[index++] = coords[0][0];
          positions[index++] = coords[0][1];
          positions[index++] = coords[0][2];
        }
      }

      if (mesh) {
        mesh.geometry.setPositions(positions);
        mesh.computeLineDistances();
        this.boundingBoxUpdateRequired = true;
      }
    }
    return positions;
  }

  /**
   * Get the vertices by face index
   */
  this.getVerticesByFaceIndex = function(faceIndex) {
    let vIndex = faceIndex * 2 * 3;
    const mesh = this.getMorph();
    if (mesh && (this.drawRange * 3) > vIndex) {
      const position = mesh.geometry.getAttribute( 'instanceStart' );
      return [
        [
          position.data.array[vIndex],
          position.data.array[++vIndex],
          position.data.array[++vIndex],
        ],
        [
          position.data.array[++vIndex],
          position.data.array[++vIndex],
          position.data.array[++vIndex],
        ],
      ];
    }
    return [];
  }

  /**
   * Edit Vertice in index.
   */
  this.editVertices = function(coords, i) {
    if (coords && coords.length) {
      let mesh = this.getMorph();
      const maxIndex = i + coords.length - 1;
      if (!mesh || 0 > i || maxIndex >= this.drawRange) {
        return;
      } else {
        let index = i * 3;
        coords.forEach(coord => {
          positions[index++] = coord[0];
          positions[index++] = coord[1];
          positions[index++] = coord[2];
        });
        index = this.drawRange * 3;
        while (index < 300) {
          positions[index++] = coords[0][0];
          positions[index++] = coords[0][1];
          positions[index++] = coords[0][2];
        }
        mesh.geometry.setPositions(positions);
        mesh.computeLineDistances();
        this.boundingBoxUpdateRequired = true;
      }
    }
    return positions;
  }

  /**
   * Add new lines to existing lines if it exists, otherwise
   * create a new one and add to it.
   * @param {Array} coords  -An array of three components coordinates.

   * @param {Number} colour - A hex value of the colour for the points
   */
	this.addLines = (coords, colour)  => {
    if (coords && coords.length > 0) {
      this.addVertices(coords);
      let mesh = this.getMorph();
      if (!mesh) {
        const material = new LineMaterial( {
          color: colour,
          linewidth:1,
          vertexColors: false,
          worldUnits: false,
        });
        material.resolution.set( window.innerWidth, window.innerHeight );
        const options = { localTimeEnabled: false, localMorphColour: false};
        this.createLineSegment(positions, material, options);
      }
      if (this.region) this.region.pickableUpdateRequired = true;
    }
	}

  this.render = (delta, playAnimation, cameraControls, options) => {
    const material = this.getMorph().material;
    material.resolution.set( window.innerWidth, window.innerHeight );
  }
}

Lines2.prototype = Object.create((require('./lines').Lines).prototype);
Lines2.prototype.constructor = Lines2;
exports.Lines2 = Lines2;