lib/sphere/from-raster.js
function fromRaster(data, width, height, depth, map, done) {

  var sphere = this;

  populateInterfieldData.call(sphere);

  var bmp = new Bitmap(width, height);

  sphere._Fields.forEach(function (field) {

    var geo       = _fieldGeometry.call(field),
        selection = _populateSelectionGrid(bmp, geo, width, height);

    var valSums   = [],
        weightSum = 0;

    for (let z = 0; z < depth; z += 1) {
      valSums[z] = 0;
    }

    for (let x = selection.min_x; x < selection.max_x; x += 1) {

      for (let y = selection.min_y; y < selection.max_y; y += 1) {

        let w = _testPoints(bmp, x, y) / 4;

        for (let z = 0; z < depth; z += 1) {
          valSums[z] += data[(height - y - 1) * width * depth + (width - x - 1) * depth + z] * w;
        }

        weightSum += w;

      }

    }

    if (weightSum <= 0) debugger; // weight sum should never be non-positive

    map.apply(field, valSums.map((val) => {
      return val / weightSum
    }));

    bmp.clear(
      selection.max_x - selection.min_x,
      selection.max_y - selection.min_y,
      selection.min_x,
      selection.min_y
    );

  });

  done();

}
function fromRaster(data, width, height, depth, map, done) {

  var sphere = this;

  populateInterfieldData.call(sphere);

  var bmp = new Bitmap(width, height);

  sphere._Fields.forEach(function (field) {

    var geo       = _fieldGeometry.call(field),
        selection = _populateSelectionGrid(bmp, geo, width, height);

    var valSums   = [],
        weightSum = 0;

    for (let z = 0; z < depth; z += 1) {
      valSums[z] = 0;
    }

    for (let x = selection.min_x; x < selection.max_x; x += 1) {

      for (let y = selection.min_y; y < selection.max_y; y += 1) {

        let w = _testPoints(bmp, x, y) / 4;

        for (let z = 0; z < depth; z += 1) {
          valSums[z] += data[(height - y - 1) * width * depth + (width - x - 1) * depth + z] * w;
        }

        weightSum += w;

      }

    }

    if (weightSum <= 0) debugger; // weight sum should never be non-positive

    map.apply(field, valSums.map((val) => {
      return val / weightSum
    }));

    bmp.clear(
      selection.max_x - selection.min_x,
      selection.max_y - selection.min_y,
      selection.min_x,
      selection.min_y
    );

  });

  done();

}
A function that sets field data based on raster data. A flat array of numbers, `data`, is
supplied representing `height` rows of `width` identical rectangles, each rectangle comprising
`depth` points of data. A plate carrée projection is assumed.

`map` is a function that receives `depth` arguments, each the weighted mean value of the data in
that channel, and called with each field's context. It can't be asynchronous.

`done` is a Node-style completion callback called when setting field data is complete.

@this {Sphere}

@param {ArrayBuffer} data
@param {number} width
@param {number} height
@param {number} depth
@param {function} map
@param {function} done