Source: MajorMinorRule.js

import {mergeOptions} from "Util";
import BaseShader from "shader/BaseShader";
import Geometry from "Geometry";
import cfg from "Config"

"use strict";

export default MajorMinorRule;

/**
 * @constructor
 * @description A flexible geometry object which can draw grids or rulers
 * @extends Geometry
 */
function MajorMinorRule(userOptions) {
  /**
    * @typedef MajorMinorRule.Options
    * @description
    * These are the options specific to this class. Other options provided by {@link Geometry.Options} can also be
    * passed to create a PlotBody.
    *
    * @property {Integer[]} majorDivs     A two element array of integers describing the number of major divisions in
    *                                     the PlotBody grid [horizontal, vertical].
    * @property {Integer[]} minorDivs     A two element array of integers describing the number of minor divisions
    *                                     between major divisions in the PlotBody grid [horizontal, vertical].
    * @property {Float[]} majorFraction   A two element array of floats describing the fraction of the geometry which
    *                                     major grid lines should span. [horizontal, vertical]
    * @property {Float[]} minorFraction   A two element array of floats describing the fraction of the geometry which
    *                                     major grid lines should span.
    * @property {Float[]} majorGridColor  A four element array ([r,g,b,a]) of floating point values, 0 to 1 describing
    *                                     the color of major grid lines
    * @property {Float[]} minorGridColor  A four element array ([r,g,b,a]) of floating point values, 0 to 1 describing
    *                                     the color of minor grid lines
    */
  let options = mergeOptions({
    majorDivs: [4, 4],
    minorDivs: [4, 4],
    majorFraction: [1.0, 1.0],    /* Fraction of the drawable to render major lines */
    minorFraction: [1.0, 1.0],    /* Fraction of the drawable to render minor lines */
    majorGridColor: cfg.MAJOR_GRID_COLOR,
    minorGridColor: cfg.MINOR_GRID_COLOR,
  }, userOptions);

  Geometry.call(this, options);

  this.opts = options;
  this.shader = new BaseShader();
  this.numMajorLines = 0;
  this.numSubLines = 0;
  this._createGrid();
}

MajorMinorRule.prototype = Object.assign( Object.create(Geometry.prototype), {

  initGl : function(gl) {
    Geometry.prototype.initGl.call(this, gl);
    this.shader.initGl(gl);
  },

  draw : function(gl) {
    Geometry.prototype.draw.call(this, gl);
    this.setShaderPosition(gl, this.shader);
    this.shader.color(gl, this.opts.majorGridColor);
    gl.lineWidth(cfg.MAJOR_GRID_LINE_WIDTH);
    gl.drawArrays(gl.LINES, 0, this.numMajorLines);
    gl.lineWidth(cfg.MINOR_GRID_LINE_WIDTH);
    if (this.numSubLines) {
      this.shader.color(gl, this.opts.minorGridColor);
      gl.drawArrays(gl.LINES, this.numMajorLines, this.numSubLines);
    }
  },

  _createGrid : function() {

    this.numMajorLines = 0;
    this.numSubLines = 0;

    let subDivVerts = [];

    for (let axisI = 0; axisI < this.opts.majorDivs.length; axisI++) {
      let axisCount = this.opts.majorDivs[axisI];
      let width = axisCount ? 1 / axisCount : 0;

      for (let lineI = 0; lineI < axisCount + 1;  lineI++) {
        let pos = width * lineI;
        let verts = new Array(6).fill(0);

        /* Set X coords for columns, Ys for rows */
        verts[axisI] = pos;
        verts[axisI + cfg.COORDS_PER_VERT] = pos;

        /* Set opposite vert in Y for columns, X for rows */
        verts[Math.abs(axisI-1)] = this.opts.majorFraction[axisI];
        this.addVertices(verts);
        this.numMajorLines += 2;

        /* Generate sub division vertices but don't add them to the main buffer yet */
        for (let subI = 0; subI < this.opts.minorDivs[axisI]; subI ++) {
          let subWidth = width / this.opts.minorDivs[axisI];
          let subPos = pos + subWidth * subI;
          let verts = new Array(6).fill(0);
          verts[axisI] = subPos;
          verts[axisI + cfg.COORDS_PER_VERT] = subPos;
          verts[Math.abs(axisI-1)] = this.opts.minorFraction[axisI];
          Array.prototype.push.apply(subDivVerts, verts);
          this.numSubLines += 2;
        }
      }
    }

    this.addVertices(subDivVerts);
  },

});