UNPKG

flatten-js

Version:

Javascript library for 2d geometry

1,139 lines (939 loc) 328 kB
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 &&