flatten-js
Version:
Javascript library for 2d geometry
1 lines • 21.2 kB
JSON
{"dependencies":[{"name":"C:\\Users\\alexbol\\WebstormProjects\\flatten-js\\package.json","includedInParent":true,"mtime":1520238055570}],"generated":{"js":"/**\r\n * Created by Alex Bol on 3/10/2017.\r\n */\n\n\"use strict\";\n\nvar _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\"); } }; }();\n\nvar _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; }; }();\n\nfunction _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nmodule.exports = function (Flatten) {\n /**\r\n * Class representing a segment\r\n * @type {Segment}\r\n */\n Flatten.Segment = function () {\n /**\r\n *\r\n * @param {Point} ps - start point\r\n * @param {Point} pe - end point\r\n */\n function Segment() {\n _classCallCheck(this, Segment);\n\n /**\r\n * Start point\r\n * @type {Point}\r\n */\n this.ps = new Flatten.Point();\n /**\r\n * End Point\r\n * @type {Point}\r\n */\n this.pe = new Flatten.Point();\n\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n if (args.length == 0) {\n return;\n }\n\n if (args.length == 1 && args[0] instanceof Array && args[0].length == 4) {\n var coords = args[0];\n this.ps = new Flatten.Point(coords[0], coords[1]);\n this.pe = new Flatten.Point(coords[2], coords[3]);\n return;\n }\n\n if (args.length == 2 && args[0] instanceof Flatten.Point && args[1] instanceof Flatten.Point) {\n this.ps = args[0].clone();\n this.pe = args[1].clone();\n return;\n }\n\n if (args.length == 4) {\n this.ps = new Flatten.Point(args[0], args[1]);\n this.pe = new Flatten.Point(args[2], args[3]);\n return;\n }\n\n throw Flatten.Errors.ILLEGAL_PARAMETERS;\n }\n\n /**\r\n * Method clone copies segment and returns a new instance\r\n * @returns {Segment}\r\n */\n\n\n _createClass(Segment, [{\n key: \"clone\",\n value: function clone() {\n return new Flatten.Segment(this.start, this.end);\n }\n\n /**\r\n * Start point\r\n * @returns {Point}\r\n */\n\n }, {\n key: \"contains\",\n\n\n /**\r\n * Returns true if segment contains point\r\n * @param {Point} pt Query point\r\n * @returns {boolean}\r\n */\n value: function contains(pt) {\n return Flatten.Utils.EQ_0(this.distanceToPoint(pt));\n }\n\n /**\r\n * Returns array of intersection points between segment and other shape\r\n * @param {Shape} shape - Shape of the one of supported types Line, Circle, Segment, Arc <br/>\r\n * TODO: support Polygon and Planar Set\r\n * @returns {Point[]}\r\n */\n\n }, {\n key: \"intersect\",\n value: function intersect(shape) {\n if (shape instanceof Flatten.Line) {\n return Segment.intersectSegment2Line(this, shape);\n }\n\n if (shape instanceof Flatten.Segment) {\n return Segment.intersectSegment2Segment(this, shape);\n }\n\n if (shape instanceof Flatten.Circle) {\n return Segment.intersectSegment2Circle(this, shape);\n }\n\n if (shape instanceof Flatten.Arc) {\n return Segment.intersectSegment2Arc(this, shape);\n }\n }\n\n /**\r\n * Calculate distance and shortest segment from segment to shape and return as array [distance, shortest segment]\r\n * @param {Shape} shape Shape of the one of supported types Point, Line, Circle, Segment, Arc, Polygon or Planar Set\r\n * @returns {number} distance from segment to shape\r\n * @returns {Segment} shortest segment between segment and shape (started at segment, ended at shape)\r\n */\n\n }, {\n key: \"distanceTo\",\n value: function distanceTo(shape) {\n var Distance = Flatten.Distance;\n\n\n if (shape instanceof Flatten.Point) {\n var _Distance$point2segme = Distance.point2segment(shape, this),\n _Distance$point2segme2 = _slicedToArray(_Distance$point2segme, 2),\n dist = _Distance$point2segme2[0],\n shortest_segment = _Distance$point2segme2[1];\n\n shortest_segment = shortest_segment.reverse();\n return [dist, shortest_segment];\n }\n\n if (shape instanceof Flatten.Circle) {\n var _Distance$segment2cir = Distance.segment2circle(this, shape),\n _Distance$segment2cir2 = _slicedToArray(_Distance$segment2cir, 2),\n _dist = _Distance$segment2cir2[0],\n _shortest_segment = _Distance$segment2cir2[1];\n\n return [_dist, _shortest_segment];\n }\n\n if (shape instanceof Flatten.Line) {\n var _Distance$segment2lin = Distance.segment2line(this, shape),\n _Distance$segment2lin2 = _slicedToArray(_Distance$segment2lin, 2),\n _dist2 = _Distance$segment2lin2[0],\n _shortest_segment2 = _Distance$segment2lin2[1];\n\n return [_dist2, _shortest_segment2];\n }\n\n if (shape instanceof Flatten.Segment) {\n var _Distance$segment2seg = Distance.segment2segment(this, shape),\n _Distance$segment2seg2 = _slicedToArray(_Distance$segment2seg, 2),\n _dist3 = _Distance$segment2seg2[0],\n _shortest_segment3 = _Distance$segment2seg2[1];\n\n return [_dist3, _shortest_segment3];\n }\n\n if (shape instanceof Flatten.Arc) {\n var _Distance$segment2arc = Distance.segment2arc(this, shape),\n _Distance$segment2arc2 = _slicedToArray(_Distance$segment2arc, 2),\n _dist4 = _Distance$segment2arc2[0],\n _shortest_segment4 = _Distance$segment2arc2[1];\n\n return [_dist4, _shortest_segment4];\n }\n\n if (shape instanceof Flatten.Polygon) {\n var _Distance$shape2polyg = Distance.shape2polygon(this, shape),\n _Distance$shape2polyg2 = _slicedToArray(_Distance$shape2polyg, 2),\n _dist5 = _Distance$shape2polyg2[0],\n _shortest_segment5 = _Distance$shape2polyg2[1];\n\n return [_dist5, _shortest_segment5];\n }\n\n if (shape instanceof Flatten.PlanarSet) {\n var _Distance$shape2plana = Distance.shape2planarSet(this, shape),\n _Distance$shape2plana2 = _slicedToArray(_Distance$shape2plana, 2),\n _dist6 = _Distance$shape2plana2[0],\n _shortest_segment6 = _Distance$shape2plana2[1];\n\n return [_dist6, _shortest_segment6];\n }\n }\n\n /**\r\n * Returns unit vector in the direction from start to end\r\n * @returns {Vector}\r\n */\n\n }, {\n key: \"tangentInStart\",\n value: function tangentInStart() {\n var vec = new Flatten.Vector(this.start, this.end);\n return vec.normalize();\n }\n\n /**\r\n * Return unit vector in the direction from end to start\r\n * @returns {Vector}\r\n */\n\n }, {\n key: \"tangentInEnd\",\n value: function tangentInEnd() {\n var vec = new Flatten.Vector(this.end, this.start);\n return vec.normalize();\n }\n\n /**\r\n * Returns new segment with swapped start and end points\r\n * @returns {Segment}\r\n */\n\n }, {\n key: \"reverse\",\n value: function reverse() {\n return new Segment(this.end, this.start);\n }\n\n /**\r\n * When point belongs to segment, return array of two segments split by given point,\r\n * if point is inside segment. Returns clone of this segment if query point is incident\r\n * to start or end point of the segment. Returns empty array if point does not belong to segment\r\n * @param {Point} pt Query point\r\n * @returns {Segment[]}\r\n */\n\n }, {\n key: \"split\",\n value: function split(pt) {\n if (!this.contains(pt)) return [];\n\n if (this.start.equalTo(this.end)) return [this.clone()];\n\n if (this.start.equalTo(pt) || this.end.equalTo(pt)) return [this];\n\n return [new Flatten.Segment(this.start, pt), new Flatten.Segment(pt, this.end)];\n }\n\n /**\r\n * Return middle point of the segment\r\n * @returns {Point}\r\n */\n\n }, {\n key: \"middle\",\n value: function middle() {\n return new Flatten.Point((this.start.x + this.end.x) / 2, (this.start.y + this.end.y) / 2);\n }\n }, {\n key: \"distanceToPoint\",\n value: function distanceToPoint(pt) {\n var _Flatten$Distance$poi = Flatten.Distance.point2segment(pt, this),\n _Flatten$Distance$poi2 = _toArray(_Flatten$Distance$poi),\n dist = _Flatten$Distance$poi2[0],\n rest = _Flatten$Distance$poi2.slice(1);\n\n return dist;\n }\n }, {\n key: \"definiteIntegral\",\n value: function definiteIntegral() {\n var ymin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0.0;\n\n var dx = this.end.x - this.start.x;\n var dy1 = this.start.y - ymin;\n var dy2 = this.end.y - ymin;\n return dx * (dy1 + dy2) / 2;\n }\n }, {\n key: \"svg\",\n\n\n /**\r\n * Return string to draw segment in svg\r\n * @param {Object} attrs - Object with attributes for svg path element,\r\n * like \"stroke\", \"strokeWidth\" <br/>\r\n * Defaults are stroke:\"black\", strokeWidth:\"3\"\r\n * @returns {string}\r\n */\n value: function svg() {\n var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { stroke: \"black\", strokeWidth: \"3\" };\n var stroke = attrs.stroke,\n strokeWidth = attrs.strokeWidth;\n\n return \"\\n<line x1=\\\"\" + this.start.x + \"\\\" y1=\\\"\" + this.start.y + \"\\\" x2=\\\"\" + this.end.x + \"\\\" y2=\\\"\" + this.end.y + \"\\\" stroke=\\\"\" + stroke + \"\\\" stroke-width=\\\"\" + strokeWidth + \"\\\" />\";\n }\n }, {\n key: \"start\",\n get: function get() {\n return this.ps;\n }\n\n /**\r\n * End point\r\n * @returns {Point}\r\n */\n\n }, {\n key: \"end\",\n get: function get() {\n return this.pe;\n }\n\n /**\r\n * Returns array of start and end point\r\n * @returns [Point,Point]\r\n */\n\n }, {\n key: \"vertices\",\n get: function get() {\n return [this.ps.clone(), this.pe.clone()];\n }\n\n /**\r\n * Length of a segment\r\n * @returns {number}\r\n */\n\n }, {\n key: \"length\",\n get: function get() {\n return this.start.distanceTo(this.end)[0];\n }\n\n /**\r\n * Slope of the line - angle to axe x in radians from 0 to 2PI\r\n * @returns {number}\r\n */\n\n }, {\n key: \"slope\",\n get: function get() {\n var vec = new Flatten.Vector(this.start, this.end);\n return vec.slope;\n }\n\n /**\r\n * Bounding box\r\n * @returns {Box}\r\n */\n\n }, {\n key: \"box\",\n get: function get() {\n return new Flatten.Box(Math.min(this.start.x, this.end.x), Math.min(this.start.y, this.end.y), Math.max(this.start.x, this.end.x), Math.max(this.start.y, this.end.y));\n }\n }], [{\n key: \"intersectSegment2Line\",\n value: function intersectSegment2Line(seg, line) {\n var ip = [];\n var zero_segment = Flatten.Utils.EQ_0(seg.length);\n\n // Boundary cases\n if (seg.ps.on(line)) {\n ip.push(seg.ps);\n }\n // If both ends lay on line, return two intersection points\n if (seg.pe.on(line) && !zero_segment) {\n ip.push(seg.pe);\n }\n\n if (ip.length > 0) {\n return ip; // done, intersection found\n }\n\n // Not a boundary case, check if both points are on the same side and\n // hence there is no intersection\n if (seg.ps.leftTo(line) && seg.pe.leftTo(line) || !seg.ps.leftTo(line) && !seg.pe.leftTo(line)) {\n return ip;\n }\n\n // Calculate intersection between lines\n var line1 = new Flatten.Line(seg.ps, seg.pe);\n return line1.intersect(line);\n }\n }, {\n key: \"intersectSegment2Segment\",\n value: function intersectSegment2Segment(seg1, seg2) {\n var ip = [];\n\n // quick reject\n if (seg1.box.notIntersect(seg2.box)) {\n return ip;\n }\n\n var line1 = new Flatten.Line(seg1.ps, seg1.pe);\n var line2 = new Flatten.Line(seg2.ps, seg2.pe);\n\n // Check overlapping between segments in case of incidence\n // If segments touching, add one point. If overlapping, add two points\n if (line1.incidentTo(line2)) {\n if (seg1.ps.on(seg2)) {\n ip.push(seg1.ps);\n }\n if (seg1.pe.on(seg2)) {\n ip.push(seg1.pe);\n }\n if (seg2.ps.on(seg1) && !seg2.ps.equalTo(seg1.ps) && !seg2.ps.equalTo(seg1.pe)) {\n ip.push(seg2.ps);\n }\n if (seg2.pe.on(seg1) && !seg2.pe.equalTo(seg1.ps) && !seg2.pe.equalTo(seg1.pe)) {\n ip.push(seg2.pe);\n }\n } else {\n /* not incident - parallel or intersect */\n // Calculate intersection between lines\n var new_ip = line1.intersect(line2);\n if (new_ip.length > 0 && new_ip[0].on(seg1) && new_ip[0].on(seg2)) {\n ip.push(new_ip[0]);\n }\n }\n\n return ip;\n }\n }, {\n key: \"intersectSegment2Circle\",\n value: function intersectSegment2Circle(segment, circle) {\n var ips = [];\n\n if (segment.box.notIntersect(circle.box)) {\n return ips;\n }\n\n var line = new Flatten.Line(segment.ps, segment.pe);\n\n var ips_tmp = line.intersect(circle);\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = ips_tmp[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var ip = _step.value;\n\n if (ip.on(segment)) {\n ips.push(ip);\n }\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n\n return ips;\n }\n }, {\n key: \"intersectSegment2Arc\",\n value: function intersectSegment2Arc(segment, arc) {\n var ip = [];\n\n if (segment.box.notIntersect(arc.box)) {\n return ip;\n }\n\n var line = new Flatten.Line(segment.ps, segment.pe);\n var circle = new Flatten.Circle(arc.pc, arc.r);\n\n var ip_tmp = line.intersect(circle);\n\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = ip_tmp[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var pt = _step2.value;\n\n if (pt.on(segment) && pt.on(arc)) {\n ip.push(pt);\n }\n }\n } catch (err) {\n _didIteratorError2 = true;\n _iteratorError2 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion2 && _iterator2.return) {\n _iterator2.return();\n }\n } finally {\n if (_didIteratorError2) {\n throw _iteratorError2;\n }\n }\n }\n\n return ip;\n }\n }]);\n\n return Segment;\n }();\n\n /**\r\n * Shortcut method to create new segment\r\n */\n Flatten.segment = function () {\n for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n args[_key2] = arguments[_key2];\n }\n\n return new (Function.prototype.bind.apply(Flatten.Segment, [null].concat(args)))();\n };\n};"},"hash":"4709231260e6f85349da6b21937bd191","cacheData":{"env":{}}}