API Docs for: 0.0.1
Show:

File: lib/graphs/gradient.js

/*
* niViz -- snow profiles visualization
* Copyright (C) 2015 WSL/SLF - Fluelastrasse 11 - 7260 Davos Dorf - Switzerland.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

(function (niviz) {
  'use strict';

  // --- Module Dependencies ---
  var Value      = niviz.Value;
  var properties = Object.defineProperties;

  /** @module niviz */

  var Color = {
    darkblue: [0, 0, 127],
    blue: [0, 0, 255],
    cyan: [0, 255, 255],
    lightwhite: [240, 240, 240],
    red: [255, 0, 0],
    black : [0, 0, 0]
  };

  /**
   * A Gradient represents a color gradient and its labels
   *
   * @class Gradient
   * @constructor
   */
  function Gradient(config) {
    /**
     * @property min
     * @type Number
     */
    this.min = parseFloat(config.min) || 0.0;

    /**
     * @property max
     * @type Number
     */
    this.max = (config.max !== undefined ? parseFloat(config.max) : 1.0);

    /**
     * @property steps
     * @type Number
     */
    this.steps = (config.steps !== undefined ? parseInt(config.steps) : 4);
    if (this.steps <= 0) this.steps = 2;

    /**
     * @property palette
     * @type Array< Array<Number> >
     */
    this.palette = Gradient.palettes[config.palette] || Gradient.palettes.whiteblue;

    /**
     * @property gradienttype
     * @type String
     */
    this.gradienttype = config.gradient || 'linear';

    this.color = config.color === 'own' ? this.own : this.linearcolor();
  }

  Gradient.palettes = {
    bluemultired: [ Color.darkblue, Color.blue, Color.cyan,
                    Color.lightwhite, Color.red ],
    whitemultiblue: [ Color.lightwhite, Color.cyan, Color.blue, Color.darkblue ],
    whiteblue: [ Color.lightwhite, Color.blue ],
    bluered: [ Color.blue, Color.red ],
    whiteblack: [ Color.lightwhite, Color.black ]
  };

  properties(Gradient.prototype, {
    /**
     * A gradient string, that can be used to fill rectangles.
     *
     * @property gradient
     * @type String
     */
    gradient: {
      get: function () {
        if (this.gradienttype === 'grainshape')
          return this.grainshape();

        return this.lineargradient();
      }
    }
  });

  Gradient.prototype.own = function (layer) {
    return layer.color;
  };

  Gradient.prototype.linearcolor = function () {
    var steps = this.palette.length, span = this.max - this.min,
        inc = span / (steps - 1), i, ii;

    if (steps === 1) {
      return function () {
        return this.palette[0];
      };
    }

    return function (value) {
      value = value.avg || value.value;

      if (value <= this.min) {
        return rgbToHex.apply(null, this.palette[0]);
      } else if (value >= this.max) {
        return rgbToHex.apply(null, this.palette[steps - 1]);
      }

      var last = this.min, color;
      for (i = 1, ii = steps; i < ii; ++i) {
        var max = inc + last;
        if (value <= max) {
          color = getStepColor(this.palette[i - 1],
                               this.palette[i], (value - last) / inc);

          return rgbToHex.apply(null, color);
        }
        last = max;
      }
    };
  };

  Gradient.prototype.lineargradient = function () {
    var i, ii, span = this.max - this.min, inc = span / (this.steps - 1), factor = 1;

    var result = {
      gradient: [],
      positions: [],
      labels : []
    };

    for (i = 0, ii = this.palette.length; i < ii; ++i) {
      var rate = Math.round(i / (ii - 1) * 100);
      if (i) result.gradient.push('-');
      result.gradient.push(rgbToHex.apply(null, this.palette[i]), ':', rate);
    }

    result.gradient = result.gradient.join('');

    if (this.max < 2) factor = 100;
    for (i = 0, ii = this.steps; i < ii; ++i) {
      result.positions.push(i / (ii - 1));
      result.labels.push(Math.round(i * inc * factor) / factor + this.min);
    }

    return result;
  };

  Gradient.prototype.grainshape = function () {
    var i, ii;

    var result = {
      gradient: [],
      positions: [],
      nogutter: true,
      lbls : ['PPgp', 'MM', 'IF', 'MFcr', 'MF', 'SH', 'DH', 'FC', 'RG', 'DF', 'PP'],
      labels : ['PPgp', 'MM', 'IF', 'MFcr', 'MF', 'SH', 'DH', 'FC', 'RG', 'DF', 'PP']
    };

    for (i = 0, ii = result.labels.length; i < ii; ++i) {
      var rate = Math.round((i + 1) / ii * 100),
        last = Math.round((i) / ii * 100),
        color = Value.GrainShape.type[result.labels[i]].color;

      result.positions.push((i / ii + (i + 1) / ii) / 2);
      if (i) result.gradient.push('-');
      result.gradient.push(color, ':', last, '-', color, ':', rate);
    }

    result.gradient = result.gradient.join('');

    for (i = 0, ii = result.labels.length; i < ii; ++i) {
      result.labels[i] = Value.GrainShape.type[result.labels[i]].key;
    }

    return result;
  };

  Gradient.patternMFcr = function () {
    var pat = document.createElement("canvas")
    pat.width = 5;
    pat.height = 5;

    var pctx = pat.getContext('2d');

    pctx.strokeStyle = '#000000';
    pctx.lineWidth = 1;
    pctx.beginPath();
    pctx.moveTo(1, -1);
    pctx.lineTo(1, 6);
    pctx.fillStyle = '#FF0000';

    pctx.fillRect(0, 0, 5, 5);
    pctx.stroke();

    return pat;
  }();

  // properties(Value.prototype, {
  //   /**
  //    * A string represantation of this value.
  //    *
  //    * @property text
  //    * @type String
  //    */
  //   text: {
  //     get: function () { return this.toString(); }
  //   },

  //   /**
  //    * The numeric value (defaults to `.value`) used for comparisons.
  //    *
  //    * @property numeric
  //    * @type Number
  //    */
  //   numeric: {
  //     get: function () { return Number(this.value); }
  //   }
  // });

  // Value.prototype.toString = function () {
  //   return String(this.value);
  // };

  function componentToHex(c) {
    var hex = c.toString(16);
    return hex.length === 1 ? '0' + hex : hex;
  }

  function rgbToHex(r, g, b) {
    return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);
  }

    var getStepColor = function(colorA, colorB, value) {
    return colorA.map(function(color, i) {
      return (color + value * (colorB[i] - color)) & 255;
    });
  };

  /*
  function ts (value) {
    var r, g, b;

    if (value instanceof Value) value = value.value;

    if (value <= -20) {
      return '#00007F';
    } else if (value < -15) {
      value = Math.round((value + 20) / 5 * 128);
      return '#0000' + componentToHex(value);
    } else if (value < -10) {
      value = (value + 15) / 5;
      r = 0;
      g = Math.round(255 * value);
      b = 255;

      return rgbToHex(r, g, b);
    } else if (value < -5) {
      value = (value + 10) / 5;
      r = Math.round(240 * value);
      g = Math.round(255 - 15 * value);
      b = Math.round(255 - 15 * value);

      return rgbToHex(r, g, b);
    } else if (value < 0) {
      value = (value + 5) / 5;
      r = Math.round(15 * value + 240);
      g = Math.round(240 * (1 - value));
      b = Math.round(240 * (1 - value));

      return rgbToHex(r, g, b);
    } else {
      return '#F00';
    }
  }
  */

  // --- Module Exports ---
  niviz.Gradient = Gradient;

}(niviz));