lib/sphere/positions.js
function populate() {

  var d     = this._divisions,
      max_x = 2 * d - 1,
      buf   = new Float64Array((d - 1) * 2);

  this._positions = new Float64Array(( 5 * 2 * d * d + 2 ) * 2);

  // Determine position for polar and tropical fields using only arithmetic.

  this._Fields[0]._setPosition(π / 2, 0);
  this._Fields[1]._setPosition(π / -2, 0);

  for (let s = 0; s < PEELS; s += 1) {

    let λNorth = s * 2 / 5 * π,
        λSouth = s * 2 / 5 * π + π / 5;

    this.get(s, d - 1, 0)._setPosition(π / 2 - L, λNorth);
    this.get(s, max_x, 0)._setPosition(π / -2 + L, λSouth);

  }

  // Determine positions for the fields along the edges using arc interpolation.

  if ((d - 1) > 0) { // d must be at least 2 for there to be fields between vertices.

    for (let s = 0; s < PEELS; s += 1) {

      let p = (s + 4) % PEELS;

      let snP = 0,
          ssP = 1,
          cnT = this.get(s, d - 1, 0)._i,
          pnT = this.get(p, d - 1, 0)._i,
          csT = this.get(s, max_x, 0)._i,
          psT = this.get(p, max_x, 0)._i;

      // north pole to current north tropical pentagon

      interpolate(
        this._positions[2 * snP + 0],
        this._positions[2 * snP + 1],
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, i - 1, 0)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to previous north tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * pnT + 0],
        this._positions[2 * pnT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1 - i, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to previous south tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * psT + 0],
        this._positions[2 * psT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to current south tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1 + i, 0)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current south tropical pentagon to previous south tropical pentagon

      interpolate(
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        this._positions[2 * psT + 0],
        this._positions[2 * psT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, max_x - i, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current south tropical pentagon to south pole

      interpolate(
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        this._positions[2 * ssP + 0],
        this._positions[2 * ssP + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, max_x, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

    }

  }

  // Determine positions for fields between edges using interpolation.

  if ((d - 2) > 0) { // d must be at least 3 for there to be fields not along edges.

    for (let s = 0; s < PEELS; s += 1) {

      for (let x = 0; x < d * 2; x += 1) {

        // for each column, fill in values for fields between edge fields,
        // whose positions were defined in the previous block.

        if ((x + 1) % d > 0) { // ignore the columns that are edges.

          let j  = d - ((x + 1) % d), // the y index of the field in this column that is along a diagonal edge
              n1 = j - 1, // the number of unpositioned fields before j
              n2 = d - 1 - j, // the number of unpositioned fields after j
              f1 = this.get(s, x, 0)._i, // the field along the early edge
              f2 = this.get(s, x, j)._i, // the field along the diagonal edge
              f3 = this.get(s, x, d - 1)._adjacentFields[2]._i; // the field along the later edge,
                                                                // which will necessarily belong to
                                                                // another section.

          interpolate(
            this._positions[2 * f1 + 0],
            this._positions[2 * f1 + 1],
            this._positions[2 * f2 + 0],
            this._positions[2 * f2 + 1],
            n1 + 1,
            buf
          );

          for (let i = 1; i < j; i += 1)
            this.get(s, x, i)
              ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

          interpolate(
            this._positions[2 * f2 + 0],
            this._positions[2 * f2 + 1],
            this._positions[2 * f3 + 0],
            this._positions[2 * f3 + 1],
            n2 + 1,
            buf
          );

          for (let i = j + 1; i < d; i += 1)
            this.get(s, x, i)
              ._setPosition(buf[2 * (i - j - 1) + 0], buf[2 * (i - j - 1) + 1]);

        }

      }

    }

  }

}
function populate() {

  var d     = this._divisions,
      max_x = 2 * d - 1,
      buf   = new Float64Array((d - 1) * 2);

  this._positions = new Float64Array(( 5 * 2 * d * d + 2 ) * 2);

  // Determine position for polar and tropical fields using only arithmetic.

  this._Fields[0]._setPosition(π / 2, 0);
  this._Fields[1]._setPosition(π / -2, 0);

  for (let s = 0; s < PEELS; s += 1) {

    let λNorth = s * 2 / 5 * π,
        λSouth = s * 2 / 5 * π + π / 5;

    this.get(s, d - 1, 0)._setPosition(π / 2 - L, λNorth);
    this.get(s, max_x, 0)._setPosition(π / -2 + L, λSouth);

  }

  // Determine positions for the fields along the edges using arc interpolation.

  if ((d - 1) > 0) { // d must be at least 2 for there to be fields between vertices.

    for (let s = 0; s < PEELS; s += 1) {

      let p = (s + 4) % PEELS;

      let snP = 0,
          ssP = 1,
          cnT = this.get(s, d - 1, 0)._i,
          pnT = this.get(p, d - 1, 0)._i,
          csT = this.get(s, max_x, 0)._i,
          psT = this.get(p, max_x, 0)._i;

      // north pole to current north tropical pentagon

      interpolate(
        this._positions[2 * snP + 0],
        this._positions[2 * snP + 1],
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, i - 1, 0)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to previous north tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * pnT + 0],
        this._positions[2 * pnT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1 - i, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to previous south tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * psT + 0],
        this._positions[2 * psT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current north tropical pentagon to current south tropical pentagon

      interpolate(
        this._positions[2 * cnT + 0],
        this._positions[2 * cnT + 1],
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, d - 1 + i, 0)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current south tropical pentagon to previous south tropical pentagon

      interpolate(
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        this._positions[2 * psT + 0],
        this._positions[2 * psT + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, max_x - i, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

      // current south tropical pentagon to south pole

      interpolate(
        this._positions[2 * csT + 0],
        this._positions[2 * csT + 1],
        this._positions[2 * ssP + 0],
        this._positions[2 * ssP + 1],
        d,
        buf
      );

      for (let i = 1; i < d; i += 1)
        this.get(s, max_x, i)
          ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

    }

  }

  // Determine positions for fields between edges using interpolation.

  if ((d - 2) > 0) { // d must be at least 3 for there to be fields not along edges.

    for (let s = 0; s < PEELS; s += 1) {

      for (let x = 0; x < d * 2; x += 1) {

        // for each column, fill in values for fields between edge fields,
        // whose positions were defined in the previous block.

        if ((x + 1) % d > 0) { // ignore the columns that are edges.

          let j  = d - ((x + 1) % d), // the y index of the field in this column that is along a diagonal edge
              n1 = j - 1, // the number of unpositioned fields before j
              n2 = d - 1 - j, // the number of unpositioned fields after j
              f1 = this.get(s, x, 0)._i, // the field along the early edge
              f2 = this.get(s, x, j)._i, // the field along the diagonal edge
              f3 = this.get(s, x, d - 1)._adjacentFields[2]._i; // the field along the later edge,
                                                                // which will necessarily belong to
                                                                // another section.

          interpolate(
            this._positions[2 * f1 + 0],
            this._positions[2 * f1 + 1],
            this._positions[2 * f2 + 0],
            this._positions[2 * f2 + 1],
            n1 + 1,
            buf
          );

          for (let i = 1; i < j; i += 1)
            this.get(s, x, i)
              ._setPosition(buf[2 * (i - 1) + 0], buf[2 * (i - 1) + 1]);

          interpolate(
            this._positions[2 * f2 + 0],
            this._positions[2 * f2 + 1],
            this._positions[2 * f3 + 0],
            this._positions[2 * f3 + 1],
            n2 + 1,
            buf
          );

          for (let i = j + 1; i < d; i += 1)
            this.get(s, x, i)
              ._setPosition(buf[2 * (i - j - 1) + 0], buf[2 * (i - j - 1) + 1]);

        }

      }

    }

  }

}
Sets the barycenter position of every field on a Sphere.
@this {Sphere}