flatten-js
Version:
Javascript library for 2d geometry
1 lines • 19.7 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/15/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 _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); } }\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 var Edge = Flatten.Edge,\n Face = Flatten.Face,\n PlanarSet = Flatten.PlanarSet,\n Box = Flatten.Box;\n var ray_shoot = Flatten.ray_shoot;\n /**\r\n * Class representing a polygon.<br/>\r\n * Polygon in FlattenJS is a multipolygon comprised from a set of [faces]{@link Flatten.Face}. <br/>\r\n * Face, in turn, is a closed loop of [edges]{@link Flatten.Edge}, where edge may be segment or circular arc<br/>\r\n * @type {Polygon}\r\n */\n\n Flatten.Polygon = function () {\n /**\r\n * Constructor creates new instance of polygon.<br/>\r\n * New polygon is empty. Add face to the polygon using method <br/>\r\n * <code>\r\n * polygon.addFace(Points[]|Segments[]|Arcs[])\r\n * </code>\r\n */\n function Polygon() {\n _classCallCheck(this, Polygon);\n\n /**\r\n * Container of faces (closed loops), may be empty\r\n * @type {PlanarSet}\r\n */\n this.faces = new PlanarSet();\n /**\r\n * Container of edges\r\n * @type {PlanarSet}\r\n */\n this.edges = new PlanarSet();\n }\n\n /**\r\n * (Getter) Returns bounding box of the polygon\r\n * @returns {Box}\r\n */\n\n\n _createClass(Polygon, [{\n key: \"addFace\",\n\n\n /**\r\n * Add new face to polygon. Returns added face\r\n * @param {Points[]|Segments[]|Arcs[]} args - list of points or list of shapes (segments and arcs)\r\n * which comprise a closed loop\r\n * @returns {Face}\r\n */\n value: function addFace() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var face = new (Function.prototype.bind.apply(Face, [null].concat([this], args)))();\n this.faces.add(face);\n return face;\n }\n\n /**\r\n * Delete existing face from polygon\r\n * @param {Face} face Face to be deleted\r\n * @returns {boolean}\r\n */\n\n }, {\n key: \"deleteFace\",\n value: function deleteFace(face) {\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = face[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var edge = _step.value;\n\n var _deleted = this.edges.delete(edge);\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 var deleted = this.faces.delete(face);\n return deleted;\n }\n\n /**\r\n * Delete chain of edges from the face.\r\n * @param {Face} face Face to remove chain\r\n * @param {Edge} edgeFrom Start of the chain of edges to be removed\r\n * @param {Edge} edgeTo End of the chain of edges to be removed\r\n */\n\n }, {\n key: \"removeChain\",\n value: function removeChain(face, edgeFrom, edgeTo) {\n // Special case: all edges removed\n if (edgeTo.next === edgeFrom) {\n this.deleteFace(face);\n return;\n }\n for (var edge = edgeFrom; edge !== edgeTo.next; edge = edge.next) {\n face.remove(this.edges, edge);\n // this.edges.delete(edge); // delete from PlanarSet of edges and update index\n if (face.isEmpty()) {\n this.deleteFace(face); // delete from PlanarSet of faces and update index\n break;\n }\n }\n }\n\n /**\r\n * Add point as a new vertex and split edge. Point supposed to belong to an edge.\r\n * When edge is split, new edge created from the start of the edge to the new vertex\r\n * and inserted before current edge.\r\n * Current edge is trimmed and updated. Method returns new edge added.\r\n * @param {Edge} edge Edge to be split with new vertex and then trimmed from start\r\n * @param {Point} pt Point to be added as a new vertex\r\n * @returns {Edge}\r\n */\n\n }, {\n key: \"addVertex\",\n value: function addVertex(pt, edge) {\n var shapes = edge.shape.split(pt);\n if (shapes.length < 2) return;\n var newEdge = new Flatten.Edge(shapes[0]);\n var edgeBefore = edge.prev;\n\n /* Insert first split edge into linked list after edgeBefore */\n edge.face.insert(this.edges, newEdge, edgeBefore);\n\n // Remove old edge from edges container and 2d index\n this.edges.delete(edge);\n\n // Update edge shape with second split edge keeping links\n edge.shape = shapes[1];\n\n // Add updated edge to the edges container and 2d index\n this.edges.add(edge);\n\n return newEdge;\n }\n }, {\n key: \"reverse\",\n value: function reverse() {\n var _iteratorNormalCompletion2 = true;\n var _didIteratorError2 = false;\n var _iteratorError2 = undefined;\n\n try {\n for (var _iterator2 = this.faces[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {\n var face = _step2.value;\n\n face.reverse();\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 this;\n }\n\n /**\r\n * Create new copied instance of the polygon\r\n * @returns {Polygon}\r\n */\n\n }, {\n key: \"clone\",\n value: function clone() {\n var polygon = new Polygon();\n var _iteratorNormalCompletion3 = true;\n var _didIteratorError3 = false;\n var _iteratorError3 = undefined;\n\n try {\n for (var _iterator3 = this.faces[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {\n var face = _step3.value;\n\n var shapes = [];\n var _iteratorNormalCompletion4 = true;\n var _didIteratorError4 = false;\n var _iteratorError4 = undefined;\n\n try {\n for (var _iterator4 = face[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {\n var edge = _step4.value;\n\n shapes.push(edge.shape.clone());\n }\n } catch (err) {\n _didIteratorError4 = true;\n _iteratorError4 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion4 && _iterator4.return) {\n _iterator4.return();\n }\n } finally {\n if (_didIteratorError4) {\n throw _iteratorError4;\n }\n }\n }\n\n polygon.addFace(shapes);\n }\n } catch (err) {\n _didIteratorError3 = true;\n _iteratorError3 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion3 && _iterator3.return) {\n _iterator3.return();\n }\n } finally {\n if (_didIteratorError3) {\n throw _iteratorError3;\n }\n }\n }\n\n return polygon;\n }\n\n /**\r\n * Returns area of the polygon. Area of an island will be added, area of a hole will be subtracted\r\n * @returns {number}\r\n */\n\n }, {\n key: \"area\",\n value: function area() {\n var signedArea = [].concat(_toConsumableArray(this.faces)).reduce(function (acc, face) {\n return acc + face.signedArea();\n }, 0);\n return Math.abs(signedArea);\n }\n\n /**\r\n * Returns true if polygon contains point, including polygon boundary, false otherwise\r\n * Point in polygon test based on ray shooting algorithm\r\n * @param {Point} point - test point\r\n * @returns {boolean}\r\n */\n\n }, {\n key: \"contains\",\n value: function contains(point) {\n var rel = ray_shoot(this, point);\n return rel == Flatten.INSIDE || rel == Flatten.BOUNDARY ? true : false;\n }\n\n /**\r\n * Return distance and shortest segment between polygon and other shape as array [distance, shortest_segment]\r\n * @param {Shape} shape Shape of one of the types Point, Circle, Line, Segment, Arc or Polygon\r\n * @returns {Number | Segment}\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$point2polyg = Distance.point2polygon(shape, this),\n _Distance$point2polyg2 = _slicedToArray(_Distance$point2polyg, 2),\n dist = _Distance$point2polyg2[0],\n shortest_segment = _Distance$point2polyg2[1];\n\n shortest_segment = shortest_segment.reverse();\n return [dist, shortest_segment];\n }\n\n if (shape instanceof Flatten.Circle || shape instanceof Flatten.Line || shape instanceof Flatten.Segment || shape instanceof Flatten.Arc) {\n var _Distance$shape2polyg = Distance.shape2polygon(shape, this),\n _Distance$shape2polyg2 = _slicedToArray(_Distance$shape2polyg, 2),\n _dist = _Distance$shape2polyg2[0],\n _shortest_segment = _Distance$shape2polyg2[1];\n\n _shortest_segment = _shortest_segment.reverse();\n return [_dist, _shortest_segment];\n }\n\n /* this method is bit faster */\n if (shape instanceof Flatten.Polygon) {\n var min_dist_and_segment = [Number.POSITIVE_INFINITY, new Flatten.Segment()];\n var _dist2 = void 0,\n _shortest_segment2 = void 0;\n\n var _iteratorNormalCompletion5 = true;\n var _didIteratorError5 = false;\n var _iteratorError5 = undefined;\n\n try {\n for (var _iterator5 = this.edges[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {\n var edge = _step5.value;\n\n // let [dist, shortest_segment] = Distance.shape2polygon(edge.shape, shape);\n var min_stop = min_dist_and_segment[0];\n\n var _Distance$shape2plana = Distance.shape2planarSet(edge.shape, shape.edges, min_stop);\n\n var _Distance$shape2plana2 = _slicedToArray(_Distance$shape2plana, 2);\n\n _dist2 = _Distance$shape2plana2[0];\n _shortest_segment2 = _Distance$shape2plana2[1];\n\n if (Flatten.Utils.LT(_dist2, min_stop)) {\n min_dist_and_segment = [_dist2, _shortest_segment2];\n }\n }\n } catch (err) {\n _didIteratorError5 = true;\n _iteratorError5 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion5 && _iterator5.return) {\n _iterator5.return();\n }\n } finally {\n if (_didIteratorError5) {\n throw _iteratorError5;\n }\n }\n }\n\n return min_dist_and_segment;\n }\n }\n\n /**\r\n * Return string to draw polygon in svg\r\n * @param attrs - json structure with attributes for svg path element,\r\n * like \"stroke\", \"strokeWidth\", \"fill\", \"fillRule\"\r\n * Defaults are stroke:\"black\", strokeWidth:\"3\", fill:\"lightcyan\", fillRule:\"evenodd\"\r\n * @returns {string}\r\n */\n\n }, {\n key: \"svg\",\n value: function svg() {\n var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { stroke: \"black\", strokeWidth: \"3\", fill: \"lightcyan\", fillRule: \"evenodd\" };\n var stroke = attrs.stroke,\n strokeWidth = attrs.strokeWidth,\n fill = attrs.fill,\n fillRule = attrs.fillRule;\n\n var svgStr = \"\\n<path stroke=\\\"\" + stroke + \"\\\" stroke-width=\\\"\" + strokeWidth + \"\\\" fill=\\\"\" + fill + \"\\\" fill-rule=\\\"\" + fillRule + \"\\\" d=\\\"\";\n var _iteratorNormalCompletion6 = true;\n var _didIteratorError6 = false;\n var _iteratorError6 = undefined;\n\n try {\n for (var _iterator6 = this.faces[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {\n var face = _step6.value;\n\n svgStr += face.svg();\n }\n } catch (err) {\n _didIteratorError6 = true;\n _iteratorError6 = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion6 && _iterator6.return) {\n _iterator6.return();\n }\n } finally {\n if (_didIteratorError6) {\n throw _iteratorError6;\n }\n }\n }\n\n svgStr += \"\\\">\\n</path>\";\n\n return svgStr;\n }\n }, {\n key: \"toJSON\",\n value: function toJSON() {\n return [].concat(_toConsumableArray(this.faces)).map(function (face) {\n return face.toJSON();\n });\n }\n }, {\n key: \"box\",\n get: function get() {\n return [].concat(_toConsumableArray(this.faces)).reduce(function (acc, face) {\n return acc.merge(face.box);\n }, new Box());\n }\n\n /**\r\n * (Getter) Returns array of vertices\r\n * @returns {Array}\r\n */\n\n }, {\n key: \"vertices\",\n get: function get() {\n return [].concat(_toConsumableArray(this.edges)).map(function (edge) {\n return edge.start;\n });\n }\n }]);\n\n return Polygon;\n }();\n};"},"hash":"e2b302fca53752abe6609ed7a9ca5025","cacheData":{"env":{}}}