text: /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId]) {
  /******/ 			return installedModules[moduleId].exports;
  /******/ 		}
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			i: moduleId,
  /******/ 			l: false,
  /******/ 			exports: {}
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.l = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  /******/
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  /******/
  /******/ 	// define getter function for harmony exports
  /******/ 	__webpack_require__.d = function(exports, name, getter) {
  /******/ 		if(!__webpack_require__.o(exports, name)) {
  /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
  /******/ 		}
  /******/ 	};
  /******/
  /******/ 	// define __esModule on exports
  /******/ 	__webpack_require__.r = function(exports) {
  /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  /******/ 		}
  /******/ 		Object.defineProperty(exports, '__esModule', { value: true });
  /******/ 	};
  /******/
  /******/ 	// create a fake namespace object
  /******/ 	// mode & 1: value is a module id, require it
  /******/ 	// mode & 2: merge all properties of value into the ns
  /******/ 	// mode & 4: return value when already ns object
  /******/ 	// mode & 8|1: behave like require
  /******/ 	__webpack_require__.t = function(value, mode) {
  /******/ 		if(mode & 1) value = __webpack_require__(value);
  /******/ 		if(mode & 8) return value;
  /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  /******/ 		var ns = Object.create(null);
  /******/ 		__webpack_require__.r(ns);
  /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  /******/ 		return ns;
  /******/ 	};
  /******/
  /******/ 	// getDefaultExport function for compatibility with non-harmony modules
  /******/ 	__webpack_require__.n = function(module) {
  /******/ 		var getter = module && module.__esModule ?
  /******/ 			function getDefault() { return module['default']; } :
  /******/ 			function getModuleExports() { return module; };
  /******/ 		__webpack_require__.d(getter, 'a', getter);
  /******/ 		return getter;
  /******/ 	};
  /******/
  /******/ 	// Object.prototype.hasOwnProperty.call
  /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  /******/
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  /******/
  /******/
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(__webpack_require__.s = "./src/components/workers/worker_cluster.tsx");
  /******/ })
  /************************************************************************/
  /******/ ({
  
  /***/ "./node_modules/concaveman/index.js":
  /*!******************************************!*\
    !*** ./node_modules/concaveman/index.js ***!
    \******************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var rbush = __webpack_require__(/*! rbush */ "./node_modules/rbush/index.js");
  var convexHull = __webpack_require__(/*! monotone-convex-hull-2d */ "./node_modules/monotone-convex-hull-2d/index.js");
  var Queue = __webpack_require__(/*! tinyqueue */ "./node_modules/concaveman/node_modules/tinyqueue/index.js");
  var pointInPolygon = __webpack_require__(/*! point-in-polygon */ "./node_modules/point-in-polygon/index.js");
  var orient = __webpack_require__(/*! robust-orientation */ "./node_modules/robust-orientation/orientation.js")[3];
  
  module.exports = concaveman;
  module.exports.default = concaveman;
  
  function concaveman(points, concavity, lengthThreshold) {
      // a relative measure of concavity; higher value means simpler hull
      concavity = Math.max(0, concavity === undefined ? 2 : concavity);
  
      // when a segment goes below this length threshold, it won't be drilled down further
      lengthThreshold = lengthThreshold || 0;
  
      // start with a convex hull of the points
      var hull = fastConvexHull(points);
  
      // index the points with an R-tree
      var tree = rbush(16, ['[0]', '[1]', '[0]', '[1]']).load(points);
  
      // turn the convex hull into a linked list and populate the initial edge queue with the nodes
      var queue = [];
      for (var i = 0, last; i < hull.length; i++) {
          var p = hull[i];
          tree.remove(p);
          last = insertNode(p, last);
          queue.push(last);
      }
  
      // index the segments with an R-tree (for intersection checks)
      var segTree = rbush(16);
      for (i = 0; i < queue.length; i++) segTree.insert(updateBBox(queue[i]));
  
      var sqConcavity = concavity * concavity;
      var sqLenThreshold = lengthThreshold * lengthThreshold;
  
      // process edges one by one
      while (queue.length) {
          var node = queue.shift();
          var a = node.p;
          var b = node.next.p;
  
          // skip the edge if it's already short enough
          var sqLen = getSqDist(a, b);
          if (sqLen < sqLenThreshold) continue;
  
          var maxSqLen = sqLen / sqConcavity;
  
          // find the best connection point for the current edge to flex inward to
          p = findCandidate(tree, node.prev.p, a, b, node.next.next.p, maxSqLen, segTree);
  
          // if we found a connection and it satisfies our concavity measure
          if (p && Math.min(getSqDist(p, a), getSqDist(p, b)) <= maxSqLen) {
              // connect the edge endpoints through this point and add 2 new edges to the queue
              queue.push(node);
              queue.push(insertNode(p, node));
  
              // update point and segment indexes
              tree.remove(p);
              segTree.remove(node);
              segTree.insert(updateBBox(node));
              segTree.insert(updateBBox(node.next));
          }
      }
  
      // convert the resulting hull linked list to an array of points
      node = last;
      var concave = [];
      do {
          concave.push(node.p);
          node = node.next;
      } while (node !== last);
  
      concave.push(node.p);
  
      return concave;
  }
  
  function findCandidate(tree, a, b, c, d, maxDist, segTree) {
      var queue = new Queue(null, compareDist);
      var node = tree.data;
  
      // search through the point R-tree with a depth-first search using a priority queue
      // in the order of distance to the edge (b, c)
      while (node) {
          for (var i = 0; i < node.children.length; i++) {
              var child = node.children[i];
  
              var dist = node.leaf ? sqSegDist(child, b, c) : sqSegBoxDist(b, c, child);
              if (dist > maxDist) continue; // skip the node if it's farther than we ever need
  
              queue.push({
                  node: child,
                  dist: dist
              });
          }
  
          while (queue.length && !queue.peek().node.children) {
              var item = queue.pop();
              var p = item.node;
  
              // skip all points that are as close to adjacent edges (a,b) and (c,d),
              // and points that would introduce self-intersections when connected
              var d0 = sqSegDist(p, a, b);
              var d1 = sqSegDist(p, c, d);
              if (item.dist < d0 && item.dist < d1 &&
                  noIntersections(b, p, segTree) &&
                  noIntersections(c, p, segTree)) return p;
          }
  
          node = queue.pop();
          if (node) node = node.node;
      }
  
      return null;
  }
  
  function compareDist(a, b) {
      return a.dist - b.dist;
  }
  
  // square distance from a segment bounding box to the given one
  function sqSegBoxDist(a, b, bbox) {
      if (inside(a, bbox) || inside(b, bbox)) return 0;
      var d1 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.minY, bbox.maxX, bbox.minY);
      if (d1 === 0) return 0;
      var d2 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.minY, bbox.minX, bbox.maxY);
      if (d2 === 0) return 0;
      var d3 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.maxX, bbox.minY, bbox.maxX, bbox.maxY);
      if (d3 === 0) return 0;
      var d4 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox.minX, bbox.maxY, bbox.maxX, bbox.maxY);
      if (d4 === 0) return 0;
      return Math.min(d1, d2, d3, d4);
  }
  
  function inside(a, bbox) {
      return a[0] >= bbox.minX &&
             a[0] <= bbox.maxX &&
             a[1] >= bbox.minY &&
             a[1] <= bbox.maxY;
  }
  
  // check if the edge (a,b) doesn't intersect any other edges
  function noIntersections(a, b, segTree) {
      var minX = Math.min(a[0], b[0]);
      var minY = Math.min(a[1], b[1]);
      var maxX = Math.max(a[0], b[0]);
      var maxY = Math.max(a[1], b[1]);
  
      var edges = segTree.search({minX: minX, minY: minY, maxX: maxX, maxY: maxY});
      for (var i = 0; i < edges.length; i++) {
          if (intersects(edges[i].p, edges[i].next.p, a, b)) return false;
      }
      return true;
  }
  
  // check if the edges (p1,q1) and (p2,q2) intersect
  function intersects(p1, q1, p2, q2) {
      return p1 !== q2 && q1 !== p2 &&
          orient(p1, q1, p2) > 0 !== orient(p1, q1, q2) > 0 &&
          orient(p2, q2, p1) > 0 !== orient(p2, q2, q1) > 0;
  }
  
  // update the bounding box of a node's edge
  function updateBBox(node) {
      var p1 = node.p;
      var p2 = node.next.p;
      node.minX = Math.min(p1[0], p2[0]);
      node.minY = Math.min(p1[1], p2[1]);
      node.maxX = Math.max(p1[0], p2[0]);
      node.maxY = Math.max(p1[1], p2[1]);
      return node;
  }
  
  // speed up convex hull by filtering out points inside quadrilateral formed by 4 extreme points
  function fastConvexHull(points) {
      var left = points[0];
      var top = points[0];
      var right = points[0];
      var bottom = points[0];
  
      // find the leftmost, rightmost, topmost and bottommost points
      for (var i = 0; i < points.length; i++) {
          var p = points[i];
          if (p[0] < left[0]) left = p;
          if (p[0] > right[0]) right = p;
          if (p[1] < top[1]) top = p;
          if (p[1] > bottom[1]) bottom = p;
      }
  
      // filter out points that are inside the resulting quadrilateral
      var cull = [left, top, right, bottom];
      var filtered = cull.slice();
      for (i = 0; i < points.length; i++) {
          if (!pointInPolygon(points[i], cull)) filtered.push(points[i]);
      }
  
      // get convex hull around the filtered points
      var indices = convexHull(filtered);
  
      // return the hull as array of points (rather than indices)
      var hull = [];
      for (i = 0; i < indices.length; i++) hull.push(filtered[indices[i]]);
      return hull;
  }
  
  // create a new node in a doubly linked list
  function insertNode(p, prev) {
      var node = {
          p: p,
          prev: null,
          next: null,
          minX: 0,
          minY: 0,
          maxX: 0,
          maxY: 0
      };
  
      if (!prev) {
          node.prev = node;
          node.next = node;
  
      } else {
          node.next = prev.next;
          node.prev = prev;
          prev.next.prev = node;
          prev.next = node;
      }
      return node;
  }
  
  // square distance between 2 points
  function getSqDist(p1, p2) {
  
      var dx = p1[0] - p2[0],
          dy = p1[1] - p2[1];
  
      return dx * dx + dy * dy;
  }
  
  // square distance from a point to a segment
  function sqSegDist(p, p1, p2) {
  
      var x = p1[0],
          y = p1[1],
          dx = p2[0] - x,
          dy = p2[1] - y;
  
      if (dx !== 0 || dy !== 0) {
  
          var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
  
          if (t > 1) {
              x = p2[0];
              y = p2[1];
  
          } else if (t > 0) {
              x += dx * t;
              y += dy * t;
          }
      }
  
      dx = p[0] - x;
      dy = p[1] - y;
  
      return dx * dx + dy * dy;
  }
  
  // segment to segment distance, ported from http://geomalgorithms.com/a07-_distance.html by Dan Sunday
  function sqSegSegDist(x0, y0, x1, y1, x2, y2, x3, y3) {
      var ux = x1 - x0;
      var uy = y1 - y0;
      var vx = x3 - x2;
      var vy = y3 - y2;
      var wx = x0 - x2;
      var wy = y0 - y2;
      var a = ux * ux + uy * uy;
      var b = ux * vx + uy * vy;
      var c = vx * vx + vy * vy;
      var d = ux * wx + uy * wy;
      var e = vx * wx + vy * wy;
      var D = a * c - b * b;
  
      var sc, sN, tc, tN;
      var sD = D;
      var tD = D;
  
      if (D === 0) {
          sN = 0;
          sD = 1;
          tN = e;
          tD = c;
      } else {
          sN = b * e - c * d;
          tN = a * e - b * d;
          if (sN < 0) {
              sN = 0;
              tN = e;
              tD = c;
          } else if (sN > sD) {
              sN = sD;
              tN = e + b;
              tD = c;
          }
      }
  
      if (tN < 0.0) {
          tN = 0.0;
          if (-d < 0.0) sN = 0.0;
          else if (-d > a) sN = sD;
          else {
              sN = -d;
              sD = a;
          }
      } else if (tN > tD) {
          tN = tD;
          if ((-d + b) < 0.0) sN = 0;
          else if (-d + b > a) sN = sD;
          else {
              sN = -d + b;
              sD = a;
          }
      }
  
      sc = sN === 0 ? 0 : sN / sD;
      tc = tN === 0 ? 0 : tN / tD;
  
      var cx = (1 - sc) * x0 + sc * x1;
      var cy = (1 - sc) * y0 + sc * y1;
      var cx2 = (1 - tc) * x2 + tc * x3;
      var cy2 = (1 - tc) * y2 + tc * y3;
      var dx = cx2 - cx;
      var dy = cy2 - cy;
  
      return dx * dx + dy * dy;
  }
  
  
  /***/ }),
  
  /***/ "./node_modules/concaveman/node_modules/tinyqueue/index.js":
  /*!*****************************************************************!*\
    !*** ./node_modules/concaveman/node_modules/tinyqueue/index.js ***!
    \*****************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = TinyQueue;
  module.exports.default = TinyQueue;
  
  function TinyQueue(data, compare) {
      if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
  
      this.data = data || [];
      this.length = this.data.length;
      this.compare = compare || defaultCompare;
  
      if (this.length > 0) {
          for (var i = (this.length >> 1) - 1; i >= 0; i--) this._down(i);
      }
  }
  
  function defaultCompare(a, b) {
      return a < b ? -1 : a > b ? 1 : 0;
  }
  
  TinyQueue.prototype = {
  
      push: function (item) {
          this.data.push(item);
          this.length++;
          this._up(this.length - 1);
      },
  
      pop: function () {
          if (this.length === 0) return undefined;
  
          var top = this.data[0];
          this.length--;
  
          if (this.length > 0) {
              this.data[0] = this.data[this.length];
              this._down(0);
          }
          this.data.pop();
  
          return top;
      },
  
      peek: function () {
          return this.data[0];
      },
  
      _up: function (pos) {
          var data = this.data;
          var compare = this.compare;
          var item = data[pos];
  
          while (pos > 0) {
              var parent = (pos - 1) >> 1;
              var current = data[parent];
              if (compare(item, current) >= 0) break;
              data[pos] = current;
              pos = parent;
          }
  
          data[pos] = item;
      },
  
      _down: function (pos) {
          var data = this.data;
          var compare = this.compare;
          var halfLength = this.length >> 1;
          var item = data[pos];
  
          while (pos < halfLength) {
              var left = (pos << 1) + 1;
              var right = left + 1;
              var best = data[left];
  
              if (right < this.length && compare(data[right], best) < 0) {
                  left = right;
                  best = data[right];
              }
              if (compare(best, item) >= 0) break;
  
              data[pos] = best;
              pos = left;
          }
  
          data[pos] = item;
      }
  };
  
  
  /***/ }),
  
  /***/ "./node_modules/libtess/libtess.min.js":
  /*!*********************************************!*\
    !*** ./node_modules/libtess/libtess.min.js ***!
    \*********************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  /*
  
   Copyright 2000, Silicon Graphics, Inc. All Rights Reserved.
   Copyright 2015, Google Inc. All Rights Reserved.
  
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to
   deal in the Software without restriction, including without limitation the
   rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   sell copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:
  
   The above copyright notice including the dates of first publication and
   either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
   shall be included in all copies or substantial portions of the Software.
  
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
   IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  
   Original Code. The Original Code is: OpenGL Sample Implementation,
   Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
   Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
   Copyright in any portions created by third parties is as indicated
   elsewhere herein. All Rights Reserved.
  */
  var n;function t(a,b){return a.b===b.b&&a.a===b.a}function u(a,b){return a.b<b.b||a.b===b.b&&a.a<=b.a}function v(a,b,c){var d=b.b-a.b,e=c.b-b.b;return 0<d+e?d<e?b.a-a.a+d/(d+e)*(a.a-c.a):b.a-c.a+e/(d+e)*(c.a-a.a):0}function x(a,b,c){var d=b.b-a.b,e=c.b-b.b;return 0<d+e?(b.a-c.a)*d+(b.a-a.a)*e:0}function z(a,b){return a.a<b.a||a.a===b.a&&a.b<=b.b}function aa(a,b,c){var d=b.a-a.a,e=c.a-b.a;return 0<d+e?d<e?b.b-a.b+d/(d+e)*(a.b-c.b):b.b-c.b+e/(d+e)*(c.b-a.b):0}
  function ba(a,b,c){var d=b.a-a.a,e=c.a-b.a;return 0<d+e?(b.b-c.b)*d+(b.b-a.b)*e:0}function ca(a){return u(a.b.a,a.a)}function da(a){return u(a.a,a.b.a)}function A(a,b,c,d){a=0>a?0:a;c=0>c?0:c;return a<=c?0===c?(b+d)/2:b+a/(a+c)*(d-b):d+c/(a+c)*(b-d)};function ea(a){var b=B(a.b);C(b,a.c);C(b.b,a.c);D(b,a.a);return b}function E(a,b){var c=!1,d=!1;a!==b&&(b.a!==a.a&&(d=!0,F(b.a,a.a)),b.d!==a.d&&(c=!0,G(b.d,a.d)),H(b,a),d||(C(b,a.a),a.a.c=a),c||(D(b,a.d),a.d.a=a))}function I(a){var b=a.b,c=!1;a.d!==a.b.d&&(c=!0,G(a.d,a.b.d));a.c===a?F(a.a,null):(a.b.d.a=J(a),a.a.c=a.c,H(a,J(a)),c||D(a,a.d));b.c===b?(F(b.a,null),G(b.d,null)):(a.d.a=J(b),b.a.c=b.c,H(b,J(b)));fa(a)}
  function K(a){var b=B(a),c=b.b;H(b,a.e);b.a=a.b.a;C(c,b.a);b.d=c.d=a.d;b=b.b;H(a.b,J(a.b));H(a.b,b);a.b.a=b.a;b.b.a.c=b.b;b.b.d=a.b.d;b.f=a.f;b.b.f=a.b.f;return b}function L(a,b){var c=!1,d=B(a),e=d.b;b.d!==a.d&&(c=!0,G(b.d,a.d));H(d,a.e);H(e,b);d.a=a.b.a;e.a=b.a;d.d=e.d=a.d;a.d.a=e;c||D(d,a.d);return d}function B(a){var b=new M,c=new M,d=a.b.h;c.h=d;d.b.h=b;b.h=a;a.b.h=c;b.b=c;b.c=b;b.e=c;c.b=b;c.c=c;return c.e=b}function H(a,b){var c=a.c,d=b.c;c.b.e=b;d.b.e=a;a.c=d;b.c=c}
  function C(a,b){var c=b.f,d=new N(b,c);c.e=d;b.f=d;c=d.c=a;do c.a=d,c=c.c;while(c!==a)}function D(a,b){var c=b.d,d=new ga(b,c);c.b=d;b.d=d;d.a=a;d.c=b.c;c=a;do c.d=d,c=c.e;while(c!==a)}function fa(a){var b=a.h;a=a.b.h;b.b.h=a;a.b.h=b}function F(a,b){var c=a.c,d=c;do d.a=b,d=d.c;while(d!==c);c=a.f;d=a.e;d.f=c;c.e=d}function G(a,b){var c=a.a,d=c;do d.d=b,d=d.e;while(d!==c);c=a.d;d=a.b;d.d=c;c.b=d};function ha(a){var b=0;Math.abs(a[1])>Math.abs(a[0])&&(b=1);Math.abs(a[2])>Math.abs(a[b])&&(b=2);return b};var O=4*1E150;function P(a,b){a.f+=b.f;a.b.f+=b.b.f}function ia(a,b,c){a=a.a;b=b.a;c=c.a;if(b.b.a===a)return c.b.a===a?u(b.a,c.a)?0>=x(c.b.a,b.a,c.a):0<=x(b.b.a,c.a,b.a):0>=x(c.b.a,a,c.a);if(c.b.a===a)return 0<=x(b.b.a,a,b.a);b=v(b.b.a,a,b.a);a=v(c.b.a,a,c.a);return b>=a}function Q(a){a.a.i=null;var b=a.e;b.a.c=b.c;b.c.a=b.a;a.e=null}function ja(a,b){I(a.a);a.c=!1;a.a=b;b.i=a}function ka(a){var b=a.a.a;do a=R(a);while(a.a.a===b);a.c&&(b=L(S(a).a.b,a.a.e),ja(a,b),a=R(a));return a}
  function la(a,b,c){var d=new ma;d.a=c;d.e=na(a.f,b.e,d);return c.i=d}function oa(a,b){switch(a.s){case 100130:return 0!==(b&1);case 100131:return 0!==b;case 100132:return 0<b;case 100133:return 0>b;case 100134:return 2<=b||-2>=b}return!1}function pa(a){var b=a.a,c=b.d;c.c=a.d;c.a=b;Q(a)}function T(a,b,c){a=b;for(b=b.a;a!==c;){a.c=!1;var d=S(a),e=d.a;if(e.a!==b.a){if(!d.c){pa(a);break}e=L(b.c.b,e.b);ja(d,e)}b.c!==e&&(E(J(e),e),E(b,e));pa(a);b=d.a;a=d}return b}
  function U(a,b,c,d,e,f){var g=!0;do la(a,b,c.b),c=c.c;while(c!==d);for(null===e&&(e=S(b).a.b.c);;){d=S(b);c=d.a.b;if(c.a!==e.a)break;c.c!==e&&(E(J(c),c),E(J(e),c));d.f=b.f-c.f;d.d=oa(a,d.f);b.b=!0;!g&&qa(a,b)&&(P(c,e),Q(b),I(e));g=!1;b=d;e=c}b.b=!0;f&&ra(a,b)}function sa(a,b,c,d,e){var f=[b.g[0],b.g[1],b.g[2]];b.d=null;b.d=a.o?a.o(f,c,d,a.c)||null:null;null===b.d&&(e?a.n||(V(a,100156),a.n=!0):b.d=c[0])}
  function ta(a,b,c){var d=[null,null,null,null];d[0]=b.a.d;d[1]=c.a.d;sa(a,b.a,d,[.5,.5,0,0],!1);E(b,c)}function ua(a,b,c,d,e){var f=Math.abs(b.b-a.b)+Math.abs(b.a-a.a),g=Math.abs(c.b-a.b)+Math.abs(c.a-a.a),h=e+1;d[e]=.5*g/(f+g);d[h]=.5*f/(f+g);a.g[0]+=d[e]*b.g[0]+d[h]*c.g[0];a.g[1]+=d[e]*b.g[1]+d[h]*c.g[1];a.g[2]+=d[e]*b.g[2]+d[h]*c.g[2]}
  function qa(a,b){var c=S(b),d=b.a,e=c.a;if(u(d.a,e.a)){if(0<x(e.b.a,d.a,e.a))return!1;if(!t(d.a,e.a))K(e.b),E(d,J(e)),b.b=c.b=!0;else if(d.a!==e.a){var c=a.e,f=d.a.h;if(0<=f){var c=c.b,g=c.d,h=c.e,k=c.c,l=k[f];g[l]=g[c.a];k[g[l]]=l;l<=--c.a&&(1>=l?W(c,l):u(h[g[l>>1]],h[g[l]])?W(c,l):va(c,l));h[f]=null;k[f]=c.b;c.b=f}else for(c.c[-(f+1)]=null;0<c.a&&null===c.c[c.d[c.a-1]];)--c.a;ta(a,J(e),d)}}else{if(0>x(d.b.a,e.a,d.a))return!1;R(b).b=b.b=!0;K(d.b);E(J(e),d)}return!0}
  function wa(a,b){var c=S(b),d=b.a,e=c.a,f=d.a,g=e.a,h=d.b.a,k=e.b.a,l=new N;x(h,a.a,f);x(k,a.a,g);if(f===g||Math.min(f.a,h.a)>Math.max(g.a,k.a))return!1;if(u(f,g)){if(0<x(k,f,g))return!1}else if(0>x(h,g,f))return!1;var r=h,p=f,q=k,y=g,m,w;u(r,p)||(m=r,r=p,p=m);u(q,y)||(m=q,q=y,y=m);u(r,q)||(m=r,r=q,q=m,m=p,p=y,y=m);u(q,p)?u(p,y)?(m=v(r,q,p),w=v(q,p,y),0>m+w&&(m=-m,w=-w),l.b=A(m,q.b,w,p.b)):(m=x(r,q,p),w=-x(r,y,p),0>m+w&&(m=-m,w=-w),l.b=A(m,q.b,w,y.b)):l.b=(q.b+p.b)/2;z(r,p)||(m=r,r=p,p=m);z(q,y)||
  (m=q,q=y,y=m);z(r,q)||(m=r,r=q,q=m,m=p,p=y,y=m);z(q,p)?z(p,y)?(m=aa(r,q,p),w=aa(q,p,y),0>m+w&&(m=-m,w=-w),l.a=A(m,q.a,w,p.a)):(m=ba(r,q,p),w=-ba(r,y,p),0>m+w&&(m=-m,w=-w),l.a=A(m,q.a,w,y.a)):l.a=(q.a+p.a)/2;u(l,a.a)&&(l.b=a.a.b,l.a=a.a.a);r=u(f,g)?f:g;u(r,l)&&(l.b=r.b,l.a=r.a);if(t(l,f)||t(l,g))return qa(a,b),!1;if(!t(h,a.a)&&0<=x(h,a.a,l)||!t(k,a.a)&&0>=x(k,a.a,l)){if(k===a.a)return K(d.b),E(e.b,d),b=ka(b),d=S(b).a,T(a,S(b),c),U(a,b,J(d),d,d,!0),!0;if(h===a.a){K(e.b);E(d.e,J(e));f=c=b;g=f.a.b.a;
  do f=R(f);while(f.a.b.a===g);b=f;f=S(b).a.b.c;c.a=J(e);e=T(a,c,null);U(a,b,e.c,d.b.c,f,!0);return!0}0<=x(h,a.a,l)&&(R(b).b=b.b=!0,K(d.b),d.a.b=a.a.b,d.a.a=a.a.a);0>=x(k,a.a,l)&&(b.b=c.b=!0,K(e.b),e.a.b=a.a.b,e.a.a=a.a.a);return!1}K(d.b);K(e.b);E(J(e),d);d.a.b=l.b;d.a.a=l.a;d.a.h=xa(a.e,d.a);d=d.a;e=[0,0,0,0];l=[f.d,h.d,g.d,k.d];d.g[0]=d.g[1]=d.g[2]=0;ua(d,f,h,e,0);ua(d,g,k,e,2);sa(a,d,l,e,!0);R(b).b=b.b=c.b=!0;return!1}
  function ra(a,b){for(var c=S(b);;){for(;c.b;)b=c,c=S(c);if(!b.b&&(c=b,b=R(b),null===b||!b.b))break;b.b=!1;var d=b.a,e=c.a,f;if(f=d.b.a!==e.b.a)a:{f=b;var g=S(f),h=f.a,k=g.a,l=void 0;if(u(h.b.a,k.b.a)){if(0>x(h.b.a,k.b.a,h.a)){f=!1;break a}R(f).b=f.b=!0;l=K(h);E(k.b,l);l.d.c=f.d}else{if(0<x(k.b.a,h.b.a,k.a)){f=!1;break a}f.b=g.b=!0;l=K(k);E(h.e,k.b);l.b.d.c=f.d}f=!0}f&&(c.c?(Q(c),I(e),c=S(b),e=c.a):b.c&&(Q(b),I(d),b=R(c),d=b.a));if(d.a!==e.a)if(d.b.a===e.b.a||b.c||c.c||d.b.a!==a.a&&e.b.a!==a.a)qa(a,
  b);else if(wa(a,b))break;d.a===e.a&&d.b.a===e.b.a&&(P(e,d),Q(b),I(d),b=R(c))}}
  function ya(a,b){a.a=b;for(var c=b.c;null===c.i;)if(c=c.c,c===b.c){var c=a,d=b,e=new ma;e.a=d.c.b;var f=c.f,g=f.a;do g=g.a;while(null!==g.b&&!f.c(f.b,e,g.b));var f=g.b,h=S(f),e=f.a,g=h.a;if(0===x(e.b.a,d,e.a))e=f.a,t(e.a,d)||t(e.b.a,d)||(K(e.b),f.c&&(I(e.c),f.c=!1),E(d.c,e),ya(c,d));else{var k=u(g.b.a,e.b.a)?f:h,h=void 0;f.d||k.c?(k===f?h=L(d.c.b,e.e):h=L(g.b.c.b,d.c).b,k.c?ja(k,h):(e=c,f=la(c,f,h),f.f=R(f).f+f.a.f,f.d=oa(e,f.f)),ya(c,d)):U(c,f,d.c,d.c,null,!0)}return}c=ka(c.i);e=S(c);f=e.a;e=T(a,
  e,null);if(e.c===f){var f=e,e=f.c,g=S(c),h=c.a,k=g.a,l=!1;h.b.a!==k.b.a&&wa(a,c);t(h.a,a.a)&&(E(J(e),h),c=ka(c),e=S(c).a,T(a,S(c),g),l=!0);t(k.a,a.a)&&(E(f,J(k)),f=T(a,g,null),l=!0);l?U(a,c,f.c,e,e,!0):(u(k.a,h.a)?d=J(k):d=h,d=L(f.c.b,d),U(a,c,d,d.c,d.c,!1),d.b.i.c=!0,ra(a,c))}else U(a,c,e.c,f,f,!0)}function za(a,b){var c=new ma,d=ea(a.b);d.a.b=O;d.a.a=b;d.b.a.b=-O;d.b.a.a=b;a.a=d.b.a;c.a=d;c.f=0;c.d=!1;c.c=!1;c.h=!0;c.b=!1;d=a.f;d=na(d,d.a,c);c.e=d};function Aa(a){this.a=new Ba;this.b=a;this.c=ia}function na(a,b,c){do b=b.c;while(null!==b.b&&!a.c(a.b,b.b,c));a=new Ba(c,b.a,b);b.a.c=a;return b.a=a};function Ba(a,b,c){this.b=a||null;this.a=b||this;this.c=c||this};function X(){this.d=Y;this.p=this.b=this.q=null;this.j=[0,0,0];this.s=100130;this.n=!1;this.o=this.a=this.e=this.f=null;this.m=!1;this.c=this.r=this.i=this.k=this.l=this.h=null}var Y=0;n=X.prototype;n.x=function(){Z(this,Y)};n.B=function(a,b){switch(a){case 100142:return;case 100140:switch(b){case 100130:case 100131:case 100132:case 100133:case 100134:this.s=b;return}break;case 100141:this.m=!!b;return;default:V(this,100900);return}V(this,100901)};
  n.y=function(a){switch(a){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:V(this,100900)}return!1};n.A=function(a,b,c){this.j[0]=a;this.j[1]=b;this.j[2]=c};
  n.z=function(a,b){var c=b?b:null;switch(a){case 100100:case 100106:this.h=c;break;case 100104:case 100110:this.l=c;break;case 100101:case 100107:this.k=c;break;case 100102:case 100108:this.i=c;break;case 100103:case 100109:this.p=c;break;case 100105:case 100111:this.o=c;break;case 100112:this.r=c;break;default:V(this,100900)}};
  n.C=function(a,b){var c=!1,d=[0,0,0];Z(this,2);for(var e=0;3>e;++e){var f=a[e];-1E150>f&&(f=-1E150,c=!0);1E150<f&&(f=1E150,c=!0);d[e]=f}c&&V(this,100155);c=this.q;null===c?(c=ea(this.b),E(c,c.b)):(K(c),c=c.e);c.a.d=b;c.a.g[0]=d[0];c.a.g[1]=d[1];c.a.g[2]=d[2];c.f=1;c.b.f=-1;this.q=c};n.u=function(a){Z(this,Y);this.d=1;this.b=new Ca;this.c=a};n.t=function(){Z(this,1);this.d=2;this.q=null};n.v=function(){Z(this,2);this.d=1};
  n.w=function(){Z(this,1);this.d=Y;var a=this.j[0],b=this.j[1],c=this.j[2],d=!1,e=[a,b,c];if(0===a&&0===b&&0===c){for(var b=[-2*1E150,-2*1E150,-2*1E150],f=[2*1E150,2*1E150,2*1E150],c=[],g=[],d=this.b.c,a=d.e;a!==d;a=a.e)for(var h=0;3>h;++h){var k=a.g[h];k<f[h]&&(f[h]=k,g[h]=a);k>b[h]&&(b[h]=k,c[h]=a)}a=0;b[1]-f[1]>b[0]-f[0]&&(a=1);b[2]-f[2]>b[a]-f[a]&&(a=2);if(f[a]>=b[a])e[0]=0,e[1]=0,e[2]=1;else{b=0;f=g[a];c=c[a];g=[0,0,0];f=[f.g[0]-c.g[0],f.g[1]-c.g[1],f.g[2]-c.g[2]];h=[0,0,0];for(a=d.e;a!==d;a=
  a.e)h[0]=a.g[0]-c.g[0],h[1]=a.g[1]-c.g[1],h[2]=a.g[2]-c.g[2],g[0]=f[1]*h[2]-f[2]*h[1],g[1]=f[2]*h[0]-f[0]*h[2],g[2]=f[0]*h[1]-f[1]*h[0],k=g[0]*g[0]+g[1]*g[1]+g[2]*g[2],k>b&&(b=k,e[0]=g[0],e[1]=g[1],e[2]=g[2]);0>=b&&(e[0]=e[1]=e[2]=0,e[ha(f)]=1)}d=!0}g=ha(e);a=this.b.c;b=(g+1)%3;c=(g+2)%3;g=0<e[g]?1:-1;for(e=a.e;e!==a;e=e.e)e.b=e.g[b],e.a=g*e.g[c];if(d){e=0;d=this.b.a;for(a=d.b;a!==d;a=a.b)if(b=a.a,!(0>=b.f)){do e+=(b.a.b-b.b.a.b)*(b.a.a+b.b.a.a),b=b.e;while(b!==a.a)}if(0>e)for(e=this.b.c,d=e.e;d!==
  e;d=d.e)d.a=-d.a}this.n=!1;e=this.b.b;for(a=e.h;a!==e;a=d)if(d=a.h,b=a.e,t(a.a,a.b.a)&&a.e.e!==a&&(ta(this,b,a),I(a),a=b,b=a.e),b.e===a){if(b!==a){if(b===d||b===d.b)d=d.h;I(b)}if(a===d||a===d.b)d=d.h;I(a)}this.e=e=new Da;d=this.b.c;for(a=d.e;a!==d;a=a.e)a.h=xa(e,a);Ea(e);this.f=new Aa(this);za(this,-O);for(za(this,O);null!==(e=Fa(this.e));){for(;;){a:if(a=this.e,0===a.a)d=Ga(a.b);else if(d=a.c[a.d[a.a-1]],0!==a.b.a&&(a=Ga(a.b),u(a,d))){d=a;break a}if(null===d||!t(d,e))break;d=Fa(this.e);ta(this,e.c,
  d.c)}ya(this,e)}this.a=this.f.a.a.b.a.a;for(e=0;null!==(d=this.f.a.a.b);)d.h||++e,Q(d);this.f=null;e=this.e;e.b=null;e.d=null;this.e=e.c=null;e=this.b;for(a=e.a.b;a!==e.a;a=d)d=a.b,a=a.a,a.e.e===a&&(P(a.c,a),I(a));if(!this.n){e=this.b;if(this.m)for(a=e.b.h;a!==e.b;a=d)d=a.h,a.b.d.c!==a.d.c?a.f=a.d.c?1:-1:I(a);else for(a=e.a.b;a!==e.a;a=d)if(d=a.b,a.c){for(a=a.a;u(a.b.a,a.a);a=a.c.b);for(;u(a.a,a.b.a);a=a.e);b=a.c.b;for(c=void 0;a.e!==b;)if(u(a.b.a,b.a)){for(;b.e!==a&&(ca(b.e)||0>=x(b.a,b.b.a,b.e.b.a));)c=
  L(b.e,b),b=c.b;b=b.c.b}else{for(;b.e!==a&&(da(a.c.b)||0<=x(a.b.a,a.a,a.c.b.a));)c=L(a,a.c.b),a=c.b;a=a.e}for(;b.e.e!==a;)c=L(b.e,b),b=c.b}if(this.h||this.i||this.k||this.l)if(this.m)for(e=this.b,d=e.a.b;d!==e.a;d=d.b){if(d.c){this.h&&this.h(2,this.c);a=d.a;do this.k&&this.k(a.a.d,this.c),a=a.e;while(a!==d.a);this.i&&this.i(this.c)}}else{e=this.b;d=!!this.l;a=!1;b=-1;for(c=e.a.d;c!==e.a;c=c.d)if(c.c){a||(this.h&&this.h(4,this.c),a=!0);g=c.a;do d&&(f=g.b.d.c?0:1,b!==f&&(b=f,this.l&&this.l(!!b,this.c))),
  this.k&&this.k(g.a.d,this.c),g=g.e;while(g!==c.a)}a&&this.i&&this.i(this.c)}if(this.r){e=this.b;for(a=e.a.b;a!==e.a;a=d)if(d=a.b,!a.c){b=a.a;c=b.e;g=void 0;do g=c,c=g.e,g.d=null,null===g.b.d&&(g.c===g?F(g.a,null):(g.a.c=g.c,H(g,J(g))),f=g.b,f.c===f?F(f.a,null):(f.a.c=f.c,H(f,J(f))),fa(g));while(g!==b);b=a.d;a=a.b;a.d=b;b.b=a}this.r(this.b);this.c=this.b=null;return}}this.b=this.c=null};
  function Z(a,b){if(a.d!==b)for(;a.d!==b;)if(a.d<b)switch(a.d){case Y:V(a,100151);a.u(null);break;case 1:V(a,100152),a.t()}else switch(a.d){case 2:V(a,100154);a.v();break;case 1:V(a,100153),a.w()}}function V(a,b){a.p&&a.p(b,a.c)};function ga(a,b){this.b=a||this;this.d=b||this;this.a=null;this.c=!1};function M(){this.h=this;this.i=this.d=this.a=this.e=this.c=this.b=null;this.f=0}function J(a){return a.b.e};function Ca(){this.c=new N;this.a=new ga;this.b=new M;this.d=new M;this.b.b=this.d;this.d.b=this.b};function N(a,b){this.e=a||this;this.f=b||this;this.d=this.c=null;this.g=[0,0,0];this.h=this.a=this.b=0};function Da(){this.c=[];this.d=null;this.a=0;this.e=!1;this.b=new Ha}function Ea(a){a.d=[];for(var b=0;b<a.a;b++)a.d[b]=b;a.d.sort(function(a){return function(b,e){return u(a[b],a[e])?1:-1}}(a.c));a.e=!0;Ia(a.b)}function xa(a,b){if(a.e){var c=a.b,d=++c.a;2*d>c.f&&(c.f*=2,c.c=Ja(c.c,c.f+1));var e;0===c.b?e=d:(e=c.b,c.b=c.c[c.b]);c.e[e]=b;c.c[e]=d;c.d[d]=e;c.h&&va(c,d);return e}c=a.a++;a.c[c]=b;return-(c+1)}
  function Fa(a){if(0===a.a)return Ka(a.b);var b=a.c[a.d[a.a-1]];if(0!==a.b.a&&u(Ga(a.b),b))return Ka(a.b);do--a.a;while(0<a.a&&null===a.c[a.d[a.a-1]]);return b};function Ha(){this.d=Ja([0],33);this.e=[null,null];this.c=[0,0];this.a=0;this.f=32;this.b=0;this.h=!1;this.d[1]=1}function Ja(a,b){for(var c=Array(b),d=0;d<a.length;d++)c[d]=a[d];for(;d<b;d++)c[d]=0;return c}function Ia(a){for(var b=a.a;1<=b;--b)W(a,b);a.h=!0}function Ga(a){return a.e[a.d[1]]}function Ka(a){var b=a.d,c=a.e,d=a.c,e=b[1],f=c[e];0<a.a&&(b[1]=b[a.a],d[b[1]]=1,c[e]=null,d[e]=a.b,a.b=e,0<--a.a&&W(a,1));return f}
  function W(a,b){for(var c=a.d,d=a.e,e=a.c,f=b,g=c[f];;){var h=f<<1;h<a.a&&u(d[c[h+1]],d[c[h]])&&(h+=1);var k=c[h];if(h>a.a||u(d[g],d[k])){c[f]=g;e[g]=f;break}c[f]=k;e[k]=f;f=h}}function va(a,b){for(var c=a.d,d=a.e,e=a.c,f=b,g=c[f];;){var h=f>>1,k=c[h];if(0===h||u(d[k],d[g])){c[f]=g;e[g]=f;break}c[f]=k;e[k]=f;f=h}};function ma(){this.e=this.a=null;this.f=0;this.c=this.b=this.h=this.d=!1}function S(a){return a.e.c.b}function R(a){return a.e.a.b};this.libtess={GluTesselator:X,windingRule:{GLU_TESS_WINDING_ODD:100130,GLU_TESS_WINDING_NONZERO:100131,GLU_TESS_WINDING_POSITIVE:100132,GLU_TESS_WINDING_NEGATIVE:100133,GLU_TESS_WINDING_ABS_GEQ_TWO:100134},primitiveType:{GL_LINE_LOOP:2,GL_TRIANGLES:4,GL_TRIANGLE_STRIP:5,GL_TRIANGLE_FAN:6},errorType:{GLU_TESS_MISSING_BEGIN_POLYGON:100151,GLU_TESS_MISSING_END_POLYGON:100153,GLU_TESS_MISSING_BEGIN_CONTOUR:100152,GLU_TESS_MISSING_END_CONTOUR:100154,GLU_TESS_COORD_TOO_LARGE:100155,GLU_TESS_NEED_COMBINE_CALLBACK:100156},
  gluEnum:{GLU_TESS_MESH:100112,GLU_TESS_TOLERANCE:100142,GLU_TESS_WINDING_RULE:100140,GLU_TESS_BOUNDARY_ONLY:100141,GLU_INVALID_ENUM:100900,GLU_INVALID_VALUE:100901,GLU_TESS_BEGIN:100100,GLU_TESS_VERTEX:100101,GLU_TESS_END:100102,GLU_TESS_ERROR:100103,GLU_TESS_EDGE_FLAG:100104,GLU_TESS_COMBINE:100105,GLU_TESS_BEGIN_DATA:100106,GLU_TESS_VERTEX_DATA:100107,GLU_TESS_END_DATA:100108,GLU_TESS_ERROR_DATA:100109,GLU_TESS_EDGE_FLAG_DATA:100110,GLU_TESS_COMBINE_DATA:100111}};X.prototype.gluDeleteTess=X.prototype.x;
  X.prototype.gluTessProperty=X.prototype.B;X.prototype.gluGetTessProperty=X.prototype.y;X.prototype.gluTessNormal=X.prototype.A;X.prototype.gluTessCallback=X.prototype.z;X.prototype.gluTessVertex=X.prototype.C;X.prototype.gluTessBeginPolygon=X.prototype.u;X.prototype.gluTessBeginContour=X.prototype.t;X.prototype.gluTessEndContour=X.prototype.v;X.prototype.gluTessEndPolygon=X.prototype.w; if (true) { module.exports = this.libtess; }
  
  
  /***/ }),
  
  /***/ "./node_modules/monotone-convex-hull-2d/index.js":
  /*!*******************************************************!*\
    !*** ./node_modules/monotone-convex-hull-2d/index.js ***!
    \*******************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = monotoneConvexHull2D
  
  var orient = __webpack_require__(/*! robust-orientation */ "./node_modules/robust-orientation/orientation.js")[3]
  
  function monotoneConvexHull2D(points) {
    var n = points.length
  
    if(n < 3) {
      var result = new Array(n)
      for(var i=0; i<n; ++i) {
        result[i] = i
      }
  
      if(n === 2 &&
         points[0][0] === points[1][0] &&
         points[0][1] === points[1][1]) {
        return [0]
      }
  
      return result
    }
  
    //Sort point indices along x-axis
    var sorted = new Array(n)
    for(var i=0; i<n; ++i) {
      sorted[i] = i
    }
    sorted.sort(function(a,b) {
      var d = points[a][0]-points[b][0]
      if(d) {
        return d
      }
      return points[a][1] - points[b][1]
    })
  
    //Construct upper and lower hulls
    var lower = [sorted[0], sorted[1]]
    var upper = [sorted[0], sorted[1]]
  
    for(var i=2; i<n; ++i) {
      var idx = sorted[i]
      var p   = points[idx]
  
      //Insert into lower list
      var m = lower.length
      while(m > 1 && orient(
          points[lower[m-2]], 
          points[lower[m-1]], 
          p) <= 0) {
        m -= 1
        lower.pop()
      }
      lower.push(idx)
  
      //Insert into upper list
      m = upper.length
      while(m > 1 && orient(
          points[upper[m-2]], 
          points[upper[m-1]], 
          p) >= 0) {
        m -= 1
        upper.pop()
      }
      upper.push(idx)
    }
  
    //Merge lists together
    var result = new Array(upper.length + lower.length - 2)
    var ptr    = 0
    for(var i=0, nl=lower.length; i<nl; ++i) {
      result[ptr++] = lower[i]
    }
    for(var j=upper.length-2; j>0; --j) {
      result[ptr++] = upper[j]
    }
  
    //Return result
    return result
  }
  
  /***/ }),
  
  /***/ "./node_modules/point-in-polygon/index.js":
  /*!************************************************!*\
    !*** ./node_modules/point-in-polygon/index.js ***!
    \************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = function (point, vs) {
      // ray-casting algorithm based on
      // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
      
      var x = point[0], y = point[1];
      
      var inside = false;
      for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
          var xi = vs[i][0], yi = vs[i][1];
          var xj = vs[j][0], yj = vs[j][1];
          
          var intersect = ((yi > y) != (yj > y))
              && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
          if (intersect) inside = !inside;
      }
      
      return inside;
  };
  
  
  /***/ }),
  
  /***/ "./node_modules/process/browser.js":
  /*!*****************************************!*\
    !*** ./node_modules/process/browser.js ***!
    \*****************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  // shim for using process in browser
  var process = module.exports = {};
  
  // cached from whatever global is present so that test runners that stub it
  // don't break things.  But we need to wrap it in a try catch in case it is
  // wrapped in strict mode code which doesn't define any globals.  It's inside a
  // function because try/catches deoptimize in certain engines.
  
  var cachedSetTimeout;
  var cachedClearTimeout;
  
  function defaultSetTimout() {
      throw new Error('setTimeout has not been defined');
  }
  function defaultClearTimeout () {
      throw new Error('clearTimeout has not been defined');
  }
  (function () {
      try {
          if (typeof setTimeout === 'function') {
              cachedSetTimeout = setTimeout;
          } else {
              cachedSetTimeout = defaultSetTimout;
          }
      } catch (e) {
          cachedSetTimeout = defaultSetTimout;
      }
      try {
          if (typeof clearTimeout === 'function') {
              cachedClearTimeout = clearTimeout;
          } else {
              cachedClearTimeout = defaultClearTimeout;
          }
      } catch (e) {
          cachedClearTimeout = defaultClearTimeout;
      }
  } ())
  function runTimeout(fun) {
      if (cachedSetTimeout === setTimeout) {
          //normal enviroments in sane situations
          return setTimeout(fun, 0);
      }
      // if setTimeout wasn't available but was latter defined
      if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
          cachedSetTimeout = setTimeout;
          return setTimeout(fun, 0);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedSetTimeout(fun, 0);
      } catch(e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
              return cachedSetTimeout.call(null, fun, 0);
          } catch(e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
              return cachedSetTimeout.call(this, fun, 0);
          }
      }
  
  
  }
  function runClearTimeout(marker) {
      if (cachedClearTimeout === clearTimeout) {
          //normal enviroments in sane situations
          return clearTimeout(marker);
      }
      // if clearTimeout wasn't available but was latter defined
      if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
          cachedClearTimeout = clearTimeout;
          return clearTimeout(marker);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedClearTimeout(marker);
      } catch (e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
              return cachedClearTimeout.call(null, marker);
          } catch (e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
              // Some versions of I.E. have different rules for clearTimeout vs setTimeout
              return cachedClearTimeout.call(this, marker);
          }
      }
  
  
  
  }
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      if (!draining || !currentQueue) {
          return;
      }
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = runTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      runClearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          runTimeout(drainQueue);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  process.prependListener = noop;
  process.prependOnceListener = noop;
  
  process.listeners = function (name) { return [] }
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  
  /***/ }),
  
  /***/ "./node_modules/quickselect/quickselect.js":
  /*!*************************************************!*\
    !*** ./node_modules/quickselect/quickselect.js ***!
    \*************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  (function (global, factory) {
  	 true ? module.exports = factory() :
  	undefined;
  }(this, (function () { 'use strict';
  
  function quickselect(arr, k, left, right, compare) {
      quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);
  }
  
  function quickselectStep(arr, k, left, right, compare) {
  
      while (right > left) {
          if (right - left > 600) {
              var n = right - left + 1;
              var m = k - left + 1;
              var z = Math.log(n);
              var s = 0.5 * Math.exp(2 * z / 3);
              var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
              var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
              var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
              quickselectStep(arr, k, newLeft, newRight, compare);
          }
  
          var t = arr[k];
          var i = left;
          var j = right;
  
          swap(arr, left, k);
          if (compare(arr[right], t) > 0) swap(arr, left, right);
  
          while (i < j) {
              swap(arr, i, j);
              i++;
              j--;
              while (compare(arr[i], t) < 0) i++;
              while (compare(arr[j], t) > 0) j--;
          }
  
          if (compare(arr[left], t) === 0) swap(arr, left, j);
          else {
              j++;
              swap(arr, j, right);
          }
  
          if (j <= k) left = j + 1;
          if (k <= j) right = j - 1;
      }
  }
  
  function swap(arr, i, j) {
      var tmp = arr[i];
      arr[i] = arr[j];
      arr[j] = tmp;
  }
  
  function defaultCompare(a, b) {
      return a < b ? -1 : a > b ? 1 : 0;
  }
  
  return quickselect;
  
  })));
  
  
  /***/ }),
  
  /***/ "./node_modules/rbush/index.js":
  /*!*************************************!*\
    !*** ./node_modules/rbush/index.js ***!
    \*************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = rbush;
  module.exports.default = rbush;
  
  var quickselect = __webpack_require__(/*! quickselect */ "./node_modules/quickselect/quickselect.js");
  
  function rbush(maxEntries, format) {
      if (!(this instanceof rbush)) return new rbush(maxEntries, format);
  
      // max entries in a node is 9 by default; min node fill is 40% for best performance
      this._maxEntries = Math.max(4, maxEntries || 9);
      this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
  
      if (format) {
          this._initFormat(format);
      }
  
      this.clear();
  }
  
  rbush.prototype = {
  
      all: function () {
          return this._all(this.data, []);
      },
  
      search: function (bbox) {
  
          var node = this.data,
              result = [],
              toBBox = this.toBBox;
  
          if (!intersects(bbox, node)) return result;
  
          var nodesToSearch = [],
              i, len, child, childBBox;
  
          while (node) {
              for (i = 0, len = node.children.length; i < len; i++) {
  
                  child = node.children[i];
                  childBBox = node.leaf ? toBBox(child) : child;
  
                  if (intersects(bbox, childBBox)) {
                      if (node.leaf) result.push(child);
                      else if (contains(bbox, childBBox)) this._all(child, result);
                      else nodesToSearch.push(child);
                  }
              }
              node = nodesToSearch.pop();
          }
  
          return result;
      },
  
      collides: function (bbox) {
  
          var node = this.data,
              toBBox = this.toBBox;
  
          if (!intersects(bbox, node)) return false;
  
          var nodesToSearch = [],
              i, len, child, childBBox;
  
          while (node) {
              for (i = 0, len = node.children.length; i < len; i++) {
  
                  child = node.children[i];
                  childBBox = node.leaf ? toBBox(child) : child;
  
                  if (intersects(bbox, childBBox)) {
                      if (node.leaf || contains(bbox, childBBox)) return true;
                      nodesToSearch.push(child);
                  }
              }
              node = nodesToSearch.pop();
          }
  
          return false;
      },
  
      load: function (data) {
          if (!(data && data.length)) return this;
  
          if (data.length < this._minEntries) {
              for (var i = 0, len = data.length; i < len; i++) {
                  this.insert(data[i]);
              }
              return this;
          }
  
          // recursively build the tree with the given data from scratch using OMT algorithm
          var node = this._build(data.slice(), 0, data.length - 1, 0);
  
          if (!this.data.children.length) {
              // save as is if tree is empty
              this.data = node;
  
          } else if (this.data.height === node.height) {
              // split root if trees have the same height
              this._splitRoot(this.data, node);
  
          } else {
              if (this.data.height < node.height) {
                  // swap trees if inserted one is bigger
                  var tmpNode = this.data;
                  this.data = node;
                  node = tmpNode;
              }
  
              // insert the small tree into the large tree at appropriate level
              this._insert(node, this.data.height - node.height - 1, true);
          }
  
          return this;
      },
  
      insert: function (item) {
          if (item) this._insert(item, this.data.height - 1);
          return this;
      },
  
      clear: function () {
          this.data = createNode([]);
          return this;
      },
  
      remove: function (item, equalsFn) {
          if (!item) return this;
  
          var node = this.data,
              bbox = this.toBBox(item),
              path = [],
              indexes = [],
              i, parent, index, goingUp;
  
          // depth-first iterative tree traversal
          while (node || path.length) {
  
              if (!node) { // go up
                  node = path.pop();
                  parent = path[path.length - 1];
                  i = indexes.pop();
                  goingUp = true;
              }
  
              if (node.leaf) { // check current node
                  index = findItem(item, node.children, equalsFn);
  
                  if (index !== -1) {
                      // item found, remove the item and condense tree upwards
                      node.children.splice(index, 1);
                      path.push(node);
                      this._condense(path);
                      return this;
                  }
              }
  
              if (!goingUp && !node.leaf && contains(node, bbox)) { // go down
                  path.push(node);
                  indexes.push(i);
                  i = 0;
                  parent = node;
                  node = node.children[0];
  
              } else if (parent) { // go right
                  i++;
                  node = parent.children[i];
                  goingUp = false;
  
              } else node = null; // nothing found
          }
  
          return this;
      },
  
      toBBox: function (item) { return item; },
  
      compareMinX: compareNodeMinX,
      compareMinY: compareNodeMinY,
  
      toJSON: function () { return this.data; },
  
      fromJSON: function (data) {
          this.data = data;
          return this;
      },
  
      _all: function (node, result) {
          var nodesToSearch = [];
          while (node) {
              if (node.leaf) result.push.apply(result, node.children);
              else nodesToSearch.push.apply(nodesToSearch, node.children);
  
              node = nodesToSearch.pop();
          }
          return result;
      },
  
      _build: function (items, left, right, height) {
  
          var N = right - left + 1,
              M = this._maxEntries,
              node;
  
          if (N <= M) {
              // reached leaf level; return leaf
              node = createNode(items.slice(left, right + 1));
              calcBBox(node, this.toBBox);
              return node;
          }
  
          if (!height) {
              // target height of the bulk-loaded tree
              height = Math.ceil(Math.log(N) / Math.log(M));
  
              // target number of root entries to maximize storage utilization
              M = Math.ceil(N / Math.pow(M, height - 1));
          }
  
          node = createNode([]);
          node.leaf = false;
          node.height = height;
  
          // split the items into M mostly square tiles
  
          var N2 = Math.ceil(N / M),
              N1 = N2 * Math.ceil(Math.sqrt(M)),
              i, j, right2, right3;
  
          multiSelect(items, left, right, N1, this.compareMinX);
  
          for (i = left; i <= right; i += N1) {
  
              right2 = Math.min(i + N1 - 1, right);
  
              multiSelect(items, i, right2, N2, this.compareMinY);
  
              for (j = i; j <= right2; j += N2) {
  
                  right3 = Math.min(j + N2 - 1, right2);
  
                  // pack each entry recursively
                  node.children.push(this._build(items, j, right3, height - 1));
              }
          }
  
          calcBBox(node, this.toBBox);
  
          return node;
      },
  
      _chooseSubtree: function (bbox, node, level, path) {
  
          var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
  
          while (true) {
              path.push(node);
  
              if (node.leaf || path.length - 1 === level) break;
  
              minArea = minEnlargement = Infinity;
  
              for (i = 0, len = node.children.length; i < len; i++) {
                  child = node.children[i];
                  area = bboxArea(child);
                  enlargement = enlargedArea(bbox, child) - area;
  
                  // choose entry with the least area enlargement
                  if (enlargement < minEnlargement) {
                      minEnlargement = enlargement;
                      minArea = area < minArea ? area : minArea;
                      targetNode = child;
  
                  } else if (enlargement === minEnlargement) {
                      // otherwise choose one with the smallest area
                      if (area < minArea) {
                          minArea = area;
                          targetNode = child;
                      }
                  }
              }
  
              node = targetNode || node.children[0];
          }
  
          return node;
      },
  
      _insert: function (item, level, isNode) {
  
          var toBBox = this.toBBox,
              bbox = isNode ? item : toBBox(item),
              insertPath = [];
  
          // find the best node for accommodating the item, saving all nodes along the path too
          var node = this._chooseSubtree(bbox, this.data, level, insertPath);
  
          // put the item into the node
          node.children.push(item);
          extend(node, bbox);
  
          // split on node overflow; propagate upwards if necessary
          while (level >= 0) {
              if (insertPath[level].children.length > this._maxEntries) {
                  this._split(insertPath, level);
                  level--;
              } else break;
          }
  
          // adjust bboxes along the insertion path
          this._adjustParentBBoxes(bbox, insertPath, level);
      },
  
      // split overflowed node into two
      _split: function (insertPath, level) {
  
          var node = insertPath[level],
              M = node.children.length,
              m = this._minEntries;
  
          this._chooseSplitAxis(node, m, M);
  
          var splitIndex = this._chooseSplitIndex(node, m, M);
  
          var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
          newNode.height = node.height;
          newNode.leaf = node.leaf;
  
          calcBBox(node, this.toBBox);
          calcBBox(newNode, this.toBBox);
  
          if (level) insertPath[level - 1].children.push(newNode);
          else this._splitRoot(node, newNode);
      },
  
      _splitRoot: function (node, newNode) {
          // split root node
          this.data = createNode([node, newNode]);
          this.data.height = node.height + 1;
          this.data.leaf = false;
          calcBBox(this.data, this.toBBox);
      },
  
      _chooseSplitIndex: function (node, m, M) {
  
          var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
  
          minOverlap = minArea = Infinity;
  
          for (i = m; i <= M - m; i++) {
              bbox1 = distBBox(node, 0, i, this.toBBox);
              bbox2 = distBBox(node, i, M, this.toBBox);
  
              overlap = intersectionArea(bbox1, bbox2);
              area = bboxArea(bbox1) + bboxArea(bbox2);
  
              // choose distribution with minimum overlap
              if (overlap < minOverlap) {
                  minOverlap = overlap;
                  index = i;
  
                  minArea = area < minArea ? area : minArea;
  
              } else if (overlap === minOverlap) {
                  // otherwise choose distribution with minimum area
                  if (area < minArea) {
                      minArea = area;
                      index = i;
                  }
              }
          }
  
          return index;
      },
  
      // sorts node children by the best axis for split
      _chooseSplitAxis: function (node, m, M) {
  
          var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
              compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
              xMargin = this._allDistMargin(node, m, M, compareMinX),
              yMargin = this._allDistMargin(node, m, M, compareMinY);
  
          // if total distributions margin value is minimal for x, sort by minX,
          // otherwise it's already sorted by minY
          if (xMargin < yMargin) node.children.sort(compareMinX);
      },
  
      // total margin of all possible split distributions where each node is at least m full
      _allDistMargin: function (node, m, M, compare) {
  
          node.children.sort(compare);
  
          var toBBox = this.toBBox,
              leftBBox = distBBox(node, 0, m, toBBox),
              rightBBox = distBBox(node, M - m, M, toBBox),
              margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
              i, child;
  
          for (i = m; i < M - m; i++) {
              child = node.children[i];
              extend(leftBBox, node.leaf ? toBBox(child) : child);
              margin += bboxMargin(leftBBox);
          }
  
          for (i = M - m - 1; i >= m; i--) {
              child = node.children[i];
              extend(rightBBox, node.leaf ? toBBox(child) : child);
              margin += bboxMargin(rightBBox);
          }
  
          return margin;
      },
  
      _adjustParentBBoxes: function (bbox, path, level) {
          // adjust bboxes along the given tree path
          for (var i = level; i >= 0; i--) {
              extend(path[i], bbox);
          }
      },
  
      _condense: function (path) {
          // go through the path, removing empty nodes and updating bboxes
          for (var i = path.length - 1, siblings; i >= 0; i--) {
              if (path[i].children.length === 0) {
                  if (i > 0) {
                      siblings = path[i - 1].children;
                      siblings.splice(siblings.indexOf(path[i]), 1);
  
                  } else this.clear();
  
              } else calcBBox(path[i], this.toBBox);
          }
      },
  
      _initFormat: function (format) {
          // data format (minX, minY, maxX, maxY accessors)
  
          // uses eval-type function compilation instead of just accepting a toBBox function
          // because the algorithms are very sensitive to sorting functions performance,
          // so they should be dead simple and without inner calls
  
          var compareArr = ['return a', ' - b', ';'];
  
          this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
          this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
  
          this.toBBox = new Function('a',
              'return {minX: a' + format[0] +
              ', minY: a' + format[1] +
              ', maxX: a' + format[2] +
              ', maxY: a' + format[3] + '};');
      }
  };
  
  function findItem(item, items, equalsFn) {
      if (!equalsFn) return items.indexOf(item);
  
      for (var i = 0; i < items.length; i++) {
          if (equalsFn(item, items[i])) return i;
      }
      return -1;
  }
  
  // calculate node's bbox from bboxes of its children
  function calcBBox(node, toBBox) {
      distBBox(node, 0, node.children.length, toBBox, node);
  }
  
  // min bounding rectangle of node children from k to p-1
  function distBBox(node, k, p, toBBox, destNode) {
      if (!destNode) destNode = createNode(null);
      destNode.minX = Infinity;
      destNode.minY = Infinity;
      destNode.maxX = -Infinity;
      destNode.maxY = -Infinity;
  
      for (var i = k, child; i < p; i++) {
          child = node.children[i];
          extend(destNode, node.leaf ? toBBox(child) : child);
      }
  
      return destNode;
  }
  
  function extend(a, b) {
      a.minX = Math.min(a.minX, b.minX);
      a.minY = Math.min(a.minY, b.minY);
      a.maxX = Math.max(a.maxX, b.maxX);
      a.maxY = Math.max(a.maxY, b.maxY);
      return a;
  }
  
  function compareNodeMinX(a, b) { return a.minX - b.minX; }
  function compareNodeMinY(a, b) { return a.minY - b.minY; }
  
  function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
  function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
  
  function enlargedArea(a, b) {
      return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
             (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
  }
  
  function intersectionArea(a, b) {
      var minX = Math.max(a.minX, b.minX),
          minY = Math.max(a.minY, b.minY),
          maxX = Math.min(a.maxX, b.maxX),
          maxY = Math.min(a.maxY, b.maxY);
  
      return Math.max(0, maxX - minX) *
             Math.max(0, maxY - minY);
  }
  
  function contains(a, b) {
      return a.minX <= b.minX &&
             a.minY <= b.minY &&
             b.maxX <= a.maxX &&
             b.maxY <= a.maxY;
  }
  
  function intersects(a, b) {
      return b.minX <= a.maxX &&
             b.minY <= a.maxY &&
             b.maxX >= a.minX &&
             b.maxY >= a.minY;
  }
  
  function createNode(children) {
      return {
          children: children,
          height: 1,
          leaf: true,
          minX: Infinity,
          minY: Infinity,
          maxX: -Infinity,
          maxY: -Infinity
      };
  }
  
  // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
  // combines selection algorithm with binary divide & conquer approach
  
  function multiSelect(arr, left, right, n, compare) {
      var stack = [left, right],
          mid;
  
      while (stack.length) {
          right = stack.pop();
          left = stack.pop();
  
          if (right - left <= n) continue;
  
          mid = left + Math.ceil((right - left) / n / 2) * n;
          quickselect(arr, mid, left, right, compare);
  
          stack.push(left, mid, mid, right);
      }
  }
  
  
  /***/ }),
  
  /***/ "./node_modules/robust-orientation/orientation.js":
  /*!********************************************************!*\
    !*** ./node_modules/robust-orientation/orientation.js ***!
    \********************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var twoProduct = __webpack_require__(/*! two-product */ "./node_modules/two-product/two-product.js")
  var robustSum = __webpack_require__(/*! robust-sum */ "./node_modules/robust-sum/robust-sum.js")
  var robustScale = __webpack_require__(/*! robust-scale */ "./node_modules/robust-scale/robust-scale.js")
  var robustSubtract = __webpack_require__(/*! robust-subtract */ "./node_modules/robust-subtract/robust-diff.js")
  
  var NUM_EXPAND = 5
  
  var EPSILON     = 1.1102230246251565e-16
  var ERRBOUND3   = (3.0 + 16.0 * EPSILON) * EPSILON
  var ERRBOUND4   = (7.0 + 56.0 * EPSILON) * EPSILON
  
  function cofactor(m, c) {
    var result = new Array(m.length-1)
    for(var i=1; i<m.length; ++i) {
      var r = result[i-1] = new Array(m.length-1)
      for(var j=0,k=0; j<m.length; ++j) {
        if(j === c) {
          continue
        }
        r[k++] = m[i][j]
      }
    }
    return result
  }
  
  function matrix(n) {
    var result = new Array(n)
    for(var i=0; i<n; ++i) {
      result[i] = new Array(n)
      for(var j=0; j<n; ++j) {
        result[i][j] = ["m", j, "[", (n-i-1), "]"].join("")
      }
    }
    return result
  }
  
  function sign(n) {
    if(n & 1) {
      return "-"
    }
    return ""
  }
  
  function generateSum(expr) {
    if(expr.length === 1) {
      return expr[0]
    } else if(expr.length === 2) {
      return ["sum(", expr[0], ",", expr[1], ")"].join("")
    } else {
      var m = expr.length>>1
      return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("")
    }
  }
  
  function determinant(m) {
    if(m.length === 2) {
      return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")]
    } else {
      var expr = []
      for(var i=0; i<m.length; ++i) {
        expr.push(["scale(", generateSum(determinant(cofactor(m, i))), ",", sign(i), m[0][i], ")"].join(""))
      }
      return expr
    }
  }
  
  function orientation(n) {
    var pos = []
    var neg = []
    var m = matrix(n)
    var args = []
    for(var i=0; i<n; ++i) {
      if((i&1)===0) {
        pos.push.apply(pos, determinant(cofactor(m, i)))
      } else {
        neg.push.apply(neg, determinant(cofactor(m, i)))
      }
      args.push("m" + i)
    }
    var posExpr = generateSum(pos)
    var negExpr = generateSum(neg)
    var funcName = "orientation" + n + "Exact"
    var code = ["function ", funcName, "(", args.join(), "){var p=", posExpr, ",n=", negExpr, ",d=sub(p,n);\
  return d[d.length-1];};return ", funcName].join("")
    var proc = new Function("sum", "prod", "scale", "sub", code)
    return proc(robustSum, twoProduct, robustScale, robustSubtract)
  }
  
  var orientation3Exact = orientation(3)
  var orientation4Exact = orientation(4)
  
  var CACHED = [
    function orientation0() { return 0 },
    function orientation1() { return 0 },
    function orientation2(a, b) { 
      return b[0] - a[0]
    },
    function orientation3(a, b, c) {
      var l = (a[1] - c[1]) * (b[0] - c[0])
      var r = (a[0] - c[0]) * (b[1] - c[1])
      var det = l - r
      var s
      if(l > 0) {
        if(r <= 0) {
          return det
        } else {
          s = l + r
        }
      } else if(l < 0) {
        if(r >= 0) {
          return det
        } else {
          s = -(l + r)
        }
      } else {
        return det
      }
      var tol = ERRBOUND3 * s
      if(det >= tol || det <= -tol) {
        return det
      }
      return orientation3Exact(a, b, c)
    },
    function orientation4(a,b,c,d) {
      var adx = a[0] - d[0]
      var bdx = b[0] - d[0]
      var cdx = c[0] - d[0]
      var ady = a[1] - d[1]
      var bdy = b[1] - d[1]
      var cdy = c[1] - d[1]
      var adz = a[2] - d[2]
      var bdz = b[2] - d[2]
      var cdz = c[2] - d[2]
      var bdxcdy = bdx * cdy
      var cdxbdy = cdx * bdy
      var cdxady = cdx * ady
      var adxcdy = adx * cdy
      var adxbdy = adx * bdy
      var bdxady = bdx * ady
      var det = adz * (bdxcdy - cdxbdy) 
              + bdz * (cdxady - adxcdy)
              + cdz * (adxbdy - bdxady)
      var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz)
                    + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz)
                    + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz)
      var tol = ERRBOUND4 * permanent
      if ((det > tol) || (-det > tol)) {
        return det
      }
      return orientation4Exact(a,b,c,d)
    }
  ]
  
  function slowOrient(args) {
    var proc = CACHED[args.length]
    if(!proc) {
      proc = CACHED[args.length] = orientation(args.length)
    }
    return proc.apply(undefined, args)
  }
  
  function generateOrientationProc() {
    while(CACHED.length <= NUM_EXPAND) {
      CACHED.push(orientation(CACHED.length))
    }
    var args = []
    var procArgs = ["slow"]
    for(var i=0; i<=NUM_EXPAND; ++i) {
      args.push("a" + i)
      procArgs.push("o" + i)
    }
    var code = [
      "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;"
    ]
    for(var i=2; i<=NUM_EXPAND; ++i) {
      code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");")
    }
    code.push("}var s=new Array(arguments.length);for(var i=0;i<arguments.length;++i){s[i]=arguments[i]};return slow(s);}return getOrientation")
    procArgs.push(code.join(""))
  
    var proc = Function.apply(undefined, procArgs)
    module.exports = proc.apply(undefined, [slowOrient].concat(CACHED))
    for(var i=0; i<=NUM_EXPAND; ++i) {
      module.exports[i] = CACHED[i]
    }
  }
  
  generateOrientationProc()
  
  /***/ }),
  
  /***/ "./node_modules/robust-scale/robust-scale.js":
  /*!***************************************************!*\
    !*** ./node_modules/robust-scale/robust-scale.js ***!
    \***************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var twoProduct = __webpack_require__(/*! two-product */ "./node_modules/two-product/two-product.js")
  var twoSum = __webpack_require__(/*! two-sum */ "./node_modules/two-sum/two-sum.js")
  
  module.exports = scaleLinearExpansion
  
  function scaleLinearExpansion(e, scale) {
    var n = e.length
    if(n === 1) {
      var ts = twoProduct(e[0], scale)
      if(ts[0]) {
        return ts
      }
      return [ ts[1] ]
    }
    var g = new Array(2 * n)
    var q = [0.1, 0.1]
    var t = [0.1, 0.1]
    var count = 0
    twoProduct(e[0], scale, q)
    if(q[0]) {
      g[count++] = q[0]
    }
    for(var i=1; i<n; ++i) {
      twoProduct(e[i], scale, t)
      var pq = q[1]
      twoSum(pq, t[0], q)
      if(q[0]) {
        g[count++] = q[0]
      }
      var a = t[1]
      var b = q[1]
      var x = a + b
      var bv = x - a
      var y = b - bv
      q[1] = x
      if(y) {
        g[count++] = y
      }
    }
    if(q[1]) {
      g[count++] = q[1]
    }
    if(count === 0) {
      g[count++] = 0.0
    }
    g.length = count
    return g
  }
  
  /***/ }),
  
  /***/ "./node_modules/robust-subtract/robust-diff.js":
  /*!*****************************************************!*\
    !*** ./node_modules/robust-subtract/robust-diff.js ***!
    \*****************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = robustSubtract
  
  //Easy case: Add two scalars
  function scalarScalar(a, b) {
    var x = a + b
    var bv = x - a
    var av = x - bv
    var br = b - bv
    var ar = a - av
    var y = ar + br
    if(y) {
      return [y, x]
    }
    return [x]
  }
  
  function robustSubtract(e, f) {
    var ne = e.length|0
    var nf = f.length|0
    if(ne === 1 && nf === 1) {
      return scalarScalar(e[0], -f[0])
    }
    var n = ne + nf
    var g = new Array(n)
    var count = 0
    var eptr = 0
    var fptr = 0
    var abs = Math.abs
    var ei = e[eptr]
    var ea = abs(ei)
    var fi = -f[fptr]
    var fa = abs(fi)
    var a, b
    if(ea < fa) {
      b = ei
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
        ea = abs(ei)
      }
    } else {
      b = fi
      fptr += 1
      if(fptr < nf) {
        fi = -f[fptr]
        fa = abs(fi)
      }
    }
    if((eptr < ne && ea < fa) || (fptr >= nf)) {
      a = ei
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
        ea = abs(ei)
      }
    } else {
      a = fi
      fptr += 1
      if(fptr < nf) {
        fi = -f[fptr]
        fa = abs(fi)
      }
    }
    var x = a + b
    var bv = x - a
    var y = b - bv
    var q0 = y
    var q1 = x
    var _x, _bv, _av, _br, _ar
    while(eptr < ne && fptr < nf) {
      if(ea < fa) {
        a = ei
        eptr += 1
        if(eptr < ne) {
          ei = e[eptr]
          ea = abs(ei)
        }
      } else {
        a = fi
        fptr += 1
        if(fptr < nf) {
          fi = -f[fptr]
          fa = abs(fi)
        }
      }
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      }
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
    }
    while(eptr < ne) {
      a = ei
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      }
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
      }
    }
    while(fptr < nf) {
      a = fi
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      } 
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
      fptr += 1
      if(fptr < nf) {
        fi = -f[fptr]
      }
    }
    if(q0) {
      g[count++] = q0
    }
    if(q1) {
      g[count++] = q1
    }
    if(!count) {
      g[count++] = 0.0  
    }
    g.length = count
    return g
  }
  
  /***/ }),
  
  /***/ "./node_modules/robust-sum/robust-sum.js":
  /*!***********************************************!*\
    !*** ./node_modules/robust-sum/robust-sum.js ***!
    \***********************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = linearExpansionSum
  
  //Easy case: Add two scalars
  function scalarScalar(a, b) {
    var x = a + b
    var bv = x - a
    var av = x - bv
    var br = b - bv
    var ar = a - av
    var y = ar + br
    if(y) {
      return [y, x]
    }
    return [x]
  }
  
  function linearExpansionSum(e, f) {
    var ne = e.length|0
    var nf = f.length|0
    if(ne === 1 && nf === 1) {
      return scalarScalar(e[0], f[0])
    }
    var n = ne + nf
    var g = new Array(n)
    var count = 0
    var eptr = 0
    var fptr = 0
    var abs = Math.abs
    var ei = e[eptr]
    var ea = abs(ei)
    var fi = f[fptr]
    var fa = abs(fi)
    var a, b
    if(ea < fa) {
      b = ei
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
        ea = abs(ei)
      }
    } else {
      b = fi
      fptr += 1
      if(fptr < nf) {
        fi = f[fptr]
        fa = abs(fi)
      }
    }
    if((eptr < ne && ea < fa) || (fptr >= nf)) {
      a = ei
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
        ea = abs(ei)
      }
    } else {
      a = fi
      fptr += 1
      if(fptr < nf) {
        fi = f[fptr]
        fa = abs(fi)
      }
    }
    var x = a + b
    var bv = x - a
    var y = b - bv
    var q0 = y
    var q1 = x
    var _x, _bv, _av, _br, _ar
    while(eptr < ne && fptr < nf) {
      if(ea < fa) {
        a = ei
        eptr += 1
        if(eptr < ne) {
          ei = e[eptr]
          ea = abs(ei)
        }
      } else {
        a = fi
        fptr += 1
        if(fptr < nf) {
          fi = f[fptr]
          fa = abs(fi)
        }
      }
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      }
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
    }
    while(eptr < ne) {
      a = ei
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      }
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
      eptr += 1
      if(eptr < ne) {
        ei = e[eptr]
      }
    }
    while(fptr < nf) {
      a = fi
      b = q0
      x = a + b
      bv = x - a
      y = b - bv
      if(y) {
        g[count++] = y
      } 
      _x = q1 + x
      _bv = _x - q1
      _av = _x - _bv
      _br = x - _bv
      _ar = q1 - _av
      q0 = _ar + _br
      q1 = _x
      fptr += 1
      if(fptr < nf) {
        fi = f[fptr]
      }
    }
    if(q0) {
      g[count++] = q0
    }
    if(q1) {
      g[count++] = q1
    }
    if(!count) {
      g[count++] = 0.0  
    }
    g.length = count
    return g
  }
  
  /***/ }),
  
  /***/ "./node_modules/two-product/two-product.js":
  /*!*************************************************!*\
    !*** ./node_modules/two-product/two-product.js ***!
    \*************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = twoProduct
  
  var SPLITTER = +(Math.pow(2, 27) + 1.0)
  
  function twoProduct(a, b, result) {
    var x = a * b
  
    var c = SPLITTER * a
    var abig = c - a
    var ahi = c - abig
    var alo = a - ahi
  
    var d = SPLITTER * b
    var bbig = d - b
    var bhi = d - bbig
    var blo = b - bhi
  
    var err1 = x - (ahi * bhi)
    var err2 = err1 - (alo * bhi)
    var err3 = err2 - (ahi * blo)
  
    var y = alo * blo - err3
  
    if(result) {
      result[0] = y
      result[1] = x
      return result
    }
  
    return [ y, x ]
  }
  
  /***/ }),
  
  /***/ "./node_modules/two-sum/two-sum.js":
  /*!*****************************************!*\
    !*** ./node_modules/two-sum/two-sum.js ***!
    \*****************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = fastTwoSum
  
  function fastTwoSum(a, b, result) {
  	var x = a + b
  	var bv = x - a
  	var av = x - bv
  	var br = b - bv
  	var ar = a - av
  	if(result) {
  		result[0] = ar + br
  		result[1] = x
  		return result
  	}
  	return [ar+br, x]
  }
  
  /***/ }),
  
  /***/ "./node_modules/util/node_modules/inherits/inherits_browser.js":
  /*!*********************************************************************!*\
    !*** ./node_modules/util/node_modules/inherits/inherits_browser.js ***!
    \*********************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  
  /***/ }),
  
  /***/ "./node_modules/util/support/isBufferBrowser.js":
  /*!******************************************************!*\
    !*** ./node_modules/util/support/isBufferBrowser.js ***!
    \******************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  
  /***/ }),
  
  /***/ "./node_modules/util/util.js":
  /*!***********************************!*\
    !*** ./node_modules/util/util.js ***!
    \***********************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors ||
    function getOwnPropertyDescriptors(obj) {
      var keys = Object.keys(obj);
      var descriptors = {};
      for (var i = 0; i < keys.length; i++) {
        descriptors[keys[i]] = Object.getOwnPropertyDescriptor(obj, keys[i]);
      }
      return descriptors;
    };
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    if (typeof process !== 'undefined' && process.noDeprecation === true) {
      return fn;
    }
  
    // Allow for deprecating things in the process of starting up.
    if (typeof process === 'undefined') {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = __webpack_require__(/*! ./support/isBuffer */ "./node_modules/util/support/isBufferBrowser.js");
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = __webpack_require__(/*! inherits */ "./node_modules/util/node_modules/inherits/inherits_browser.js");
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  var kCustomPromisifiedSymbol = typeof Symbol !== 'undefined' ? Symbol('util.promisify.custom') : undefined;
  
  exports.promisify = function promisify(original) {
    if (typeof original !== 'function')
      throw new TypeError('The "original" argument must be of type Function');
  
    if (kCustomPromisifiedSymbol && original[kCustomPromisifiedSymbol]) {
      var fn = original[kCustomPromisifiedSymbol];
      if (typeof fn !== 'function') {
        throw new TypeError('The "util.promisify.custom" argument must be of type Function');
      }
      Object.defineProperty(fn, kCustomPromisifiedSymbol, {
        value: fn, enumerable: false, writable: false, configurable: true
      });
      return fn;
    }
  
    function fn() {
      var promiseResolve, promiseReject;
      var promise = new Promise(function (resolve, reject) {
        promiseResolve = resolve;
        promiseReject = reject;
      });
  
      var args = [];
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      args.push(function (err, value) {
        if (err) {
          promiseReject(err);
        } else {
          promiseResolve(value);
        }
      });
  
      try {
        original.apply(this, args);
      } catch (err) {
        promiseReject(err);
      }
  
      return promise;
    }
  
    Object.setPrototypeOf(fn, Object.getPrototypeOf(original));
  
    if (kCustomPromisifiedSymbol) Object.defineProperty(fn, kCustomPromisifiedSymbol, {
      value: fn, enumerable: false, writable: false, configurable: true
    });
    return Object.defineProperties(
      fn,
      getOwnPropertyDescriptors(original)
    );
  }
  
  exports.promisify.custom = kCustomPromisifiedSymbol
  
  function callbackifyOnRejected(reason, cb) {
    // `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
    // Because `null` is a special error value in callbacks which means "no error
    // occurred", we error-wrap so the callback consumer can distinguish between
    // "the promise rejected with null" or "the promise fulfilled with undefined".
    if (!reason) {
      var newReason = new Error('Promise was rejected with a falsy value');
      newReason.reason = reason;
      reason = newReason;
    }
    return cb(reason);
  }
  
  function callbackify(original) {
    if (typeof original !== 'function') {
      throw new TypeError('The "original" argument must be of type Function');
    }
  
    // We DO NOT return the promise as it gives the user a false sense that
    // the promise is actually somehow related to the callback's execution
    // and that the callback throwing will reject the promise.
    function callbackified() {
      var args = [];
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
  
      var maybeCb = args.pop();
      if (typeof maybeCb !== 'function') {
        throw new TypeError('The last argument must be of type Function');
      }
      var self = this;
      var cb = function() {
        return maybeCb.apply(self, arguments);
      };
      // In true node style we process the callback on `nextTick` with all the
      // implications (stack, `uncaughtException`, `async_hooks`)
      original.apply(this, args)
        .then(function(ret) { process.nextTick(cb, null, ret) },
              function(rej) { process.nextTick(callbackifyOnRejected, rej, cb) });
    }
  
    Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
    Object.defineProperties(callbackified,
                            getOwnPropertyDescriptors(original));
    return callbackified;
  }
  exports.callbackify = callbackify;
  
  /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../process/browser.js */ "./node_modules/process/browser.js")))
  
  /***/ }),
  
  /***/ "./src/components/workers/worker_cluster.tsx":
  /*!***************************************************!*\
    !*** ./src/components/workers/worker_cluster.tsx ***!
    \***************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
  
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  
  function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
  
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var concaveman = __webpack_require__(/*! concaveman */ "./node_modules/concaveman/index.js");
  
  var libtess = __webpack_require__(/*! libtess */ "./node_modules/libtess/libtess.min.js");
  
  var util_1 = __webpack_require__(/*! util */ "./node_modules/util/util.js");
  
  var backend_utils = __webpack_require__(/*! ../../utils/backend-connect */ "./src/utils/backend-connect.ts");
  /*global libtess */
  
  /* exported triangulate */
  
  
  var tessy = function initTesselator() {
    // function called for each vertex of tesselator output
    function vertexCallback(data, polyVertArray) {
      // console.log(data[0], data[1]);
      polyVertArray[polyVertArray.length] = data[0];
      polyVertArray[polyVertArray.length] = data[1];
    }
  
    function begincallback(type) {
      if (type !== libtess.primitiveType.GL_TRIANGLES) {
        console.log('expected TRIANGLES but got type: ' + type);
      }
    }
  
    function errorcallback(errno) {
      console.log('error callback');
      console.log('error number: ' + errno);
    } // callback for when segments intersect and must be split
  
  
    function combinecallback(coords, data, weight) {
      // console.log('combine callback');
      return [coords[0], coords[1], coords[2]];
    }
  
    function edgeCallback(flag) {// don't really care about the flag, but need no-strip/no-fan behavior
      // console.log('edge flag: ' + flag);
    }
  
    var tessy = new libtess.GluTesselator(); // tessy.gluTessProperty(libtess.gluEnum.GLU_TESS_WINDING_RULE, libtess.windingRule.GLU_TESS_WINDING_POSITIVE);
  
    tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_VERTEX_DATA, vertexCallback);
    tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_BEGIN, begincallback);
    tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_ERROR, errorcallback);
    tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_COMBINE, combinecallback);
    tessy.gluTessCallback(libtess.gluEnum.GLU_TESS_EDGE_FLAG, edgeCallback);
    return tessy;
  }();
  
  function triangulate(contours) {
    // libtess will take 3d verts and flatten to a plane for tesselation
    // since only doing 2d tesselation here, provide z=1 normal to skip
    // iterating over verts only to get the same answer.
    // comment out to test normal-generation code
    tessy.gluTessNormal(0, 0, 1);
    var triangleVerts = [];
    tessy.gluTessBeginPolygon(triangleVerts);
  
    for (var i = 0; i < contours.length; i++) {
      tessy.gluTessBeginContour();
      var contour = contours[i];
  
      for (var j = 0; j < contour.length; j += 2) {
        var coords = [contour[j], contour[j + 1], 0];
        tessy.gluTessVertex(coords, coords);
      }
  
      tessy.gluTessEndContour();
    } // finish polygon (and time triangulation process)
  
  
    var startTime = new Date().getTime();
    tessy.gluTessEndPolygon();
    var endTime = new Date().getTime();
    return triangleVerts;
  }
  /**
   * Create cluster structures from raw data.
   */
  
  
  function processClusters(raw, xy) {
    var clusters = {};
    raw.forEach(function (entry, index) {
      var x = xy[index][0];
      var y = xy[index][1];
  
      var _entry = _slicedToArray(entry, 3),
          label = _entry[0],
          probability = _entry[1],
          score = _entry[2];
  
      if (!(label in clusters)) {
        clusters[label] = {
          points: []
        };
      }
  
      clusters[label].points.push({
        label: label,
        probability: probability,
        meshIndex: index,
        x: x,
        y: y,
        score: score
      });
    });
    return clusters;
  }
  
  function validKey(key) {
    if (util_1.isNumber(key) && key < 0) {
      return false;
    }
  
    return true;
  }
  /**
   * Clustering endpoint that
   */
  
  
  self.addEventListener('message', function (e) {
    if (e.data.type == 'point') {
      var xy = e.data.load;
      fetch(backend_utils.BASE_URL + '/hdbscan', {
        method: 'POST',
        body: JSON.stringify(xy)
      }).then(function (response) {
        response.json().then(function (values) {
          // Get clusters
          var clusters = processClusters(values.result, xy);
          Object.keys(clusters).forEach(function (key) {
            if (!validKey(key)) return;
            var cluster = clusters[key];
            var bounds = {
              minX: 10000,
              maxX: -10000,
              minY: 10000,
              maxY: -10000
            };
            cluster.bounds = bounds;
            var pts = cluster.points.filter(function (e) {
              return e.probability > 0.7;
            }).map(function (e) {
              var x = xy[e.meshIndex][0];
              var y = xy[e.meshIndex][1];
              if (x < bounds.minX) bounds.minX = x;
              if (x > bounds.maxX) bounds.maxX = x;
              if (y < bounds.minY) bounds.minY = y;
              if (y > bounds.maxY) bounds.maxY = y;
              return [x, y];
            }); // Get hull of cluster
  
            var polygon = concaveman(pts); // Get triangulated hull for cluster
  
            var triangulated = triangulate([polygon.flat()]);
            cluster.hull = polygon;
            cluster.triangulation = triangulated;
          });
          var context = self;
          context.postMessage(clusters);
        });
      });
    } else if (e.data.type == 'segment') {
      var xy = e.data.load;
      fetch(backend_utils.BASE_URL + '/segmentation', {
        method: 'POST',
        body: JSON.stringify(xy)
      }).then(function (response) {
        var context = self;
        response.json().then(function (values) {
          context.postMessage(values);
        });
      });
    } else if (e.data.type == 'extract') {
      // From input data [ [label], [label]... ] generate the clusters with triangulation
      var clusters = {};
      e.data.message.forEach(function (vector, index) {
        var _vector = _slicedToArray(vector, 3),
            x = _vector[0],
            y = _vector[1],
            labels = _vector[2];
  
        labels.forEach(function (label) {
          // If we have a new
          if (!(label in clusters)) {
            clusters[label] = {
              points: []
            };
          }
  
          clusters[label].points.push({
            label: label,
            probability: 1.0,
            meshIndex: index,
            x: x,
            y: y
          });
        });
      });
      Object.keys(clusters).forEach(function (key) {
        if (!validKey(key)) return;
        var cluster = clusters[key];
        var bounds = {
          minX: 10000,
          maxX: -10000,
          minY: 10000,
          maxY: -10000
        };
        cluster.bounds = bounds;
        var pts = cluster.points.map(function (point) {
          var x = point.x;
          var y = point.y;
          if (x < bounds.minX) bounds.minX = x;
          if (x > bounds.maxX) bounds.maxX = x;
          if (y < bounds.minY) bounds.minY = y;
          if (y > bounds.maxY) bounds.maxY = y;
          return [x, y];
        }); // Get hull of cluster
  
        var polygon = concaveman(pts); // Get triangulated hull for cluster
  
        var triangulated = triangulate([polygon.flat()]);
        cluster.hull = polygon;
        cluster.triangulation = triangulated;
      });
      var context = self;
      context.postMessage(clusters);
    }
  }); // OLD code that uses C++ and WebAssembly, only here for completeness
  
  /**self.importScripts('test.js')
  
  
  self.addEventListener('message', function (e) {
  
      var sab = e.data
      const vectorArray = new Float32Array(sab)
  
      var nVec = vectorArray.length / 2
  
  
      // Allocate some space in the heap for the data (making sure to use the appropriate memory size of the elements)
      var buffer = Module._malloc(vectorArray.length * vectorArray.BYTES_PER_ELEMENT)
  
      // Output buffer for labels
      var outLabel = Module._malloc(nVec * 4)
  
      // Output buffer for probabilities
      var outProbs = Module._malloc(nVec * 4)
  
      // Assign the data to the heap - Keep in mind bytes per element
      Module.HEAPF32.set(vectorArray, buffer >> 2)
  
      // Finally, call the function with "number" parameter type for the array (the pointer), and an extra length parameter
      var js_wrapped_fib = Module.cwrap("cluster", "number", ["number", "number", "number", "number", "number", "number"]);
      console.log("STARTING")
      js_wrapped_fib(buffer, vectorArray.length, outLabel, nVec, outProbs, nVec)
  
      var labels = Module.HEAP32.subarray(outLabel / 4, outLabel / 4 + nVec)
      var probabilities = Module.HEAPF32.subarray(outProbs / 4, outProbs / 4 + nVec)
  
      self.postMessage({
          labels: labels,
          probabilities: probabilities
      })
  })**/
  
  /***/ }),
  
  /***/ "./src/utils/backend-connect.ts":
  /*!**************************************!*\
    !*** ./src/utils/backend-connect.ts ***!
    \**************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
   // CONSTANTS
  
  var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.calculate_hdbscan_clusters = exports.get_representation_list = exports.upload_sdf_file = exports.get_substructure_count = exports.get_mcs_from_smiles_list = exports.get_structures_from_smiles_list = exports.get_structure_from_smiles = exports.get_difference_highlight = exports.get_uploaded_files = exports.delete_file = exports.BASE_URL = exports.CREDENTIALS = void 0; // export const CREDENTIALS = 'include'; // for AWS/docker
  
  exports.CREDENTIALS = 'omit'; // for netlify/local
  
  exports.BASE_URL = 'https://cime.caleydoapp.org'; // for netlify
  // export const BASE_URL = 'http://127.0.0.1:8080'; // for local
  // export const BASE_URL = ''; // for AWS/docker
  
  var smiles_cache = {};
  var smiles_highlight_cache = {};
  
  function handleSmilesCache(smiles) {
    var highlight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  
    //already downloaded this image -> saved in smiles cache
    if (highlight) {
      return smiles_highlight_cache[smiles];
    } else {
      return smiles_cache[smiles];
    }
  }
  
  function setSmilesCache(smiles) {
    var highlight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
    var data = arguments.length > 2 ? arguments[2] : undefined;
    if (highlight) smiles_highlight_cache[smiles] = data;else smiles_cache[smiles] = data;
  }
  
  function async_cache(cached_data) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee() {
      return regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              return _context.abrupt("return", cached_data);
  
            case 1:
            case "end":
              return _context.stop();
          }
        }
      }, _callee);
    }));
  }
  
  var cache = {};
  
  function handleCache(key) {
    if (cache[key]) return Object.assign(cache[key]); // return copy of cached object
  
    return null;
  }
  
  function setCache(key, value) {
    cache[key] = value;
  }
  
  function handle_errors(response) {
    if (!response.ok) {
      throw Error(response.statusText);
    }
  
    return response;
  }
  
  function handle_errors_json(data) {
    if (Object.keys(data).includes("error")) {
      alert(data["error"]);
    }
  
    return data;
  }
  
  function delete_file(filename) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee2() {
      var path;
      return regeneratorRuntime.wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              path = exports.BASE_URL + '/delete_file/' + filename;
              return _context2.abrupt("return", fetch(path, {
                method: 'GET',
                credentials: exports.CREDENTIALS
              }).then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).catch(function (error) {
                alert("file could not be deleted. please, try again");
                console.log(error);
              }));
  
            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2);
    }));
  }
  
  exports.delete_file = delete_file;
  
  function get_uploaded_files() {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee3() {
      var path;
      return regeneratorRuntime.wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              path = exports.BASE_URL + '/get_uploaded_files_list';
              return _context3.abrupt("return", fetch(path, {
                method: 'GET',
                credentials: exports.CREDENTIALS
              }).then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).catch(function (error) {
                // alert("could not load uploaded filenames.")
                console.log(error);
              }));
  
            case 2:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3);
    }));
  }
  
  exports.get_uploaded_files = get_uploaded_files;
  
  function get_difference_highlight(smilesA, smilesB) {
    var controller = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
      var formData, path, my_fetch;
      return regeneratorRuntime.wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              formData = new FormData();
              formData.append('smilesA', smilesA);
              formData.append('smilesB', smilesB);
              path = exports.BASE_URL + '/get_difference_highlight';
              my_fetch = null;
  
              if (controller) {
                my_fetch = fetch(path, {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS,
                  signal: controller.signal
                });
              } else {
                my_fetch = fetch(path, {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS
                });
              }
  
              return _context4.abrupt("return", my_fetch.then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                console.log(data);
                return data["data"];
              }).catch(function (error) {
                // alert("could not load structure");
                console.log(error);
              }));
  
            case 7:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4);
    }));
  }
  
  exports.get_difference_highlight = get_difference_highlight;
  
  function get_structure_from_smiles(smiles) {
    var highlight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
    var controller = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
      var cached_data, formData, path, my_fetch;
      return regeneratorRuntime.wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              cached_data = handleSmilesCache(smiles, highlight);
  
              if (!cached_data) {
                _context5.next = 3;
                break;
              }
  
              return _context5.abrupt("return", async_cache(cached_data));
  
            case 3:
              formData = new FormData();
              formData.append('smiles', smiles);
              if (localStorage.getItem("unique_filename")) formData.append('filename', localStorage.getItem("unique_filename"));
              path = exports.BASE_URL + '/get_mol_img';
  
              if (highlight) {
                path += "/highlight";
              }
  
              my_fetch = null;
  
              if (controller) {
                my_fetch = fetch(path, {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS,
                  signal: controller.signal
                });
              } else {
                my_fetch = fetch(path, {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS
                });
              }
  
              return _context5.abrupt("return", my_fetch.then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                setSmilesCache(smiles, highlight, data["data"]);
                return data["data"];
              }).catch(function (error) {
                // alert("could not load structure");
                console.log(error);
              }));
  
            case 11:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5);
    }));
  }
  
  exports.get_structure_from_smiles = get_structure_from_smiles;
  
  function get_structures_from_smiles_list(formData, controller) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee6() {
      var my_fetch;
      return regeneratorRuntime.wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              if (localStorage.getItem("unique_filename")) formData.append('filename', localStorage.getItem("unique_filename"));
              my_fetch = null;
  
              if (controller) {
                my_fetch = fetch(exports.BASE_URL + '/get_mol_imgs', {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS,
                  signal: controller === null || controller === void 0 ? void 0 : controller.signal
                });
              } else {
                my_fetch = fetch(exports.BASE_URL + '/get_mol_imgs', {
                  method: 'POST',
                  body: formData,
                  credentials: exports.CREDENTIALS
                });
              }
  
              return _context6.abrupt("return", my_fetch.then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                if (data["error_smiles"].length > 0) {
                  alert("following smiles couldn not be parsed: " + data["error_smiles"]);
                }
  
                return data;
              }).catch(function (error) {
                if (error.name === 'AbortError') {
                  console.log('Fetch aborted');
                } else {
                  alert("could not load structures");
                  console.log(error);
                }
              }));
  
            case 4:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6);
    }));
  }
  
  exports.get_structures_from_smiles_list = get_structures_from_smiles_list;
  
  function get_mcs_from_smiles_list(formData, controller) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee7() {
      var my_fetch;
      return regeneratorRuntime.wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              my_fetch = null;
  
              if (controller) {
                my_fetch = fetch(exports.BASE_URL + '/get_common_mol_img', {
                  method: 'POST',
                  body: formData,
                  signal: controller === null || controller === void 0 ? void 0 : controller.signal
                });
              } else {
                my_fetch = fetch(exports.BASE_URL + '/get_common_mol_img', {
                  method: 'POST',
                  body: formData
                });
              }
  
              return _context7.abrupt("return", my_fetch.then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (response) {
                return response["data"];
              }).catch(function (error) {
                // alert("could not get maximum common substructure")
                console.log(error);
              }));
  
            case 3:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7);
    }));
  }
  
  exports.get_mcs_from_smiles_list = get_mcs_from_smiles_list;
  
  function get_substructure_count(smiles_list, filter) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee8() {
      var formData;
      return regeneratorRuntime.wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              formData = new FormData();
              formData.append('smiles_list', smiles_list);
              formData.append('filter_smiles', filter);
              return _context8.abrupt("return", fetch(exports.BASE_URL + '/get_substructure_count', {
                method: 'POST',
                body: formData
              }).then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                if (Object.keys(data).includes("substructure_counts")) return data["substructure_counts"];else throw Error("Backend responded with error: " + data["error"]);
              }).catch(function (error) {
                alert("could not find substructure match");
                console.log(error);
              }));
  
            case 4:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8);
    }));
  }
  
  exports.get_substructure_count = get_substructure_count;
  
  function upload_sdf_file(file, controller) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee9() {
      var formData_file, promise;
      return regeneratorRuntime.wrap(function _callee9$(_context9) {
        while (1) {
          switch (_context9.prev = _context9.next) {
            case 0:
              // upload the sdf file to the server
              // the response is a unique filename that can be used to make further requests
              formData_file = new FormData();
              formData_file.append('myFile', file);
              formData_file.append('file_size', file.size);
              promise = fetch(exports.BASE_URL + '/upload_sdf', {
                method: 'POST',
                body: formData_file,
                credentials: exports.CREDENTIALS,
                signal: controller === null || controller === void 0 ? void 0 : controller.signal
              }).then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                localStorage.setItem("unique_filename", data["unique_filename"]);
              }).catch(function (error) {
                if (error.name === 'AbortError') {
                  console.log('Fetch aborted');
                } else {
                  alert("error when uploading file. it might be too big");
                  console.log(error);
                }
              });
              return _context9.abrupt("return", promise);
  
            case 5:
            case "end":
              return _context9.stop();
          }
        }
      }, _callee9);
    }));
  }
  
  exports.upload_sdf_file = upload_sdf_file;
  
  function get_representation_list() {
    var refresh = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
    var dataset_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
    var controller = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee10() {
      var cached_data, path, my_fetch;
      return regeneratorRuntime.wrap(function _callee10$(_context10) {
        while (1) {
          switch (_context10.prev = _context10.next) {
            case 0:
              if (refresh) {
                _context10.next = 4;
                break;
              }
  
              cached_data = handleCache("representation_list_" + dataset_name);
  
              if (!(cached_data && cached_data["rep_list"].length > 0)) {
                _context10.next = 4;
                break;
              }
  
              return _context10.abrupt("return", async_cache(cached_data));
  
            case 4:
              path = exports.BASE_URL + '/get_atom_rep_list';
              if (localStorage.getItem("unique_filename")) path += "/" + localStorage.getItem("unique_filename");
              my_fetch = null;
  
              if (controller) {
                my_fetch = fetch(path, {
                  method: 'GET',
                  credentials: exports.CREDENTIALS,
                  signal: controller.signal
                });
              } else {
                my_fetch = fetch(path, {
                  method: 'GET',
                  credentials: exports.CREDENTIALS
                });
              }
  
              return _context10.abrupt("return", my_fetch.then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).then(function (data) {
                setCache("representation_list_" + dataset_name, data);
                return data;
              }).catch(function (error) {
                // alert("error when loading representation list")
                console.log(error);
              }));
  
            case 9:
            case "end":
              return _context10.stop();
          }
        }
      }, _callee10);
    }));
  }
  
  exports.get_representation_list = get_representation_list;
  
  function calculate_hdbscan_clusters(X, min_cluster_size, min_cluster_samples, allow_single_cluster) {
    return __awaiter(this, void 0, void 0, /*#__PURE__*/regeneratorRuntime.mark(function _callee11() {
      var formData;
      return regeneratorRuntime.wrap(function _callee11$(_context11) {
        while (1) {
          switch (_context11.prev = _context11.next) {
            case 0:
              formData = new FormData();
              formData.append('min_cluster_size', min_cluster_size);
              formData.append('min_cluster_samples', min_cluster_samples);
              formData.append('allow_single_cluster', allow_single_cluster);
              formData.append('X', X);
              return _context11.abrupt("return", fetch(exports.BASE_URL + '/segmentation', {
                method: 'POST',
                body: formData
              }).then(handle_errors).then(function (response) {
                return response.json();
              }).then(handle_errors_json).catch(function (error) {
                alert("error when calculating clusters");
                console.log(error);
              }));
  
            case 6:
            case "end":
              return _context11.stop();
          }
        }
      }, _callee11);
    }));
  }
  
  exports.calculate_hdbscan_clusters = calculate_hdbscan_clusters;
  
  /***/ })
  
  /******/ });
  //# sourceMappingURL=cluster.js.map