{"version":3,"file":"greiner-hormann.min.js","sources":["../src/vertex.js","../src/intersection.js","../src/polygon.js","../src/clip.js","../src/index.js"],"sourcesContent":["export default class Vertex {\n\n /**\n * Vertex representation\n *\n * @param {Number|Array.} x\n * @param {Number=} y\n */\n constructor (x, y) {\n if (arguments.length === 1) {\n // Coords\n if (Array.isArray(x)) {\n y = x[1];\n x = x[0];\n } else {\n y = x.y;\n x = x.x;\n }\n }\n\n /**\n * X coordinate\n * @type {Number}\n */\n this.x = x;\n\n /**\n * Y coordinate\n * @type {Number}\n */\n this.y = y;\n\n /**\n * Next node\n * @type {Vertex}\n */\n this.next = null;\n\n /**\n * Previous vertex\n * @type {Vertex}\n */\n this.prev = null;\n\n /**\n * Corresponding intersection in other polygon\n */\n this._corresponding = null;\n\n /**\n * Distance from previous\n */\n this._distance = 0.0;\n\n /**\n * Entry/exit point in another polygon\n * @type {Boolean}\n */\n this._isEntry = true;\n\n /**\n * Intersection vertex flag\n * @type {Boolean}\n */\n this._isIntersection = false;\n\n /**\n * Loop check\n * @type {Boolean}\n */\n this._visited = false;\n }\n\n\n /**\n * Creates intersection vertex\n * @param {Number} x\n * @param {Number} y\n * @param {Number} distance\n * @return {Vertex}\n */\n static createIntersection (x, y, distance) {\n const vertex = new Vertex(x, y);\n vertex._distance = distance;\n vertex._isIntersection = true;\n vertex._isEntry = false;\n return vertex;\n }\n\n\n /**\n * Mark as visited\n */\n visit () {\n this._visited = true;\n if (this._corresponding !== null && !this._corresponding._visited) {\n this._corresponding.visit();\n }\n }\n\n\n /**\n * Convenience\n * @param {Vertex} v\n * @return {Boolean}\n */\n equals (v) {\n return this.x === v.x && this.y === v.y;\n }\n\n\n /**\n * Check if vertex is inside a polygon by odd-even rule:\n * If the number of intersections of a ray out of the point and polygon\n * segments is odd - the point is inside.\n * @param {Polygon} poly\n * @return {Boolean}\n */\n isInside (poly) {\n let oddNodes = false;\n let vertex = poly.first;\n let next = vertex.next;\n const x = this.x;\n const y = this.y;\n\n do {\n if ((vertex.y < y && next.y >= y ||\n next.y < y && vertex.y >= y) &&\n (vertex.x <= x || next.x <= x)) {\n oddNodes ^= (vertex.x + (y - vertex.y) /\n (next.y - vertex.y) * (next.x - vertex.x) < x);\n }\n\n vertex = vertex.next;\n next = vertex.next || poly.first;\n } while (!vertex.equals(poly.first));\n\n return oddNodes;\n }\n}\n","export default class Intersection {\n\n\n /**\n * @param {Vertex} s1\n * @param {Vertex} s2\n * @param {Vertex} c1\n * @param {Vertex} c2\n */\n constructor(s1, s2, c1, c2) {\n\n /**\n * @type {Number}\n */\n this.x = 0.0;\n\n /**\n * @type {Number}\n */\n this.y = 0.0;\n\n /**\n * @type {Number}\n */\n this.toSource = 0.0;\n\n /**\n * @type {Number}\n */\n this.toClip = 0.0;\n\n const d = (c2.y - c1.y) * (s2.x - s1.x) - (c2.x - c1.x) * (s2.y - s1.y);\n\n if (d === 0) return;\n\n /**\n * @type {Number}\n */\n this.toSource = ((c2.x - c1.x) * (s1.y - c1.y) - (c2.y - c1.y) * (s1.x - c1.x)) / d;\n\n /**\n * @type {Number}\n */\n this.toClip = ((s2.x - s1.x) * (s1.y - c1.y) - (s2.y - s1.y) * (s1.x - c1.x)) / d;\n\n if (this.valid()) {\n this.x = s1.x + this.toSource * (s2.x - s1.x);\n this.y = s1.y + this.toSource * (s2.y - s1.y);\n }\n }\n\n\n /**\n * @return {Boolean}\n */\n valid () {\n return (0 < this.toSource && this.toSource < 1) && (0 < this.toClip && this.toClip < 1);\n }\n}\n","import Vertex from './vertex';\nimport Intersection from './intersection';\n\n\nexport default class Polygon {\n\n\n /**\n * Polygon representation\n * @param {Array.>} p\n * @param {Boolean=} arrayVertices\n */\n constructor (p, arrayVertices) {\n\n /**\n * @type {Vertex}\n */\n this.first = null;\n\n /**\n * @type {Number}\n */\n this.vertices = 0;\n\n /**\n * @type {Vertex}\n */\n this._lastUnprocessed = null;\n\n /**\n * Whether to handle input and output as [x,y] or {x:x,y:y}\n * @type {Boolean}\n */\n this._arrayVertices = (typeof arrayVertices === \"undefined\") ?\n Array.isArray(p[0]) :\n arrayVertices;\n\n for (let i = 0, len = p.length; i < len; i++) {\n this.addVertex(new Vertex(p[i]));\n }\n }\n\n\n /**\n * Add a vertex object to the polygon\n * (vertex is added at the 'end' of the list')\n *\n * @param vertex\n */\n addVertex (vertex) {\n if (this.first === null) {\n this.first = vertex;\n this.first.next = vertex;\n this.first.prev = vertex;\n } else {\n const next = this.first;\n const prev = next.prev;\n\n next.prev = vertex;\n vertex.next = next;\n vertex.prev = prev;\n prev.next = vertex;\n }\n this.vertices++;\n }\n\n\n /**\n * Inserts a vertex inbetween start and end\n *\n * @param {Vertex} vertex\n * @param {Vertex} start\n * @param {Vertex} end\n */\n insertVertex (vertex, start, end) {\n let prev, curr = start;\n\n while (!curr.equals(end) && curr._distance < vertex._distance) {\n curr = curr.next;\n }\n\n vertex.next = curr;\n prev = curr.prev;\n\n vertex.prev = prev;\n prev.next = vertex;\n curr.prev = vertex;\n\n this.vertices++;\n }\n\n /**\n * Get next non-intersection point\n * @param {Vertex} v\n * @return {Vertex}\n */\n getNext (v) {\n let c = v;\n while (c._isIntersection) c = c.next;\n return c;\n }\n\n\n /**\n * Unvisited intersection\n * @return {Vertex}\n */\n getFirstIntersect () {\n let v = this._firstIntersect || this.first;\n\n do {\n if (v._isIntersection && !v._visited) break;\n\n v = v.next;\n } while (!v.equals(this.first));\n\n this._firstIntersect = v;\n return v;\n }\n\n\n /**\n * Does the polygon have unvisited vertices\n * @return {Boolean} [description]\n */\n hasUnprocessed () {\n let v = this._lastUnprocessed || this.first;\n do {\n if (v._isIntersection && !v._visited) {\n this._lastUnprocessed = v;\n return true;\n }\n\n v = v.next;\n } while (!v.equals(this.first));\n\n this._lastUnprocessed = null;\n return false;\n }\n\n\n /**\n * The output depends on what you put in, arrays or objects\n * @return {Array.|Array.}\n */\n getPoints () {\n const points = [];\n let v = this.first;\n\n if (this._arrayVertices) {\n do {\n points.push([v.x, v.y]);\n v = v.next;\n } while (v !== this.first);\n } else {\n do {\n points.push({\n x: v.x,\n y: v.y\n });\n v = v.next;\n } while (v !== this.first);\n }\n\n return points;\n }\n\n /**\n * Clip polygon against another one.\n * Result depends on algorithm direction:\n *\n * Intersection: forwards forwards\n * Union: backwars backwards\n * Diff: backwards forwards\n *\n * @param {Polygon} clip\n * @param {Boolean} sourceForwards\n * @param {Boolean} clipForwards\n */\n clip (clip, sourceForwards, clipForwards) {\n let sourceVertex = this.first;\n let clipVertex = clip.first;\n let sourceInClip, clipInSource;\n\n const isUnion = !sourceForwards && !clipForwards;\n const isIntersection = sourceForwards && clipForwards;\n const isDiff = !isUnion && !isIntersection;\n\n // calculate and mark intersections\n do {\n if (!sourceVertex._isIntersection) {\n do {\n if (!clipVertex._isIntersection) {\n const i = new Intersection(\n sourceVertex,\n this.getNext(sourceVertex.next),\n clipVertex, clip.getNext(clipVertex.next)\n );\n\n if (i.valid()) {\n const sourceIntersection = Vertex.createIntersection(i.x, i.y, i.toSource);\n const clipIntersection = Vertex.createIntersection(i.x, i.y, i.toClip);\n\n sourceIntersection._corresponding = clipIntersection;\n clipIntersection._corresponding = sourceIntersection;\n\n this.insertVertex(sourceIntersection, sourceVertex, this.getNext(sourceVertex.next));\n clip.insertVertex(clipIntersection, clipVertex, clip.getNext(clipVertex.next));\n }\n }\n clipVertex = clipVertex.next;\n } while (!clipVertex.equals(clip.first));\n }\n\n sourceVertex = sourceVertex.next;\n } while (!sourceVertex.equals(this.first));\n\n // phase two - identify entry/exit points\n sourceVertex = this.first;\n clipVertex = clip.first;\n\n sourceInClip = sourceVertex.isInside(clip);\n clipInSource = clipVertex.isInside(this);\n\n sourceForwards ^= sourceInClip;\n clipForwards ^= clipInSource;\n\n do {\n if (sourceVertex._isIntersection) {\n sourceVertex._isEntry = sourceForwards;\n sourceForwards = !sourceForwards;\n }\n sourceVertex = sourceVertex.next;\n } while (!sourceVertex.equals(this.first));\n\n do {\n if (clipVertex._isIntersection) {\n clipVertex._isEntry = clipForwards;\n clipForwards = !clipForwards;\n }\n clipVertex = clipVertex.next;\n } while (!clipVertex.equals(clip.first));\n\n // phase three - construct a list of clipped polygons\n let list = [];\n\n while (this.hasUnprocessed()) {\n let current = this.getFirstIntersect();\n // keep format\n const clipped = new Polygon([], this._arrayVertices);\n\n clipped.addVertex(new Vertex(current.x, current.y));\n do {\n current.visit();\n if (current._isEntry) {\n do {\n current = current.next;\n clipped.addVertex(new Vertex(current.x, current.y));\n } while (!current._isIntersection);\n\n } else {\n do {\n current = current.prev;\n clipped.addVertex(new Vertex(current.x, current.y));\n } while (!current._isIntersection);\n }\n current = current._corresponding;\n } while (!current._visited);\n\n list.push(clipped.getPoints());\n }\n\n if (list.length === 0) {\n if (isUnion) {\n if (sourceInClip) list.push(clip.getPoints());\n else if (clipInSource) list.push(this.getPoints());\n else list.push(this.getPoints(), clip.getPoints());\n } else if (isIntersection) { // intersection\n if (sourceInClip) list.push(this.getPoints());\n else if (clipInSource) list.push(clip.getPoints());\n } else { // diff\n if (sourceInClip) list.push(clip.getPoints(), this.getPoints());\n else if (clipInSource) list.push(this.getPoints(), clip.getPoints());\n else list.push(this.getPoints());\n }\n if (list.length === 0) list = null;\n }\n\n return list;\n }\n}\n","import Polygon from './polygon';\n\n/**\n * Clip driver\n * @param {Array.>} polygonA\n * @param {Array.>} polygonB\n * @param {Boolean} sourceForwards\n * @param {Boolean} clipForwards\n * @return {Array.>}\n */\nexport default function (polygonA, polygonB, eA, eB) {\n const source = new Polygon(polygonA);\n const clip = new Polygon(polygonB);\n return source.clip(clip, eA, eB);\n}\n","import boolean from './clip';\n\n/**\n * @param {Array.|Array.} polygonA\n * @param {Array.|Array.} polygonB\n * @return {Array.>|Array.|Null}\n */\nexport function union (polygonA, polygonB) {\n return boolean(polygonA, polygonB, false, false);\n}\n\n/**\n * @param {Array.|Array.} polygonA\n * @param {Array.|Array.} polygonB\n * @return {Array.>|Array.>|Null}\n */\nexport function intersection (polygonA, polygonB) {\n return boolean(polygonA, polygonB, true, true);\n}\n\n/**\n * @param {Array.|Array.} polygonA\n * @param {Array.|Array.} polygonB\n * @return {Array.>|Array.>|Null}\n */\nexport function diff (polygonA, polygonB) {\n return boolean(polygonA, polygonB, false, true);\n}\n\nexport const clip = boolean;\n"],"names":["Vertex","x","y","arguments","length","Array","isArray","this","next","prev","_corresponding","_distance","_isEntry","_isIntersection","_visited","createIntersection","distance","vertex","visit","equals","v","isInside","poly","let","oddNodes","first","Intersection","s1","s2","c1","c2","toSource","toClip","const","d","valid","Polygon","p","arrayVertices","vertices","_lastUnprocessed","_arrayVertices","i","len","addVertex","polygonA","polygonB","eA","eB","source","clip","insertVertex","start","end","curr","getNext","c","getFirstIntersect","_firstIntersect","hasUnprocessed","getPoints","points","push","sourceForwards","clipForwards","sourceInClip","clipInSource","sourceVertex","clipVertex","isUnion","isIntersection","sourceIntersection","clipIntersection","list","current","clipped","boolean"],"mappings":"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"}