flatten-js
Version:
Javascript library for 2d geometry
1,139 lines (939 loc) • 328 kB
JavaScript
module.exports =
/******/ (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 = "./index.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./algorithms/distance.js":
/*!********************************!*\
!*** ./algorithms/distance.js ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { 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"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var IntervalTree = __webpack_require__(/*! flatten-interval-tree */ "./node_modules/flatten-interval-tree/index.js");
module.exports = function (Flatten) {
var Polygon = Flatten.Polygon,
Point = Flatten.Point,
Segment = Flatten.Segment,
Arc = Flatten.Arc,
Circle = Flatten.Circle,
Line = Flatten.Line,
Ray = Flatten.Ray,
Vector = Flatten.Vector;
var vector = Flatten.vector;
Flatten.Distance = function () {
function Distance() {
_classCallCheck(this, Distance);
}
_createClass(Distance, null, [{
key: "point2point",
/**
* Calculate distance and shortest segment between points
* @param pt1
* @param pt2
* @returns {Number | Segment} - distance and shortest segment
*/
value: function point2point(pt1, pt2) {
return pt1.distanceTo(pt2);
}
/**
* Calculate distance and shortest segment between point and line
* @param pt
* @param line
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "point2line",
value: function point2line(pt, line) {
var closest_point = pt.projectionOn(line);
var vec = vector(pt, closest_point);
return [vec.length, new Segment(pt, closest_point)];
}
/**
* Calculate distance and shortest segment between point and circle
* @param pt
* @param circle
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "point2circle",
value: function point2circle(pt, circle) {
var _pt$distanceTo = pt.distanceTo(circle.center),
_pt$distanceTo2 = _slicedToArray(_pt$distanceTo, 2),
dist2center = _pt$distanceTo2[0],
shortest_dist = _pt$distanceTo2[1];
if (Flatten.Utils.EQ_0(dist2center)) {
return [circle.r, new Segment(pt, circle.toArc().start)];
} else {
var dist = Math.abs(dist2center - circle.r);
var v = vector(circle.pc, pt).normalize().multiply(circle.r);
var closest_point = circle.pc.translate(v);
return [dist, new Segment(pt, closest_point)];
}
}
/**
* Calculate distance and shortest segment between point and segment
* @param pt
* @param segment
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "point2segment",
value: function point2segment(pt, segment) {
/* Degenerated case of zero-length segment */
if (segment.start.equalTo(segment.end)) {
return Distance.point2point(pt, segment.start);
}
var v_seg = new Flatten.Vector(segment.start, segment.end);
var v_ps2pt = new Flatten.Vector(segment.start, pt);
var v_pe2pt = new Flatten.Vector(segment.end, pt);
var start_sp = v_seg.dot(v_ps2pt);
/* dot product v_seg * v_ps2pt */
var end_sp = -v_seg.dot(v_pe2pt);
/* minus dot product v_seg * v_pe2pt */
var dist = void 0;
var closest_point = void 0;
if (Flatten.Utils.GE(start_sp, 0) && Flatten.Utils.GE(end_sp, 0)) {
/* point inside segment scope */
var v_unit = segment.tangentInStart(); // new Flatten.Vector(v_seg.x / this.length, v_seg.y / this.length);
/* unit vector ||v_unit|| = 1 */
dist = Math.abs(v_unit.cross(v_ps2pt));
/* dist = abs(v_unit x v_ps2pt) */
closest_point = segment.start.translate(v_unit.multiply(v_unit.dot(v_ps2pt)));
return [dist, new Segment(pt, closest_point)];
} else if (start_sp < 0) {
/* point is out of scope closer to ps */
return pt.distanceTo(segment.start);
} else {
/* point is out of scope closer to pe */
return pt.distanceTo(segment.end);
}
}
}, {
key: "point2arc",
/**
* Calculate distance and shortest segment between point and arc
* @param pt
* @param arc
* @returns {Number | Segment} - distance and shortest segment
*/
value: function point2arc(pt, arc) {
var circle = new Flatten.Circle(arc.pc, arc.r);
var dist_and_segment = [];
var dist = void 0,
shortest_segment = void 0;
var _Distance$point2circl = Distance.point2circle(pt, circle);
var _Distance$point2circl2 = _slicedToArray(_Distance$point2circl, 2);
dist = _Distance$point2circl2[0];
shortest_segment = _Distance$point2circl2[1];
if (shortest_segment.end.on(arc)) {
dist_and_segment.push(Distance.point2circle(pt, circle));
}
dist_and_segment.push(Distance.point2point(pt, arc.start));
dist_and_segment.push(Distance.point2point(pt, arc.end));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
/**
* Calculate distance and shortest segment between segment and line
* @param seg
* @param line
* @returns {Number | Segment}
*/
}, {
key: "segment2line",
value: function segment2line(seg, line) {
var ip = seg.intersect(line);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])]; // distance = 0, closest point is the first point
}
var dist_and_segment = [];
dist_and_segment.push(Distance.point2line(seg.start, line));
dist_and_segment.push(Distance.point2line(seg.end, line));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
/**
* Calculate distance and shortest segment between two segments
* @param seg1
* @param seg2
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "segment2segment",
value: function segment2segment(seg1, seg2) {
var ip = Segment.intersectSegment2Segment(seg1, seg2);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])]; // distance = 0, closest point is the first point
}
// Seg1 and seg2 not intersected
var dist_and_segment = [];
dist_and_segment.push(Distance.point2segment(seg2.start, seg1));
dist_and_segment.push(Distance.point2segment(seg2.end, seg1));
dist_and_segment.push(Distance.point2segment(seg1.start, seg2));
dist_and_segment.push(Distance.point2segment(seg1.end, seg2));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
/**
* Calculate distance and shortest segment between segment and circle
* @param seg
* @param circle
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "segment2circle",
value: function segment2circle(seg, circle) {
/* Case 1 Segment and circle intersected. Return the first point and zero distance */
var ip = seg.intersect(circle);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
// No intersection between segment and circle
/* Case 2. Distance to projection of center point to line bigger than radius
* And projection point belong to segment
* Then measure again distance from projection to circle and return it */
var line = new Flatten.Line(seg.ps, seg.pe);
var _Distance$point2line = Distance.point2line(circle.center, line),
_Distance$point2line2 = _slicedToArray(_Distance$point2line, 2),
dist = _Distance$point2line2[0],
shortest_segment = _Distance$point2line2[1];
if (Flatten.Utils.GE(dist, circle.r) && shortest_segment.end.on(seg)) {
return Distance.point2circle(shortest_segment.end, circle);
}
/* Case 3. Otherwise closest point is one of the end points of the segment */
else {
var _Distance$point2circl3 = Distance.point2circle(seg.start, circle),
_Distance$point2circl4 = _slicedToArray(_Distance$point2circl3, 2),
dist_from_start = _Distance$point2circl4[0],
shortest_segment_from_start = _Distance$point2circl4[1];
var _Distance$point2circl5 = Distance.point2circle(seg.end, circle),
_Distance$point2circl6 = _slicedToArray(_Distance$point2circl5, 2),
dist_from_end = _Distance$point2circl6[0],
shortest_segment_from_end = _Distance$point2circl6[1];
return Flatten.Utils.LT(dist_from_start, dist_from_end) ? [dist_from_start, shortest_segment_from_start] : [dist_from_end, shortest_segment_from_end];
}
}
/**
* Calculate distance and shortest segment between segment and arc
* @param seg
* @param arc
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "segment2arc",
value: function segment2arc(seg, arc) {
/* Case 1 Segment and arc intersected. Return the first point and zero distance */
var ip = seg.intersect(arc);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
// No intersection between segment and arc
var line = new Flatten.Line(seg.ps, seg.pe);
var circle = new Flatten.Circle(arc.pc, arc.r);
/* Case 2. Distance to projection of center point to line bigger than radius AND
* projection point belongs to segment AND
* distance from projection point to circle belongs to arc =>
* return this distance from projection to circle */
var _Distance$point2line3 = Distance.point2line(circle.center, line),
_Distance$point2line4 = _slicedToArray(_Distance$point2line3, 2),
dist_from_center = _Distance$point2line4[0],
shortest_segment_from_center = _Distance$point2line4[1];
if (Flatten.Utils.GE(dist_from_center, circle.r) && shortest_segment_from_center.end.on(seg)) {
var _Distance$point2circl7 = Distance.point2circle(shortest_segment_from_center.end, circle),
_Distance$point2circl8 = _slicedToArray(_Distance$point2circl7, 2),
dist_from_projection = _Distance$point2circl8[0],
shortest_segment_from_projection = _Distance$point2circl8[1];
if (shortest_segment_from_projection.end.on(arc)) {
return [dist_from_projection, shortest_segment_from_projection];
}
}
/* Case 3. Otherwise closest point is one of the end points of the segment */
var dist_and_segment = [];
dist_and_segment.push(Distance.point2arc(seg.start, arc));
dist_and_segment.push(Distance.point2arc(seg.end, arc));
var dist_tmp = void 0,
segment_tmp = void 0;
var _Distance$point2segme = Distance.point2segment(arc.start, seg);
var _Distance$point2segme2 = _slicedToArray(_Distance$point2segme, 2);
dist_tmp = _Distance$point2segme2[0];
segment_tmp = _Distance$point2segme2[1];
dist_and_segment.push([dist_tmp, segment_tmp.reverse()]);
var _Distance$point2segme3 = Distance.point2segment(arc.end, seg);
var _Distance$point2segme4 = _slicedToArray(_Distance$point2segme3, 2);
dist_tmp = _Distance$point2segme4[0];
segment_tmp = _Distance$point2segme4[1];
dist_and_segment.push([dist_tmp, segment_tmp.reverse()]);
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
/**
* Calculate distance and shortest segment between two circles
* @param circle1
* @param circle2
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "circle2circle",
value: function circle2circle(circle1, circle2) {
var ip = circle1.intersect(circle2);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
// Case 1. Concentric circles. Convert to arcs and take distance between two arc starts
if (circle1.center.equalTo(circle2.center)) {
var arc1 = circle1.toArc();
var arc2 = circle2.toArc();
return Distance.point2point(arc1.start, arc2.start);
} else {
// Case 2. Not concentric circles
var line = new Line(circle1.center, circle2.center);
var ip1 = line.intersect(circle1);
var ip2 = line.intersect(circle2);
var dist_and_segment = [];
dist_and_segment.push(Distance.point2point(ip1[0], ip2[0]));
dist_and_segment.push(Distance.point2point(ip1[0], ip2[1]));
dist_and_segment.push(Distance.point2point(ip1[1], ip2[0]));
dist_and_segment.push(Distance.point2point(ip1[1], ip2[1]));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
}
/**
* Calculate distance and shortest segment between two circles
* @param circle
* @param line
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "circle2line",
value: function circle2line(circle, line) {
var ip = circle.intersect(line);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
var _Distance$point2line5 = Distance.point2line(circle.center, line),
_Distance$point2line6 = _slicedToArray(_Distance$point2line5, 2),
dist_from_center = _Distance$point2line6[0],
shortest_segment_from_center = _Distance$point2line6[1];
var _Distance$point2circl9 = Distance.point2circle(shortest_segment_from_center.end, circle),
_Distance$point2circl10 = _slicedToArray(_Distance$point2circl9, 2),
dist = _Distance$point2circl10[0],
shortest_segment = _Distance$point2circl10[1];
shortest_segment = shortest_segment.reverse();
return [dist, shortest_segment];
}
/**
* Calculate distance and shortest segment between arc and line
* @param arc
* @param line
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "arc2line",
value: function arc2line(arc, line) {
/* Case 1 Line and arc intersected. Return the first point and zero distance */
var ip = line.intersect(arc);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
var circle = new Flatten.Circle(arc.center, arc.r);
/* Case 2. Distance to projection of center point to line bigger than radius AND
* projection point belongs to segment AND
* distance from projection point to circle belongs to arc =>
* return this distance from projection to circle */
var _Distance$point2line7 = Distance.point2line(circle.center, line),
_Distance$point2line8 = _slicedToArray(_Distance$point2line7, 2),
dist_from_center = _Distance$point2line8[0],
shortest_segment_from_center = _Distance$point2line8[1];
if (Flatten.Utils.GE(dist_from_center, circle.r)) {
var _Distance$point2circl11 = Distance.point2circle(shortest_segment_from_center.end, circle),
_Distance$point2circl12 = _slicedToArray(_Distance$point2circl11, 2),
dist_from_projection = _Distance$point2circl12[0],
shortest_segment_from_projection = _Distance$point2circl12[1];
if (shortest_segment_from_projection.end.on(arc)) {
return [dist_from_projection, shortest_segment_from_projection];
}
} else {
var dist_and_segment = [];
dist_and_segment.push(Distance.point2line(arc.start, line));
dist_and_segment.push(Distance.point2line(arc.end, line));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
}
/**
* Calculate distance and shortest segment between arc and circle
* @param arc
* @param circle2
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "arc2circle",
value: function arc2circle(arc, circle2) {
var ip = arc.intersect(circle2);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
var circle1 = new Flatten.Circle(arc.center, arc.r);
var _Distance$circle2circ = Distance.circle2circle(circle1, circle2),
_Distance$circle2circ2 = _slicedToArray(_Distance$circle2circ, 2),
dist = _Distance$circle2circ2[0],
shortest_segment = _Distance$circle2circ2[1];
if (shortest_segment.start.on(arc)) {
return [dist, shortest_segment];
} else {
var dist_and_segment = [];
dist_and_segment.push(Distance.point2circle(arc.start, circle2));
dist_and_segment.push(Distance.point2circle(arc.end, circle2));
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
}
/**
* Calculate distance and shortest segment between two arcs
* @param arc1
* @param arc2
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "arc2arc",
value: function arc2arc(arc1, arc2) {
var ip = arc1.intersect(arc2);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
var circle1 = new Flatten.Circle(arc1.center, arc1.r);
var circle2 = new Flatten.Circle(arc2.center, arc2.r);
var _Distance$circle2circ3 = Distance.circle2circle(circle1, circle2),
_Distance$circle2circ4 = _slicedToArray(_Distance$circle2circ3, 2),
dist = _Distance$circle2circ4[0],
shortest_segment = _Distance$circle2circ4[1];
if (shortest_segment.start.on(arc1) && shortest_segment.end.on(arc2)) {
return [dist, shortest_segment];
} else {
var dist_and_segment = [];
var dist_tmp = void 0,
segment_tmp = void 0;
var _Distance$point2arc = Distance.point2arc(arc1.start, arc2);
var _Distance$point2arc2 = _slicedToArray(_Distance$point2arc, 2);
dist_tmp = _Distance$point2arc2[0];
segment_tmp = _Distance$point2arc2[1];
if (segment_tmp.end.on(arc2)) {
dist_and_segment.push([dist_tmp, segment_tmp]);
}
var _Distance$point2arc3 = Distance.point2arc(arc1.end, arc2);
var _Distance$point2arc4 = _slicedToArray(_Distance$point2arc3, 2);
dist_tmp = _Distance$point2arc4[0];
segment_tmp = _Distance$point2arc4[1];
if (segment_tmp.end.on(arc2)) {
dist_and_segment.push([dist_tmp, segment_tmp]);
}
var _Distance$point2arc5 = Distance.point2arc(arc2.start, arc1);
var _Distance$point2arc6 = _slicedToArray(_Distance$point2arc5, 2);
dist_tmp = _Distance$point2arc6[0];
segment_tmp = _Distance$point2arc6[1];
if (segment_tmp.end.on(arc1)) {
dist_and_segment.push([dist_tmp, segment_tmp.reverse()]);
}
var _Distance$point2arc7 = Distance.point2arc(arc2.end, arc1);
var _Distance$point2arc8 = _slicedToArray(_Distance$point2arc7, 2);
dist_tmp = _Distance$point2arc8[0];
segment_tmp = _Distance$point2arc8[1];
if (segment_tmp.end.on(arc1)) {
dist_and_segment.push([dist_tmp, segment_tmp.reverse()]);
}
var _Distance$point2point = Distance.point2point(arc1.start, arc2.start);
var _Distance$point2point2 = _slicedToArray(_Distance$point2point, 2);
dist_tmp = _Distance$point2point2[0];
segment_tmp = _Distance$point2point2[1];
dist_and_segment.push([dist_tmp, segment_tmp]);
var _Distance$point2point3 = Distance.point2point(arc1.start, arc2.end);
var _Distance$point2point4 = _slicedToArray(_Distance$point2point3, 2);
dist_tmp = _Distance$point2point4[0];
segment_tmp = _Distance$point2point4[1];
dist_and_segment.push([dist_tmp, segment_tmp]);
var _Distance$point2point5 = Distance.point2point(arc1.end, arc2.start);
var _Distance$point2point6 = _slicedToArray(_Distance$point2point5, 2);
dist_tmp = _Distance$point2point6[0];
segment_tmp = _Distance$point2point6[1];
dist_and_segment.push([dist_tmp, segment_tmp]);
var _Distance$point2point7 = Distance.point2point(arc1.end, arc2.end);
var _Distance$point2point8 = _slicedToArray(_Distance$point2point7, 2);
dist_tmp = _Distance$point2point8[0];
segment_tmp = _Distance$point2point8[1];
dist_and_segment.push([dist_tmp, segment_tmp]);
Distance.sort(dist_and_segment);
return dist_and_segment[0];
}
}
/**
* Calculate distance and shortest segment between point and polygon
* @param point
* @param polygon
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "point2polygon",
value: function point2polygon(point, polygon) {
var min_dist_and_segment = [Number.POSITIVE_INFINITY, new Segment()];
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = polygon.edges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var edge = _step.value;
var _ref = edge.shape instanceof Segment ? Distance.point2segment(point, edge.shape) : Distance.point2arc(point, edge.shape),
_ref2 = _slicedToArray(_ref, 2),
dist = _ref2[0],
shortest_segment = _ref2[1];
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return min_dist_and_segment;
}
}, {
key: "shape2polygon",
value: function shape2polygon(shape, polygon) {
var min_dist_and_segment = [Number.POSITIVE_INFINITY, new Segment()];
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = polygon.edges[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var edge = _step2.value;
var _shape$distanceTo = shape.distanceTo(edge.shape),
_shape$distanceTo2 = _slicedToArray(_shape$distanceTo, 2),
dist = _shape$distanceTo2[0],
shortest_segment = _shape$distanceTo2[1];
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
return min_dist_and_segment;
}
/*
static arc2polygon(arc, polygon) {
let ip = arc.intersect(polygon);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
let min_dist_and_segment = [Number.POSITIVE_INFINITY, new Segment()];
for (let edge of polygon.edges) {
let [dist, shortest_segment] = arc.distanceTo(edge.shape);
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
return min_dist_and_segment;
}
static line2polygon(line, polygon) {
let ip = line.intersect(polygon);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
let min_dist_and_segment = [Number.POSITIVE_INFINITY, new Segment()];
for (let edge of polygon.edges) {
let [dist, shortest_segment] = line.distanceTo(edge.shape);
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
return min_dist_and_segment;
}
static circle2polygon(circle, polygon) {
let ip = circle.intersect(polygon);
if (ip.length > 0) {
return [0, new Segment(ip[0], ip[0])];
}
let min_dist_and_segment = [Number.POSITIVE_INFINITY, new Segment()];
for (let edge of polygon.edges) {
let [dist, shortest_segment] = circle.distanceTo(edge.shape);
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
return min_dist_and_segment;
}
*/
/**
* Calculate distance and shortest segment between two polygons
* @param polygon1
* @param polygon2
* @returns {Number | Segment} - distance and shortest segment
*/
}, {
key: "polygon2polygon",
value: function polygon2polygon(polygon1, polygon2) {
var min_dist_and_segment = [Number.POSITIVE_INFINITY, new Flatten.Segment()];
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = polygon1.edges[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var edge1 = _step3.value;
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = polygon2.edges[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var edge2 = _step4.value;
var _edge1$shape$distance = edge1.shape.distanceTo(edge2.shape),
_edge1$shape$distance2 = _slicedToArray(_edge1$shape$distance, 2),
dist = _edge1$shape$distance2[0],
shortest_segment = _edge1$shape$distance2[1];
if (Flatten.Utils.LT(dist, min_dist_and_segment[0])) {
min_dist_and_segment = [dist, shortest_segment];
}
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
return min_dist_and_segment;
}
/**
* Returns [mindist, maxdist] array of squared minimal and maximal distance between boxes
* Minimal distance by x is
* (box2.xmin - box1.xmax), if box1 is left to box2
* (box1.xmin - box2.xmax), if box2 is left to box1
* 0, if box1 and box2 are intersected by x
* Minimal distance by y is defined in the same way
*
* Maximal distance is estimated as a sum of squared dimensions of the merged box
*
* @param box1
* @param box2
* @returns {Number | Number} - minimal and maximal distance
*/
}, {
key: "box2box_minmax",
value: function box2box_minmax(box1, box2) {
var mindist_x = Math.max(Math.max(box1.xmin - box2.xmax, 0), Math.max(box2.xmin - box1.xmax, 0));
var mindist_y = Math.max(Math.max(box1.ymin - box2.ymax, 0), Math.max(box2.ymin - box1.ymax, 0));
var mindist = mindist_x * mindist_x + mindist_y * mindist_y;
var box = box1.merge(box2);
var dx = box.xmax - box.xmin;
var dy = box.ymax - box.ymin;
var maxdist = dx * dx + dy * dy;
return [mindist, maxdist];
}
}, {
key: "minmax_tree_process_level",
value: function minmax_tree_process_level(shape, level, min_stop, tree) {
// Calculate minmax distance to each shape in current level
// Insert result into the interval tree for further processing
// update min_stop with maxdist, it will be the new stop distance
var mindist = void 0,
maxdist = void 0;
var _iteratorNormalCompletion5 = true;
var _didIteratorError5 = false;
var _iteratorError5 = undefined;
try {
for (var _iterator5 = level[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
var node = _step5.value;
// [mindist, maxdist] = Distance.box2box_minmax(shape.box, node.max);
// if (Flatten.Utils.GT(mindist, min_stop))
// continue;
// Estimate min-max dist to the shape stored in the node.item, using node.item.key which is shape's box
var _Distance$box2box_min3 = Distance.box2box_minmax(shape.box, node.item.key);
var _Distance$box2box_min4 = _slicedToArray(_Distance$box2box_min3, 2);
mindist = _Distance$box2box_min4[0];
maxdist = _Distance$box2box_min4[1];
if (node.item.value instanceof Flatten.Edge) {
tree.insert([mindist, maxdist], node.item.value.shape);
} else {
tree.insert([mindist, maxdist], node.item.value);
}
if (Flatten.Utils.LT(maxdist, min_stop)) {
min_stop = maxdist; // this will be the new distance estimation
}
}
} catch (err) {
_didIteratorError5 = true;
_iteratorError5 = err;
} finally {
try {
if (!_iteratorNormalCompletion5 && _iterator5.return) {
_iterator5.return();
}
} finally {
if (_didIteratorError5) {
throw _iteratorError5;
}
}
}
if (level.length === 0) return min_stop;
// Calculate new level from left and right children of the current
var new_level_left = level.map(function (node) {
return node.left.isNil() ? undefined : node.left;
}).filter(function (node) {
return node !== undefined;
});
var new_level_right = level.map(function (node) {
return node.right.isNil() ? undefined : node.right;
}).filter(function (node) {
return node !== undefined;
});
// Merge left and right subtrees and leave only relevant subtrees
var new_level = [].concat(_toConsumableArray(new_level_left), _toConsumableArray(new_level_right)).filter(function (node) {
// Node subtree quick reject, node.max is a subtree box
var _Distance$box2box_min = Distance.box2box_minmax(shape.box, node.max),
_Distance$box2box_min2 = _slicedToArray(_Distance$box2box_min, 2),
mindist = _Distance$box2box_min2[0],
maxdist = _Distance$box2box_min2[1];
return Flatten.Utils.LE(mindist, min_stop);
});
min_stop = Distance.minmax_tree_process_level(shape, new_level, min_stop, tree);
return min_stop;
}
/**
* Calculates sorted tree of [mindist, maxdist] intervals between query shape
* and shapes of the planar set.
* @param shape
* @param set
*/
}, {
key: "minmax_tree",
value: function minmax_tree(shape, set, min_stop) {
var tree = new IntervalTree();
var level = [set.index.root];
var squared_min_stop = min_stop < Number.POSITIVE_INFINITY ? min_stop * min_stop : Number.POSITIVE_INFINITY;
squared_min_stop = Distance.minmax_tree_process_level(shape, level, squared_min_stop, tree);
return tree;
}
}, {
key: "minmax_tree_calc_distance",
value: function minmax_tree_calc_distance(shape, node, min_dist_and_segment) {
var min_dist_and_segment_new = void 0,
stop = void 0;
if (node != null && !node.isNil()) {
var _Distance$minmax_tree = Distance.minmax_tree_calc_distance(shape, node.left, min_dist_and_segment);
var _Distance$minmax_tree2 = _slicedToArray(_Distance$minmax_tree, 2);
min_dist_and_segment_new = _Distance$minmax_tree2[0];
stop = _Distance$minmax_tree2[1];
if (stop) {
return [min_dist_and_segment_new, stop];
}
if (Flatten.Utils.LT(min_dist_and_segment_new[0], Math.sqrt(node.item.key.low))) {
return [min_dist_and_segment_new, true]; // stop condition
}
var _Distance$distance = Distance.distance(shape, node.item.value),
_Distance$distance2 = _slicedToArray(_Distance$distance, 2),
dist = _Distance$distance2[0],
shortest_segment = _Distance$distance2[1];
// console.log(dist)
if (Flatten.Utils.LT(dist, min_dist_and_segment_new[0])) {
min_dist_and_segment_new = [dist, shortest_segment];
}
var _Distance$minmax_tree3 = Distance.minmax_tree_calc_distance(shape, node.right, min_dist_and_segment_new);
var _Distance$minmax_tree4 = _slicedToArray(_Distance$minmax_tree3, 2);
min_dist_and_segment_new = _Distance$minmax_tree4[0];
stop = _Distance$minmax_tree4[1];
return [min_dist_and_segment_new, stop];
}
return [min_dist_and_segment, false];
}
/**
* Calculates distance between shape and Planar Set of shapes
* @param shape
* @param {PlanarSet} set
* @param {Number} min_stop
* @returns {*}
*/
}, {
key: "shape2planarSet",
value: function shape2planarSet(shape, set) {
var min_stop = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Number.POSITIVE_INFINITY;
var min_dist_and_segment = [min_stop, new Flatten.Segment()];
var stop = false;
if (set instanceof Flatten.PlanarSet) {
var tree = Distance.minmax_tree(shape, set, min_stop);
var _Distance$minmax_tree5 = Distance.minmax_tree_calc_distance(shape, tree.root, min_dist_and_segment);
var _Distance$minmax_tree6 = _slicedToArray(_Distance$minmax_tree5, 2);
min_dist_and_segment = _Distance$minmax_tree6[0];
stop = _Distance$minmax_tree6[1];
}
return min_dist_and_segment;
}
}, {
key: "sort",
value: function sort(dist_and_segment) {
dist_and_segment.sort(function (d1, d2) {
if (Flatten.Utils.LT(d1[0], d2[0])) {
return -1;
}
if (Flatten.Utils.GT(d1[0], d2[0])) {
return 1;
}
return 0;
});
}
}, {
key: "distance",
value: function distance(shape1, shape2) {
return shape1.distanceTo(shape2);
}
}]);
return Distance;
}();
};
/***/ }),
/***/ "./algorithms/ray_shooting.js":
/*!************************************!*\
!*** ./algorithms/ray_shooting.js ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (Flatten) {
var Polygon = Flatten.Polygon,
Point = Flatten.Point,
Segment = Flatten.Segment,
Arc = Flatten.Arc,
Line = Flatten.Line,
Ray = Flatten.Ray;
Flatten.ray_shoot = function (polygon, point) {
var contains = undefined;
// if (!(polygon instanceof Polygon &&