@itwin/core-geometry 3.0.0-dev.84 → 3.0.0-dev.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgePointInGraphSearch.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePointInGraphSearch.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\n\nimport { Geometry } from \"../Geometry\";\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\nimport { Ray3d } from \"../geometry3d/Ray3d\";\nimport { HalfEdge } from \"./Graph\";\nimport { NodeXYZUV } from \"./HalfEdgeNodeXYZUV\";\nimport { HalfEdgePositionDetail } from \"./HalfEdgePositionDetail\";\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport enum RayClassification {\n RC_NoHits,\n RC_TargetOnVertex,\n RC_TargetOnEdge,\n RC_Bracket,\n RC_TargetBefore,\n RC_TargetAfter,\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport class PointSearchContext {\n private _tol: number;\n private constructor(tol: number) {\n this._tol = tol;\n }\n public static create(tol: number = Geometry.smallMetricDistance) {\n return new PointSearchContext(tol);\n }\n private panic(): HalfEdgePositionDetail {\n return HalfEdgePositionDetail.create();\n }\n // From given edge start point\n // The edgeHit is reused as the result.\n public reAimFromEdge(\n edgeHit: HalfEdgePositionDetail,\n ray: Ray3d,\n targetDistance: number): HalfEdgePositionDetail {\n const nodeA = edgeHit.node!;\n const dataA = NodeXYZUV.createNodeAndRayOrigin(nodeA, ray);\n const dataB = NodeXYZUV.createNodeAndRayOrigin(nodeA.edgeMate, ray);\n const sideA = -dataA.classifyV(0.0, this._tol);\n const sideB = -dataB.classifyV(0.0, this._tol);\n let result;\n if (sideA * sideB < 0) {\n // Simple crossing -- just aim into a face\n if (sideA > 0) {\n result = edgeHit.resetAsFace(dataA.node);\n } else {\n result = edgeHit.resetAsFace(dataB.node);\n }\n } else if (sideA === 0 || sideB === 0) {\n // The usual case is both 0 i.e. ray is clearly along the edge.\n\n const alongA = dataA.classifyU(targetDistance, this._tol);\n const alongB = dataB.classifyU(targetDistance, this._tol);\n if (alongA === 0 && sideA === 0) {\n result = edgeHit.resetAsVertex(dataA.node);\n result.setITag(1);\n } else if (alongB === 0 && sideB === 0) {\n result = edgeHit.resetAsVertex(dataB.node);\n result.setITag(1);\n } else if (alongA * alongB < 0) {\n // target is within edge\n // (.. This is written for the case where both sideA and sideB are zero.\n // If only one is zero, this computes a close edge point but the strong \"on\" conclusion might be wrong)\n\n const edgeFraction = (targetDistance - dataA.u) / (dataB.u - dataA.u);\n result = edgeHit.resetAtEdgeAndFraction(dataA.node, edgeFraction);\n result.setITag(1);\n } else if (alongA < 0 && alongB < 0) {\n // target is beyond the edge -- move towards it.\n if (dataA.u > dataB.u)\n result = edgeHit.resetAsVertex(dataA.node);\n else\n result = edgeHit.resetAsVertex(dataB.node);\n } else {\n // This shouldn't happen -- maybe as if the initial edge point was not within the edge???\n if (Math.abs(dataA.u) < this._tol\n && Math.abs(dataA.v) < this._tol\n ) {\n result = edgeHit.resetAsVertex(dataA.node); // , dataA);\n } else if (Math.abs(dataB.u) < this._tol\n && Math.abs(dataB.v) < this._tol\n ) {\n result = edgeHit.resetAsVertex(dataB.node);\n } else {\n edgeHit.resetAsUnknown();\n result = this.panic();\n }\n }\n } else {\n // Both vertices are to same side of the line. This can't happen for edge point between nodes.\n edgeHit.resetAsUnknown();\n result = this.panic();\n }\n return result;\n }\n\n // From given edge start point, pick vertex or edge side for proceeding along ray.\n // RAY IS ASSUMED TO START AT THE VERTEX PRECISELY !!!!\n public reAimFromVertex(\n searchBase: HalfEdgePositionDetail,\n ray: Ray3d,\n targetDistance: number): HalfEdgePositionDetail {\n const vertexNode = searchBase.node;\n let result;\n let outboundEdge = vertexNode!;\n do {\n // DPoint3d xyzBase;\n // vu_getDPoint3d(& xyzBase, outboundEdge);\n const data0 = NodeXYZUV.createNodeAndRayOrigin(outboundEdge.faceSuccessor, ray);\n const data1 = NodeXYZUV.createNodeAndRayOrigin(outboundEdge.facePredecessor, ray);\n const u0 = data0.u;\n // double u1 = data1.GetU ();\n const v0 = data0.v;\n const v1 = data1.v;\n if (Math.abs(v0) < this._tol) {\n if (Math.abs(u0 - targetDistance) < this._tol) {\n // Direct hit at far end\n result = searchBase.resetAsVertex(data0.node);\n result.setITag(1);\n return result;\n } else if (u0 > targetDistance) {\n // Direct hig within edge\n const edgeFraction = targetDistance / u0;\n result = searchBase.resetAtEdgeAndFraction(outboundEdge, edgeFraction);\n return result;\n } else if (Math.abs(u0) <= this._tol) {\n // Unexpected direct hit on the base of the search, but call it a hit....\n result = searchBase.resetAsVertex(outboundEdge);\n result.setITag(1);\n return result;\n } else if (u0 > this._tol) {\n // Advance to vertex ...\n // double edgeFraction = targetDistance / u0;\n result = searchBase.resetAsVertex(data0.node);\n return result;\n } else {\n // Search direction is exactly opposite this edge.\n // See if the other side of the sector is turned even beyond that ...\n if (v1 > this._tol) {\n result = searchBase.resetAsFace(outboundEdge, outboundEdge);\n return result;\n }\n }\n } else if (v0 < -this._tol) {\n if (v1 > this._tol) {\n // The usual simple entry into an angle < 180\n result = searchBase.resetAsFace(outboundEdge, outboundEdge);\n return result;\n }\n }\n // NEEDS WORK: angle >= 180 cases !!!!\n outboundEdge = outboundEdge.vertexSuccessor;\n } while (outboundEdge !== vertexNode);\n return this.panic();\n }\n\n // Visit all edges around face.\n // reset lastBefore and firstAfter describing progress towards target distance on ray.\n public reAimAroundFace(\n faceNode: HalfEdge,\n ray: Ray3d,\n targetDistance: number, // !< distance to target point\n lastBefore: HalfEdgePositionDetail, // CALLER CREATED -- reset as first hit on negative side of ray.\n firstAfter: HalfEdgePositionDetail): RayClassification { // ! CALLER CREATED -- reset as first hit on positive side of ray.\n\n lastBefore.resetAsUndefinedWithTag(-Number.MAX_VALUE);\n firstAfter.resetAsUndefinedWithTag(Number.MAX_VALUE);\n const data0 = NodeXYZUV.createNodeAndRayOrigin(faceNode, ray);\n let data1;\n let node0 = faceNode;\n do {\n const node1 = node0.faceSuccessor;\n data1 = NodeXYZUV.createNodeAndRayOrigin(node1, ray, data1);\n const u0 = data0.u;\n const u1 = data1.u;\n const v0 = data0.v;\n const v1 = data1.v;\n if (Math.abs(v1) < this._tol) {\n // Vertex hit ...\n const vertexHit = HalfEdgePositionDetail.createVertex(node1);\n vertexHit.setDTag(u1);\n if (Math.abs(u1 - targetDistance) < this._tol) {\n firstAfter.setFrom(vertexHit);\n lastBefore.setFrom(vertexHit);\n return RayClassification.RC_TargetOnVertex;\n }\n if (u1 > targetDistance && u1 < firstAfter.getDTag()!)\n firstAfter.setFrom(vertexHit);\n if (u1 < targetDistance && u1 > lastBefore.getDTag()!)\n lastBefore.setFrom(vertexHit);\n } else if (v0 * v1 < 0.0) {\n // Edge Crossing ...\n const edgeFraction = - v0 / (v1 - v0);\n const uEdge = Geometry.interpolate(u0, edgeFraction, u1);\n const edgeHit = HalfEdgePositionDetail.createEdgeAtFraction(data0.node, edgeFraction);\n edgeHit.setDTag(uEdge);\n if (Math.abs(uEdge - targetDistance) <= this._tol) {\n firstAfter.setFrom(edgeHit);\n lastBefore.setFrom(edgeHit);\n return RayClassification.RC_TargetOnEdge;\n }\n if (uEdge > targetDistance && uEdge < firstAfter.getDTag()!) {\n firstAfter.setFrom(edgeHit);\n firstAfter.setITag(v0 > 0.0 ? -1 : 1);\n }\n if (uEdge < targetDistance && uEdge > lastBefore.getDTag()!) {\n lastBefore.setFrom(edgeHit);\n lastBefore.setDTag(uEdge);\n }\n }\n data0.setFrom(data1);\n node0 = node0.faceSuccessor;\n } while (node0 !== faceNode);\n\n const afterTag = firstAfter.getITag();\n firstAfter.setITag(0);\n lastBefore.setITag(0);\n if (lastBefore.isUnclassified) {\n if (firstAfter.isUnclassified)\n return RayClassification.RC_NoHits;\n return RayClassification.RC_TargetBefore;\n }\n if (firstAfter.isUnclassified\n || (firstAfter.isEdge && afterTag && afterTag < 0)) {\n return RayClassification.RC_TargetAfter;\n } else {\n return RayClassification.RC_Bracket;\n }\n }\n\n // Return false if target is reached !!!!\n /**\n * Set (replace contents) ray with\n * * `origin` at start\n * * `direction` is unit vector from start towards target\n * * `a` is distance from start to target.\n * @param start existing position\n * @param target target xy coordinates\n * @param ray ray to update\n */\n public setSearchRay(start: HalfEdgePositionDetail, target: Point3d, ray: Ray3d): boolean {\n ray.origin.setFromPoint3d(start);\n Vector3d.createStartEnd(ray.origin, target, ray.direction);\n ray.direction.z = 0.0;\n const distanceToTarget = ray.direction.magnitudeXY();\n ray.a = ray.direction.magnitude();\n ray.direction.scaleInPlace(1 / ray.a);\n return distanceToTarget >= this._tol;\n }\n}\n"]}
1
+ {"version":3,"file":"HalfEdgePointInGraphSearch.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePointInGraphSearch.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\nimport { Geometry } from \"../Geometry\";\r\nimport { Point3d, Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { Ray3d } from \"../geometry3d/Ray3d\";\r\nimport { HalfEdge } from \"./Graph\";\r\nimport { NodeXYZUV } from \"./HalfEdgeNodeXYZUV\";\r\nimport { HalfEdgePositionDetail } from \"./HalfEdgePositionDetail\";\r\n\r\n/* eslint-disable @typescript-eslint/naming-convention */\r\nexport enum RayClassification {\r\n RC_NoHits,\r\n RC_TargetOnVertex,\r\n RC_TargetOnEdge,\r\n RC_Bracket,\r\n RC_TargetBefore,\r\n RC_TargetAfter,\r\n}\r\n/* eslint-enable @typescript-eslint/naming-convention */\r\n\r\nexport class PointSearchContext {\r\n private _tol: number;\r\n private constructor(tol: number) {\r\n this._tol = tol;\r\n }\r\n public static create(tol: number = Geometry.smallMetricDistance) {\r\n return new PointSearchContext(tol);\r\n }\r\n private panic(): HalfEdgePositionDetail {\r\n return HalfEdgePositionDetail.create();\r\n }\r\n // From given edge start point\r\n // The edgeHit is reused as the result.\r\n public reAimFromEdge(\r\n edgeHit: HalfEdgePositionDetail,\r\n ray: Ray3d,\r\n targetDistance: number): HalfEdgePositionDetail {\r\n const nodeA = edgeHit.node!;\r\n const dataA = NodeXYZUV.createNodeAndRayOrigin(nodeA, ray);\r\n const dataB = NodeXYZUV.createNodeAndRayOrigin(nodeA.edgeMate, ray);\r\n const sideA = -dataA.classifyV(0.0, this._tol);\r\n const sideB = -dataB.classifyV(0.0, this._tol);\r\n let result;\r\n if (sideA * sideB < 0) {\r\n // Simple crossing -- just aim into a face\r\n if (sideA > 0) {\r\n result = edgeHit.resetAsFace(dataA.node);\r\n } else {\r\n result = edgeHit.resetAsFace(dataB.node);\r\n }\r\n } else if (sideA === 0 || sideB === 0) {\r\n // The usual case is both 0 i.e. ray is clearly along the edge.\r\n\r\n const alongA = dataA.classifyU(targetDistance, this._tol);\r\n const alongB = dataB.classifyU(targetDistance, this._tol);\r\n if (alongA === 0 && sideA === 0) {\r\n result = edgeHit.resetAsVertex(dataA.node);\r\n result.setITag(1);\r\n } else if (alongB === 0 && sideB === 0) {\r\n result = edgeHit.resetAsVertex(dataB.node);\r\n result.setITag(1);\r\n } else if (alongA * alongB < 0) {\r\n // target is within edge\r\n // (.. This is written for the case where both sideA and sideB are zero.\r\n // If only one is zero, this computes a close edge point but the strong \"on\" conclusion might be wrong)\r\n\r\n const edgeFraction = (targetDistance - dataA.u) / (dataB.u - dataA.u);\r\n result = edgeHit.resetAtEdgeAndFraction(dataA.node, edgeFraction);\r\n result.setITag(1);\r\n } else if (alongA < 0 && alongB < 0) {\r\n // target is beyond the edge -- move towards it.\r\n if (dataA.u > dataB.u)\r\n result = edgeHit.resetAsVertex(dataA.node);\r\n else\r\n result = edgeHit.resetAsVertex(dataB.node);\r\n } else {\r\n // This shouldn't happen -- maybe as if the initial edge point was not within the edge???\r\n if (Math.abs(dataA.u) < this._tol\r\n && Math.abs(dataA.v) < this._tol\r\n ) {\r\n result = edgeHit.resetAsVertex(dataA.node); // , dataA);\r\n } else if (Math.abs(dataB.u) < this._tol\r\n && Math.abs(dataB.v) < this._tol\r\n ) {\r\n result = edgeHit.resetAsVertex(dataB.node);\r\n } else {\r\n edgeHit.resetAsUnknown();\r\n result = this.panic();\r\n }\r\n }\r\n } else {\r\n // Both vertices are to same side of the line. This can't happen for edge point between nodes.\r\n edgeHit.resetAsUnknown();\r\n result = this.panic();\r\n }\r\n return result;\r\n }\r\n\r\n // From given edge start point, pick vertex or edge side for proceeding along ray.\r\n // RAY IS ASSUMED TO START AT THE VERTEX PRECISELY !!!!\r\n public reAimFromVertex(\r\n searchBase: HalfEdgePositionDetail,\r\n ray: Ray3d,\r\n targetDistance: number): HalfEdgePositionDetail {\r\n const vertexNode = searchBase.node;\r\n let result;\r\n let outboundEdge = vertexNode!;\r\n do {\r\n // DPoint3d xyzBase;\r\n // vu_getDPoint3d(& xyzBase, outboundEdge);\r\n const data0 = NodeXYZUV.createNodeAndRayOrigin(outboundEdge.faceSuccessor, ray);\r\n const data1 = NodeXYZUV.createNodeAndRayOrigin(outboundEdge.facePredecessor, ray);\r\n const u0 = data0.u;\r\n // double u1 = data1.GetU ();\r\n const v0 = data0.v;\r\n const v1 = data1.v;\r\n if (Math.abs(v0) < this._tol) {\r\n if (Math.abs(u0 - targetDistance) < this._tol) {\r\n // Direct hit at far end\r\n result = searchBase.resetAsVertex(data0.node);\r\n result.setITag(1);\r\n return result;\r\n } else if (u0 > targetDistance) {\r\n // Direct hig within edge\r\n const edgeFraction = targetDistance / u0;\r\n result = searchBase.resetAtEdgeAndFraction(outboundEdge, edgeFraction);\r\n return result;\r\n } else if (Math.abs(u0) <= this._tol) {\r\n // Unexpected direct hit on the base of the search, but call it a hit....\r\n result = searchBase.resetAsVertex(outboundEdge);\r\n result.setITag(1);\r\n return result;\r\n } else if (u0 > this._tol) {\r\n // Advance to vertex ...\r\n // double edgeFraction = targetDistance / u0;\r\n result = searchBase.resetAsVertex(data0.node);\r\n return result;\r\n } else {\r\n // Search direction is exactly opposite this edge.\r\n // See if the other side of the sector is turned even beyond that ...\r\n if (v1 > this._tol) {\r\n result = searchBase.resetAsFace(outboundEdge, outboundEdge);\r\n return result;\r\n }\r\n }\r\n } else if (v0 < -this._tol) {\r\n if (v1 > this._tol) {\r\n // The usual simple entry into an angle < 180\r\n result = searchBase.resetAsFace(outboundEdge, outboundEdge);\r\n return result;\r\n }\r\n }\r\n // NEEDS WORK: angle >= 180 cases !!!!\r\n outboundEdge = outboundEdge.vertexSuccessor;\r\n } while (outboundEdge !== vertexNode);\r\n return this.panic();\r\n }\r\n\r\n // Visit all edges around face.\r\n // reset lastBefore and firstAfter describing progress towards target distance on ray.\r\n public reAimAroundFace(\r\n faceNode: HalfEdge,\r\n ray: Ray3d,\r\n targetDistance: number, // !< distance to target point\r\n lastBefore: HalfEdgePositionDetail, // CALLER CREATED -- reset as first hit on negative side of ray.\r\n firstAfter: HalfEdgePositionDetail): RayClassification { // ! CALLER CREATED -- reset as first hit on positive side of ray.\r\n\r\n lastBefore.resetAsUndefinedWithTag(-Number.MAX_VALUE);\r\n firstAfter.resetAsUndefinedWithTag(Number.MAX_VALUE);\r\n const data0 = NodeXYZUV.createNodeAndRayOrigin(faceNode, ray);\r\n let data1;\r\n let node0 = faceNode;\r\n do {\r\n const node1 = node0.faceSuccessor;\r\n data1 = NodeXYZUV.createNodeAndRayOrigin(node1, ray, data1);\r\n const u0 = data0.u;\r\n const u1 = data1.u;\r\n const v0 = data0.v;\r\n const v1 = data1.v;\r\n if (Math.abs(v1) < this._tol) {\r\n // Vertex hit ...\r\n const vertexHit = HalfEdgePositionDetail.createVertex(node1);\r\n vertexHit.setDTag(u1);\r\n if (Math.abs(u1 - targetDistance) < this._tol) {\r\n firstAfter.setFrom(vertexHit);\r\n lastBefore.setFrom(vertexHit);\r\n return RayClassification.RC_TargetOnVertex;\r\n }\r\n if (u1 > targetDistance && u1 < firstAfter.getDTag()!)\r\n firstAfter.setFrom(vertexHit);\r\n if (u1 < targetDistance && u1 > lastBefore.getDTag()!)\r\n lastBefore.setFrom(vertexHit);\r\n } else if (v0 * v1 < 0.0) {\r\n // Edge Crossing ...\r\n const edgeFraction = - v0 / (v1 - v0);\r\n const uEdge = Geometry.interpolate(u0, edgeFraction, u1);\r\n const edgeHit = HalfEdgePositionDetail.createEdgeAtFraction(data0.node, edgeFraction);\r\n edgeHit.setDTag(uEdge);\r\n if (Math.abs(uEdge - targetDistance) <= this._tol) {\r\n firstAfter.setFrom(edgeHit);\r\n lastBefore.setFrom(edgeHit);\r\n return RayClassification.RC_TargetOnEdge;\r\n }\r\n if (uEdge > targetDistance && uEdge < firstAfter.getDTag()!) {\r\n firstAfter.setFrom(edgeHit);\r\n firstAfter.setITag(v0 > 0.0 ? -1 : 1);\r\n }\r\n if (uEdge < targetDistance && uEdge > lastBefore.getDTag()!) {\r\n lastBefore.setFrom(edgeHit);\r\n lastBefore.setDTag(uEdge);\r\n }\r\n }\r\n data0.setFrom(data1);\r\n node0 = node0.faceSuccessor;\r\n } while (node0 !== faceNode);\r\n\r\n const afterTag = firstAfter.getITag();\r\n firstAfter.setITag(0);\r\n lastBefore.setITag(0);\r\n if (lastBefore.isUnclassified) {\r\n if (firstAfter.isUnclassified)\r\n return RayClassification.RC_NoHits;\r\n return RayClassification.RC_TargetBefore;\r\n }\r\n if (firstAfter.isUnclassified\r\n || (firstAfter.isEdge && afterTag && afterTag < 0)) {\r\n return RayClassification.RC_TargetAfter;\r\n } else {\r\n return RayClassification.RC_Bracket;\r\n }\r\n }\r\n\r\n // Return false if target is reached !!!!\r\n /**\r\n * Set (replace contents) ray with\r\n * * `origin` at start\r\n * * `direction` is unit vector from start towards target\r\n * * `a` is distance from start to target.\r\n * @param start existing position\r\n * @param target target xy coordinates\r\n * @param ray ray to update\r\n */\r\n public setSearchRay(start: HalfEdgePositionDetail, target: Point3d, ray: Ray3d): boolean {\r\n ray.origin.setFromPoint3d(start);\r\n Vector3d.createStartEnd(ray.origin, target, ray.direction);\r\n ray.direction.z = 0.0;\r\n const distanceToTarget = ray.direction.magnitudeXY();\r\n ray.a = ray.direction.magnitude();\r\n ray.direction.scaleInPlace(1 / ray.a);\r\n return distanceToTarget >= this._tol;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"HalfEdgePriorityQueue.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH,sDAAuE;AAEvE,uCAA6C;AAE7C;;;;;;;;GAQG;AACH,MAAa,qCAAqC;IAGhD,YACE,UAAuC,0BAAgB,CAAC,gBAAgB;QACxE,IAAI,CAAC,aAAa,GAAG,IAAI,4BAAa,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACxB,CAAC;IACD,qEAAqE;IAC9D,eAAe;QACpB,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO;YAC5B,OAAO,SAAS,CAAC;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAG,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD;;;;OAIG;IACI,oBAAoB,CAAC,CAAS;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YACT,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAG,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SACzB;IACH,CAAC;IACD;;;;OAIG;IACI,6BAA6B,CAAC,CAAS;QAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,CAAC,EAAE;gBACX,+BAA+B;gBAC/B,IAAI,OAAO,GAAG,CAAC;oBACb,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,EAAE,CAAC;aACX;iBAAM;gBACL,mBAAmB;aACpB;SACF;QACD,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC;IACpC,CAAC;CACF;AAlDD,sFAkDC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\nimport { OrderedComparator, PriorityQueue } from \"@itwin/core-bentley\";\nimport { HalfEdge } from \"./Graph\";\nimport { HalfEdgeGraphOps } from \"./Merging\";\n\n/**\n * * Combination of a priority queue of HalfEdges with\n * * Additional \"active\" array to carry edges that have been removed from the queue but are still to be\n * inspected (possibly many times)\n * * The priority queue default sort is Y-then-X lexical sort.\n * * Caller has direct access to the queue and array.\n * * Methods are added here only to do things that involve both the queue and the array.\n * @internal\n */\nexport class HalfEdgePriorityQueueWithPartnerArray {\n public priorityQueue: PriorityQueue<HalfEdge>;\n public activeEdges: HalfEdge[];\n public constructor(\n compare: OrderedComparator<HalfEdge> = HalfEdgeGraphOps.compareNodesYXUp) {\n this.priorityQueue = new PriorityQueue(compare);\n this.activeEdges = [];\n }\n /** Read a member from the queue and transfer to the active array. */\n public popQueueToArray(): HalfEdge | undefined {\n if (this.priorityQueue.isEmpty)\n return undefined;\n const x = this.priorityQueue.pop()!;\n this.activeEdges.push(x);\n return x;\n }\n /** Pop the last entry and put it back as replacement for current entry at index i.\n * * Effectively remove active member at index i\n * * The array order is changed.\n * * constant time.\n */\n public popArrayToArrayIndex(i: number) {\n const n = this.activeEdges.length;\n if (i < n) {\n const x = this.activeEdges.pop()!;\n this.activeEdges[i] = x;\n }\n }\n /**\n * * Scan the active array.\n * * remove edges whose top y is below y\n * * (pack all remaining ones back towards the beginning)\n */\n public removeArrayMembersWithY1Below(y: number) {\n let numKeep = 0;\n const n = this.activeEdges.length;\n for (let i = 0; i < n; i++) {\n const q = this.activeEdges[i];\n const yB = q.faceSuccessor.y;\n if (yB >= y) {\n // copy [i] forward to [target]\n if (numKeep < i)\n this.activeEdges[numKeep] = q;\n numKeep++;\n } else {\n // let it go by !!!\n }\n }\n this.activeEdges.length = numKeep;\n }\n}\n"]}
1
+ {"version":3,"file":"HalfEdgePriorityQueue.js","sourceRoot":"","sources":["../../../src/topology/HalfEdgePriorityQueue.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH,sDAAuE;AAEvE,uCAA6C;AAE7C;;;;;;;;GAQG;AACH,MAAa,qCAAqC;IAGhD,YACE,UAAuC,0BAAgB,CAAC,gBAAgB;QACxE,IAAI,CAAC,aAAa,GAAG,IAAI,4BAAa,CAAC,OAAO,CAAC,CAAC;QAChD,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACxB,CAAC;IACD,qEAAqE;IAC9D,eAAe;QACpB,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO;YAC5B,OAAO,SAAS,CAAC;QACnB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,EAAG,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC;IACX,CAAC;IACD;;;;OAIG;IACI,oBAAoB,CAAC,CAAS;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,IAAI,CAAC,GAAG,CAAC,EAAE;YACT,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAG,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;SACzB;IACH,CAAC;IACD;;;;OAIG;IACI,6BAA6B,CAAC,CAAS;QAC5C,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,IAAI,CAAC,EAAE;gBACX,+BAA+B;gBAC/B,IAAI,OAAO,GAAG,CAAC;oBACb,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChC,OAAO,EAAE,CAAC;aACX;iBAAM;gBACL,mBAAmB;aACpB;SACF;QACD,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC;IACpC,CAAC;CACF;AAlDD,sFAkDC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\nimport { OrderedComparator, PriorityQueue } from \"@itwin/core-bentley\";\r\nimport { HalfEdge } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n/**\r\n * * Combination of a priority queue of HalfEdges with\r\n * * Additional \"active\" array to carry edges that have been removed from the queue but are still to be\r\n * inspected (possibly many times)\r\n * * The priority queue default sort is Y-then-X lexical sort.\r\n * * Caller has direct access to the queue and array.\r\n * * Methods are added here only to do things that involve both the queue and the array.\r\n * @internal\r\n */\r\nexport class HalfEdgePriorityQueueWithPartnerArray {\r\n public priorityQueue: PriorityQueue<HalfEdge>;\r\n public activeEdges: HalfEdge[];\r\n public constructor(\r\n compare: OrderedComparator<HalfEdge> = HalfEdgeGraphOps.compareNodesYXUp) {\r\n this.priorityQueue = new PriorityQueue(compare);\r\n this.activeEdges = [];\r\n }\r\n /** Read a member from the queue and transfer to the active array. */\r\n public popQueueToArray(): HalfEdge | undefined {\r\n if (this.priorityQueue.isEmpty)\r\n return undefined;\r\n const x = this.priorityQueue.pop()!;\r\n this.activeEdges.push(x);\r\n return x;\r\n }\r\n /** Pop the last entry and put it back as replacement for current entry at index i.\r\n * * Effectively remove active member at index i\r\n * * The array order is changed.\r\n * * constant time.\r\n */\r\n public popArrayToArrayIndex(i: number) {\r\n const n = this.activeEdges.length;\r\n if (i < n) {\r\n const x = this.activeEdges.pop()!;\r\n this.activeEdges[i] = x;\r\n }\r\n }\r\n /**\r\n * * Scan the active array.\r\n * * remove edges whose top y is below y\r\n * * (pack all remaining ones back towards the beginning)\r\n */\r\n public removeArrayMembersWithY1Below(y: number) {\r\n let numKeep = 0;\r\n const n = this.activeEdges.length;\r\n for (let i = 0; i < n; i++) {\r\n const q = this.activeEdges[i];\r\n const yB = q.faceSuccessor.y;\r\n if (yB >= y) {\r\n // copy [i] forward to [target]\r\n if (numKeep < i)\r\n this.activeEdges[numKeep] = q;\r\n numKeep++;\r\n } else {\r\n // let it go by !!!\r\n }\r\n }\r\n this.activeEdges.length = numKeep;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MaskManager.js","sourceRoot":"","sources":["../../../src/topology/MaskManager.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH;;;;;;GAMG;AACH,MAAa,WAAW;IAItB;;OAEG;IACH,YAAoB,SAAiB,EAAE,aAAqB;QAC1D,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;IACtC,CAAC;IACD;;;OAGG;IACI,MAAM,CAAC,MAAM,CAAC,SAAiB;QACpC,kCAAkC;QAClC,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE;gBAC/B,SAAS,GAAG,OAAO,CAAC;gBACpB,MAAM;aACP;YACD,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;SAC1B;QACD,IAAI,SAAS,KAAK,CAAC;YACjB,OAAO,SAAS,CAAC;QACnB,OAAO,IAAI,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;IACD;;OAEG;IACI,QAAQ;QACb,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC;QAC/B,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,OAAO,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;YAC9B,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;QAEnB,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD;;OAEG;IACI,QAAQ,CAAC,IAAY;QAC1B,IAAI,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAI,0CAA0C;QAC9E,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IAC1B,CAAC;CAEF;AApDD,kCAoDC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\n/**\n * Methods to \"grab and drop\" mask bits.\n * * Caller code (e.g. HalfEdgeGraph) initializes with a block of bits to be managed.\n * * Callers borrow and return masks with \"grabMask\" and \"dropMask\"\n * * Callers must exercise grab/drop balance discipline.\n * @internal\n */\nexport class MaskManager {\n private _freeMasks: number;\n private _originalFreeMasks: number;\n private _firstFreeMask: number;\n /**\n * @param freeMasks caller-defined block of bits that are to be managed.\n */\n private constructor(freeMasks: number, firstFreeMask: number) {\n this._originalFreeMasks = freeMasks;\n this._freeMasks = freeMasks;\n this._firstFreeMask = firstFreeMask;\n }\n /** Create a MaskManager.\n * Typical use: MaskManager.create (0xFFFF0000)\n * * This makes bits 16 through 31 available to be borrowed, with lower bits available for fixed usage.\n */\n public static create(freeMasks: number): MaskManager | undefined {\n // look for first bit up to bit 31\n let firstFree = 0;\n let testBit = 0x01;\n for (let i = 0; i < 32; i++) {\n if ((testBit & freeMasks) !== 0) {\n firstFree = testBit;\n break;\n }\n testBit = (testBit << 1);\n }\n if (firstFree === 0)\n return undefined;\n return new MaskManager(freeMasks, firstFree);\n }\n /**\n * Find a mask bit that is not \"in use\".\n */\n public grabMask(): number {\n let mask = this._firstFreeMask;\n if (this._freeMasks === 0)\n return 0;\n while (!(mask & this._freeMasks))\n mask = mask << 1;\n\n this._freeMasks &= ~mask;\n return mask;\n }\n /**\n * Find a mask bit that is not \"in use\".\n */\n public dropMask(mask: number) {\n mask &= this._originalFreeMasks; // prevent \"drop\" of mask not in the pool.\n this._freeMasks |= mask;\n }\n\n}\n"]}
1
+ {"version":3,"file":"MaskManager.js","sourceRoot":"","sources":["../../../src/topology/MaskManager.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;;;AAE/F;;GAEG;AACH;;;;;;GAMG;AACH,MAAa,WAAW;IAItB;;OAEG;IACH,YAAoB,SAAiB,EAAE,aAAqB;QAC1D,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,cAAc,GAAG,aAAa,CAAC;IACtC,CAAC;IACD;;;OAGG;IACI,MAAM,CAAC,MAAM,CAAC,SAAiB;QACpC,kCAAkC;QAClC,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;YAC3B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,EAAE;gBAC/B,SAAS,GAAG,OAAO,CAAC;gBACpB,MAAM;aACP;YACD,OAAO,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;SAC1B;QACD,IAAI,SAAS,KAAK,CAAC;YACjB,OAAO,SAAS,CAAC;QACnB,OAAO,IAAI,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/C,CAAC;IACD;;OAEG;IACI,QAAQ;QACb,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc,CAAC;QAC/B,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC;YACvB,OAAO,CAAC,CAAC;QACX,OAAO,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC;YAC9B,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;QAEnB,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IACD;;OAEG;IACI,QAAQ,CAAC,IAAY;QAC1B,IAAI,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAI,0CAA0C;QAC9E,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;IAC1B,CAAC;CAEF;AApDD,kCAoDC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n/**\r\n * Methods to \"grab and drop\" mask bits.\r\n * * Caller code (e.g. HalfEdgeGraph) initializes with a block of bits to be managed.\r\n * * Callers borrow and return masks with \"grabMask\" and \"dropMask\"\r\n * * Callers must exercise grab/drop balance discipline.\r\n * @internal\r\n */\r\nexport class MaskManager {\r\n private _freeMasks: number;\r\n private _originalFreeMasks: number;\r\n private _firstFreeMask: number;\r\n /**\r\n * @param freeMasks caller-defined block of bits that are to be managed.\r\n */\r\n private constructor(freeMasks: number, firstFreeMask: number) {\r\n this._originalFreeMasks = freeMasks;\r\n this._freeMasks = freeMasks;\r\n this._firstFreeMask = firstFreeMask;\r\n }\r\n /** Create a MaskManager.\r\n * Typical use: MaskManager.create (0xFFFF0000)\r\n * * This makes bits 16 through 31 available to be borrowed, with lower bits available for fixed usage.\r\n */\r\n public static create(freeMasks: number): MaskManager | undefined {\r\n // look for first bit up to bit 31\r\n let firstFree = 0;\r\n let testBit = 0x01;\r\n for (let i = 0; i < 32; i++) {\r\n if ((testBit & freeMasks) !== 0) {\r\n firstFree = testBit;\r\n break;\r\n }\r\n testBit = (testBit << 1);\r\n }\r\n if (firstFree === 0)\r\n return undefined;\r\n return new MaskManager(freeMasks, firstFree);\r\n }\r\n /**\r\n * Find a mask bit that is not \"in use\".\r\n */\r\n public grabMask(): number {\r\n let mask = this._firstFreeMask;\r\n if (this._freeMasks === 0)\r\n return 0;\r\n while (!(mask & this._freeMasks))\r\n mask = mask << 1;\r\n\r\n this._freeMasks &= ~mask;\r\n return mask;\r\n }\r\n /**\r\n * Find a mask bit that is not \"in use\".\r\n */\r\n public dropMask(mask: number) {\r\n mask &= this._originalFreeMasks; // prevent \"drop\" of mask not in the pool.\r\n this._freeMasks |= mask;\r\n }\r\n\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Merging.js","sourceRoot":"","sources":["../../../src/topology/Merging.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\n\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\nimport { Geometry } from \"../Geometry\";\nimport { Angle } from \"../geometry3d/Angle\";\nimport { Point2d, Vector2d } from \"../geometry3d/Point2dVector2d\";\nimport { Range3d } from \"../geometry3d/Range\";\nimport { ClusterableArray } from \"../numerics/ClusterableArray\";\nimport { SmallSystem } from \"../numerics/Polynomials\";\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\nimport { HalfEdgePriorityQueueWithPartnerArray } from \"./HalfEdgePriorityQueue\";\nimport { RegularizationContext } from \"./RegularizeFace\";\nimport { MultiLineStringDataVariant, Triangulator } from \"./Triangulation\";\n\nexport class GraphSplitData {\n public numUpEdge = 0;\n public numIntersectionTest = 0;\n public numSplit = 0;\n public numPopOut = 0;\n public numA0B0 = 0;\n public numA0B1 = 0;\n public constructor() {\n }\n}\n\n/**\n * * Assorted methods used in algorithms on HalfEdgeGraph.\n * @internal\n */\nexport class HalfEdgeGraphOps {\n\n /** Compare function for sorting with primary y compare, secondary x compare. */\n public static compareNodesYXUp(a: HalfEdge, b: HalfEdge) {\n // Check y's\n // if (!Geometry.isSameCoordinate(a.y, b.y))\n if (a.y < b.y)\n return -1;\n else if (a.y > b.y)\n return 1;\n // Check x's\n // if (!Geometry.isSameCoordinate(a.x, b.x))\n if (a.x < b.x)\n return -1;\n else if (a.x > b.x)\n return 1;\n return 0;\n }\n\n /** Return true if nodeB (a) is lower than both its neighbors and (b) inflects as a downward peak (rather than an upward trough) */\n public static isDownPeak(nodeB: HalfEdge) {\n const nodeA = nodeB.facePredecessor;\n const nodeC = nodeB.faceSuccessor;\n return this.compareNodesYXUp(nodeB, nodeA) < 0\n && this.compareNodesYXUp(nodeB, nodeC) < 0\n && this.crossProductToTargets(nodeB, nodeA, nodeC) > 0;\n }\n\n /** return the cross product of vectors from base to targetA and base to targetB\n * @param base base vertex of both vectors.\n * @param targetA target vertex of first vector\n * @param targetB target vertex of second vector\n */\n public static crossProductToTargets(base: HalfEdge, targetA: HalfEdge, targetB: HalfEdge): number {\n return Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);\n }\n\n // ---------------------------------------------------------------------------------------------------------------------\n // ----------------------------------------------------------------------------------------------------------------------\n\n public static graphRange(graph: HalfEdgeGraph): Range3d {\n const range = Range3d.create();\n for (const node of graph.allHalfEdges) {\n range.extendXYZ(node.x, node.y, node.z);\n }\n return range;\n }\n /** Returns an array of a all nodes (both ends) of edges created from segments. */\n public static segmentArrayToGraphEdges(segments: LineSegment3d[], returnGraph: HalfEdgeGraph, mask: HalfEdgeMask): HalfEdge[] {\n const result = [];\n let idxCounter = 0;\n\n // Push the endpoints of each segment onto arr[] in the form {(x, y, theta), Node}\n for (const segment of segments) {\n\n const node0 = returnGraph.createEdgeXYZXYZ(\n segment.point0Ref.x, segment.point0Ref.y, segment.point0Ref.z,\n idxCounter,\n segment.point1Ref.x, segment.point1Ref.y, segment.point1Ref.z,\n idxCounter + 1);\n\n const node1 = node0.edgeMate;\n idxCounter += 2;\n\n node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary\n result.push(node0);\n result.push(node1);\n }\n\n return result;\n }\n\n /**\n * * For each face with positive area . . . add edges as needed so that each face has one definitely lower node and one definite upper node.\n * * Hence tracing edges from the low node, there is a sequence of upward edges, reaching the upper, then a sequence of downward edges reaching the low node.\n * * This is an essential step for subsequent triangulation.\n *\n * @param graph\n */\n public static formMonotoneFaces(graph: HalfEdgeGraph) {\n\n const allFaces = graph.collectFaceLoops();\n graph.clearMask(HalfEdgeMask.VISITED);\n // For every face, break the face down into monotone sections\n for (const node of allFaces) {\n if (node.isMaskSet(HalfEdgeMask.VISITED))\n continue;\n const area = node.signedFaceArea();\n if (area <= 0.0) {\n node.setMaskAroundFace(HalfEdgeMask.VISITED);\n continue;\n }\n\n }\n }\n\n /**\n * * Visit all nodes in `graph`.\n * * invoke `pinch(node, vertexPredecessor)`\n * * this leaves the graph as isolated edges.\n * @param graph graph to modify\n */\n public static isolateAllEdges(graph: HalfEdgeGraph) {\n for (const nodeA of graph.allHalfEdges) {\n const nodeB = nodeA.vertexPredecessor;\n HalfEdge.pinch(nodeA, nodeB);\n }\n }\n\n}\n/**\n * @internal\n */\nexport class HalfEdgeGraphMerge {\n /** Simplest merge algorithm:\n * * collect array of (x,y,theta) at all nodes\n * * lexical sort of the array.\n * * twist all vertices together.\n * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.\n * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.\n * * Mask.NULL_FACE is cleared throughout and applied within null faces.\n */\n public static clusterAndMergeXYTheta(graph: HalfEdgeGraph, outboundRadiansFunction?: (he: HalfEdge) => number) {\n const allNodes = graph.allHalfEdges;\n const numNodes = allNodes.length;\n graph.clearMask(HalfEdgeMask.NULL_FACE);\n const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta, nodeIndex. But theta is not set in first round.\n for (let i = 0; i < numNodes; i++) {\n const nodeA = allNodes[i];\n const xA = nodeA.x;\n const yA = nodeA.y;\n HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop.\n clusters.addDirect(xA, yA, 0.0, i);\n }\n const order = clusters.clusterIndicesLexical();\n let k0 = 0;\n const numK = order.length;\n for (let k1 = 0; k1 < numK; k1++) {\n if (order[k1] === ClusterableArray.clusterTerminator) {\n // nodes identified in order[k0]..order[k1] are properly sorted around a vertex.\n if (k1 > k0) {\n const iA = clusters.getExtraData(order[k0], 1);\n const nodeA0 = allNodes[iA];\n for (let k = k0 + 1; k < k1; k++) {\n const iB = clusters.getExtraData(order[k], 1);\n const nodeB = allNodes[iB];\n nodeB.x = nodeA0.x;\n nodeB.y = nodeA0.y;\n }\n }\n k0 = k1 + 1;\n }\n }\n // NOW\n // 1) There are identical coordinates at all nodes around each vertex loop.\n // 2) Hence ready do sort (at each vertex) by theta.\n\n // insert theta as extra data in the sort table . . .\n for (const clusterTableIndex of order) {\n if (clusterTableIndex !== ClusterableArray.clusterTerminator) {\n const nodeA = allNodes[clusterTableIndex];\n const nodeB = nodeA.faceSuccessor;\n let radians = outboundRadiansFunction ? outboundRadiansFunction(nodeA) : Math.atan2(nodeB.y - nodeA.y, nodeB.x - nodeA.x);\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(radians, -Math.PI))\n radians = Math.PI;\n clusters.setExtraData(clusterTableIndex, 0, radians);\n }\n }\n clusters.sortSubsetsBySingleKey(order, 2);\n const unmatchedNullFaceNodes: HalfEdge[] = [];\n k0 = 0;\n let thetaA, thetaB;\n // now pinch each neighboring pair together\n for (let k1 = 0; k1 < numK; k1++) {\n if (order[k1] === ClusterableArray.clusterTerminator) {\n // nodes identified in order[k0]..order[k1] are properly sorted around a vertex.\n if (k1 > k0) {\n const iA = clusters.getExtraData(order[k0], 1);\n thetaA = clusters.getExtraData(order[k0], 0);\n const nodeA0 = allNodes[iA];\n let nodeA = nodeA0;\n for (let k = k0 + 1; k < k1; k++) {\n const iB = clusters.getExtraData(order[k], 1);\n thetaB = clusters.getExtraData(order[k], 0);\n const nodeB = allNodes[iB];\n if (nodeA.isMaskSet(HalfEdgeMask.NULL_FACE)) {\n // nope, this edge was flagged and pinched from the other end.\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\n if (j >= 0) {\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\n unmatchedNullFaceNodes.pop();\n }\n nodeA = nodeB;\n thetaA = thetaB;\n } else if (nodeB.isMaskSet(HalfEdgeMask.NULL_FACE)) {\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\n if (j >= 0) {\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\n unmatchedNullFaceNodes.pop();\n }\n // NO leave nodeA and thetaA ignore nodeB -- later step will get the outside of its banana.\n } else {\n HalfEdge.pinch(nodeA, nodeB);\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\n const nodeA1 = nodeA.faceSuccessor;\n const nodeB1 = nodeB.edgeMate;\n // WE TRUST -- nodeA1 and node B1 must have identical xy.\n // pinch them together and mark the face loop as null ..\n HalfEdge.pinch(nodeA1, nodeB1);\n nodeA.setMask(HalfEdgeMask.NULL_FACE);\n nodeB1.setMask(HalfEdgeMask.NULL_FACE);\n unmatchedNullFaceNodes.push(nodeB1);\n }\n nodeA = nodeB;\n thetaA = thetaB;\n }\n }\n }\n k0 = k1 + 1;\n }\n }\n }\n\n private static buildVerticalSweepPriorityQueue(graph: HalfEdgeGraph): HalfEdgePriorityQueueWithPartnerArray {\n const sweepHeap = new HalfEdgePriorityQueueWithPartnerArray();\n for (const p of graph.allHalfEdges) {\n\n if (HalfEdgeGraphOps.compareNodesYXUp(p, p.faceSuccessor) < 0) {\n sweepHeap.priorityQueue.push(p);\n }\n }\n return sweepHeap;\n }\n private static snapFractionToNode(xy: Point2d, fraction: number, node: HalfEdge, nodeFraction: number): number{\n if (Geometry.isSameCoordinate(xy.x, node.x) && Geometry.isSameCoordinate(xy.y, node.y))\n return nodeFraction;\n return fraction;\n}\n private static computeIntersectionFractionsOnEdges(nodeA0: HalfEdge, nodeB0: HalfEdge, fractions: Vector2d, pointA: Point2d, pointB: Point2d): boolean {\n const nodeA1 = nodeA0.faceSuccessor;\n const ax0 = nodeA0.x;\n const ay0 = nodeA0.y;\n const ux = nodeA1.x - ax0;\n const uy = nodeA1.y - ay0;\n const nodeB1 = nodeB0.faceSuccessor;\n const bx0 = nodeB0.x;\n const by0 = nodeB0.y;\n const vx = nodeB1.x - bx0;\n const vy = nodeB1.y - by0;\n if (SmallSystem.lineSegmentXYUVTransverseIntersectionUnbounded(ax0, ay0, ux, uy,\n bx0, by0, vx, vy, fractions)) {\n pointA.x = ax0 + fractions.x * ux;\n pointA.y = ay0 + fractions.x * uy;\n pointB.x = bx0 + fractions.y * vx;\n pointB.y = by0 + fractions.y * vy;\n fractions.x = this.snapFractionToNode(pointA, fractions.x, nodeA0, 0.0);\n fractions.x = this.snapFractionToNode(pointA, fractions.x, nodeA1, 1.0);\n fractions.y = this.snapFractionToNode(pointB, fractions.y, nodeB0, 0.0);\n fractions.y = this.snapFractionToNode(pointB, fractions.y, nodeB1, 1.0);\n return Geometry.isIn01(fractions.x) && Geometry.isIn01(fractions.y);\n }\n return false;\n }\n /**\n * Split edges at intersections.\n * * This is a large operation.\n * @param graph\n */\n public static splitIntersectingEdges(graph: HalfEdgeGraph): GraphSplitData {\n const data = new GraphSplitData();\n const sweepHeap = this.buildVerticalSweepPriorityQueue(graph);\n let nodeA0, nodeB1;\n const smallFraction = 1.0e-8;\n const largeFraction = 1.0 - smallFraction;\n let i;\n const fractions = Vector2d.create();\n const pointA = Point2d.create();\n const pointB = Point2d.create();\n let nodeB0;\n const popTolerance = Geometry.smallMetricDistance;\n while (undefined !== (nodeA0 = sweepHeap.priorityQueue.pop())) {\n data.numUpEdge++;\n const n0 = sweepHeap.activeEdges.length;\n sweepHeap.removeArrayMembersWithY1Below(nodeA0.y - popTolerance);\n data.numPopOut += n0 - sweepHeap.activeEdges.length;\n for (i = 0; i < sweepHeap.activeEdges.length; i++) {\n nodeB0 = sweepHeap.activeEdges[i];\n nodeB1 = nodeB0.faceSuccessor;\n // const nodeB1 = nodeB0.faceSuccessor;\n if (Geometry.isSameCoordinateXY(nodeA0.x, nodeA0.y, nodeB0.x, nodeB0.y)) {\n data.numA0B0++;\n } else if (Geometry.isSameCoordinateXY(nodeB1.x, nodeB1.y, nodeA0.x, nodeA0.y)) {\n data.numA0B1++;\n } else {\n data.numIntersectionTest++;\n if (this.computeIntersectionFractionsOnEdges(nodeA0, nodeB0, fractions, pointA, pointB)) {\n if (fractions.x > smallFraction && fractions.x < largeFraction) {\n const nodeC0 = graph.splitEdgeAtFraction(nodeA0, fractions.x);\n sweepHeap.priorityQueue.push(nodeC0); // The upper portion will be reviewed as a nodeA0 later !!!\n data.numSplit++;\n }\n if (fractions.y > smallFraction && fractions.y < largeFraction) {\n const nodeD0 = graph.splitEdgeAtFraction(nodeB0, fractions.y);\n sweepHeap.priorityQueue.push(nodeD0); // The upper portion will be reviewed as a nodeA0 later !!!\n data.numSplit++;\n }\n // existing nodeA0 and its shortened edge remain for further intersections\n }\n }\n }\n sweepHeap.activeEdges.push(nodeA0);\n }\n return data;\n }\n\n /**\n * Returns a graph structure formed from the given LineSegment array\n *\n * * Find all intersections among segments, and split them if necessary\n * * Record endpoints of every segment in the form X, Y, Theta; This information is stored as a new node and sorted to match up\n * vertices.\n * * For vertices that match up, pinch the nodes to create vertex loops, which in closed objects, will also eventually form face\n * loops\n */\n public static formGraphFromSegments(lineSegments: LineSegment3d[]): HalfEdgeGraph {\n // Structure of an index of the array: { xyTheta: Point3d, node: Node }\n const graph = new HalfEdgeGraph();\n HalfEdgeGraphOps.segmentArrayToGraphEdges(lineSegments, graph, HalfEdgeMask.BOUNDARY_EDGE);\n this.splitIntersectingEdges(graph);\n this.clusterAndMergeXYTheta(graph);\n\n return graph;\n }\n\n /**\n * * Input is random linestrings, not necessarily loops\n * * Graph gets full splitEdges, regularize, and triangulate.\n * @returns triangulated graph, or undefined if bad data.\n */\n public static formGraphFromChains(chains: MultiLineStringDataVariant, regularize: boolean = true, mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE): HalfEdgeGraph | undefined {\n if (chains.length < 1)\n return undefined;\n const graph = new HalfEdgeGraph();\n const chainSeeds = Triangulator.directCreateChainsFromCoordinates(graph, chains);\n for (const seed of chainSeeds)\n seed.setMaskAroundFace(mask);\n\n this.splitIntersectingEdges(graph);\n this.clusterAndMergeXYTheta(graph);\n if (regularize) {\n const context = new RegularizationContext(graph);\n context.regularizeGraph(true, true);\n }\n return graph;\n }\n\n}\n"]}
1
+ {"version":3,"file":"Merging.js","sourceRoot":"","sources":["../../../src/topology/Merging.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\nimport { LineSegment3d } from \"../curve/LineSegment3d\";\r\nimport { Geometry } from \"../Geometry\";\r\nimport { Angle } from \"../geometry3d/Angle\";\r\nimport { Point2d, Vector2d } from \"../geometry3d/Point2dVector2d\";\r\nimport { Range3d } from \"../geometry3d/Range\";\r\nimport { ClusterableArray } from \"../numerics/ClusterableArray\";\r\nimport { SmallSystem } from \"../numerics/Polynomials\";\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgePriorityQueueWithPartnerArray } from \"./HalfEdgePriorityQueue\";\r\nimport { RegularizationContext } from \"./RegularizeFace\";\r\nimport { MultiLineStringDataVariant, Triangulator } from \"./Triangulation\";\r\n\r\nexport class GraphSplitData {\r\n public numUpEdge = 0;\r\n public numIntersectionTest = 0;\r\n public numSplit = 0;\r\n public numPopOut = 0;\r\n public numA0B0 = 0;\r\n public numA0B1 = 0;\r\n public constructor() {\r\n }\r\n}\r\n\r\n/**\r\n * * Assorted methods used in algorithms on HalfEdgeGraph.\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphOps {\r\n\r\n /** Compare function for sorting with primary y compare, secondary x compare. */\r\n public static compareNodesYXUp(a: HalfEdge, b: HalfEdge) {\r\n // Check y's\r\n // if (!Geometry.isSameCoordinate(a.y, b.y))\r\n if (a.y < b.y)\r\n return -1;\r\n else if (a.y > b.y)\r\n return 1;\r\n // Check x's\r\n // if (!Geometry.isSameCoordinate(a.x, b.x))\r\n if (a.x < b.x)\r\n return -1;\r\n else if (a.x > b.x)\r\n return 1;\r\n return 0;\r\n }\r\n\r\n /** Return true if nodeB (a) is lower than both its neighbors and (b) inflects as a downward peak (rather than an upward trough) */\r\n public static isDownPeak(nodeB: HalfEdge) {\r\n const nodeA = nodeB.facePredecessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n return this.compareNodesYXUp(nodeB, nodeA) < 0\r\n && this.compareNodesYXUp(nodeB, nodeC) < 0\r\n && this.crossProductToTargets(nodeB, nodeA, nodeC) > 0;\r\n }\r\n\r\n /** return the cross product of vectors from base to targetA and base to targetB\r\n * @param base base vertex of both vectors.\r\n * @param targetA target vertex of first vector\r\n * @param targetB target vertex of second vector\r\n */\r\n public static crossProductToTargets(base: HalfEdge, targetA: HalfEdge, targetB: HalfEdge): number {\r\n return Geometry.crossProductXYXY(targetA.x - base.x, targetA.y - base.y, targetB.x - base.x, targetB.y - base.y);\r\n }\r\n\r\n // ---------------------------------------------------------------------------------------------------------------------\r\n // ----------------------------------------------------------------------------------------------------------------------\r\n\r\n public static graphRange(graph: HalfEdgeGraph): Range3d {\r\n const range = Range3d.create();\r\n for (const node of graph.allHalfEdges) {\r\n range.extendXYZ(node.x, node.y, node.z);\r\n }\r\n return range;\r\n }\r\n /** Returns an array of a all nodes (both ends) of edges created from segments. */\r\n public static segmentArrayToGraphEdges(segments: LineSegment3d[], returnGraph: HalfEdgeGraph, mask: HalfEdgeMask): HalfEdge[] {\r\n const result = [];\r\n let idxCounter = 0;\r\n\r\n // Push the endpoints of each segment onto arr[] in the form {(x, y, theta), Node}\r\n for (const segment of segments) {\r\n\r\n const node0 = returnGraph.createEdgeXYZXYZ(\r\n segment.point0Ref.x, segment.point0Ref.y, segment.point0Ref.z,\r\n idxCounter,\r\n segment.point1Ref.x, segment.point1Ref.y, segment.point1Ref.z,\r\n idxCounter + 1);\r\n\r\n const node1 = node0.edgeMate;\r\n idxCounter += 2;\r\n\r\n node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary\r\n result.push(node0);\r\n result.push(node1);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * * For each face with positive area . . . add edges as needed so that each face has one definitely lower node and one definite upper node.\r\n * * Hence tracing edges from the low node, there is a sequence of upward edges, reaching the upper, then a sequence of downward edges reaching the low node.\r\n * * This is an essential step for subsequent triangulation.\r\n *\r\n * @param graph\r\n */\r\n public static formMonotoneFaces(graph: HalfEdgeGraph) {\r\n\r\n const allFaces = graph.collectFaceLoops();\r\n graph.clearMask(HalfEdgeMask.VISITED);\r\n // For every face, break the face down into monotone sections\r\n for (const node of allFaces) {\r\n if (node.isMaskSet(HalfEdgeMask.VISITED))\r\n continue;\r\n const area = node.signedFaceArea();\r\n if (area <= 0.0) {\r\n node.setMaskAroundFace(HalfEdgeMask.VISITED);\r\n continue;\r\n }\r\n\r\n }\r\n }\r\n\r\n /**\r\n * * Visit all nodes in `graph`.\r\n * * invoke `pinch(node, vertexPredecessor)`\r\n * * this leaves the graph as isolated edges.\r\n * @param graph graph to modify\r\n */\r\n public static isolateAllEdges(graph: HalfEdgeGraph) {\r\n for (const nodeA of graph.allHalfEdges) {\r\n const nodeB = nodeA.vertexPredecessor;\r\n HalfEdge.pinch(nodeA, nodeB);\r\n }\r\n }\r\n\r\n}\r\n/**\r\n * @internal\r\n */\r\nexport class HalfEdgeGraphMerge {\r\n /** Simplest merge algorithm:\r\n * * collect array of (x,y,theta) at all nodes\r\n * * lexical sort of the array.\r\n * * twist all vertices together.\r\n * * This effectively creates valid face loops for a planar subdivision if there are no edge crossings.\r\n * * If there are edge crossings, the graph can be a (highly complicated) Klein bottle topology.\r\n * * Mask.NULL_FACE is cleared throughout and applied within null faces.\r\n */\r\n public static clusterAndMergeXYTheta(graph: HalfEdgeGraph, outboundRadiansFunction?: (he: HalfEdge) => number) {\r\n const allNodes = graph.allHalfEdges;\r\n const numNodes = allNodes.length;\r\n graph.clearMask(HalfEdgeMask.NULL_FACE);\r\n const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta, nodeIndex. But theta is not set in first round.\r\n for (let i = 0; i < numNodes; i++) {\r\n const nodeA = allNodes[i];\r\n const xA = nodeA.x;\r\n const yA = nodeA.y;\r\n HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop.\r\n clusters.addDirect(xA, yA, 0.0, i);\r\n }\r\n const order = clusters.clusterIndicesLexical();\r\n let k0 = 0;\r\n const numK = order.length;\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1] are properly sorted around a vertex.\r\n if (k1 > k0) {\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n const nodeA0 = allNodes[iA];\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n const nodeB = allNodes[iB];\r\n nodeB.x = nodeA0.x;\r\n nodeB.y = nodeA0.y;\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n // NOW\r\n // 1) There are identical coordinates at all nodes around each vertex loop.\r\n // 2) Hence ready do sort (at each vertex) by theta.\r\n\r\n // insert theta as extra data in the sort table . . .\r\n for (const clusterTableIndex of order) {\r\n if (clusterTableIndex !== ClusterableArray.clusterTerminator) {\r\n const nodeA = allNodes[clusterTableIndex];\r\n const nodeB = nodeA.faceSuccessor;\r\n let radians = outboundRadiansFunction ? outboundRadiansFunction(nodeA) : Math.atan2(nodeB.y - nodeA.y, nodeB.x - nodeA.x);\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(radians, -Math.PI))\r\n radians = Math.PI;\r\n clusters.setExtraData(clusterTableIndex, 0, radians);\r\n }\r\n }\r\n clusters.sortSubsetsBySingleKey(order, 2);\r\n const unmatchedNullFaceNodes: HalfEdge[] = [];\r\n k0 = 0;\r\n let thetaA, thetaB;\r\n // now pinch each neighboring pair together\r\n for (let k1 = 0; k1 < numK; k1++) {\r\n if (order[k1] === ClusterableArray.clusterTerminator) {\r\n // nodes identified in order[k0]..order[k1] are properly sorted around a vertex.\r\n if (k1 > k0) {\r\n const iA = clusters.getExtraData(order[k0], 1);\r\n thetaA = clusters.getExtraData(order[k0], 0);\r\n const nodeA0 = allNodes[iA];\r\n let nodeA = nodeA0;\r\n for (let k = k0 + 1; k < k1; k++) {\r\n const iB = clusters.getExtraData(order[k], 1);\r\n thetaB = clusters.getExtraData(order[k], 0);\r\n const nodeB = allNodes[iB];\r\n if (nodeA.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n // nope, this edge was flagged and pinched from the other end.\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n } else if (nodeB.isMaskSet(HalfEdgeMask.NULL_FACE)) {\r\n const j = unmatchedNullFaceNodes.findIndex((node: HalfEdge) => nodeA === node);\r\n if (j >= 0) {\r\n unmatchedNullFaceNodes[j] = unmatchedNullFaceNodes[unmatchedNullFaceNodes.length - 1];\r\n unmatchedNullFaceNodes.pop();\r\n }\r\n // NO leave nodeA and thetaA ignore nodeB -- later step will get the outside of its banana.\r\n } else {\r\n HalfEdge.pinch(nodeA, nodeB);\r\n if (Angle.isAlmostEqualRadiansAllowPeriodShift(thetaA, thetaB)) {\r\n const nodeA1 = nodeA.faceSuccessor;\r\n const nodeB1 = nodeB.edgeMate;\r\n // WE TRUST -- nodeA1 and node B1 must have identical xy.\r\n // pinch them together and mark the face loop as null ..\r\n HalfEdge.pinch(nodeA1, nodeB1);\r\n nodeA.setMask(HalfEdgeMask.NULL_FACE);\r\n nodeB1.setMask(HalfEdgeMask.NULL_FACE);\r\n unmatchedNullFaceNodes.push(nodeB1);\r\n }\r\n nodeA = nodeB;\r\n thetaA = thetaB;\r\n }\r\n }\r\n }\r\n k0 = k1 + 1;\r\n }\r\n }\r\n }\r\n\r\n private static buildVerticalSweepPriorityQueue(graph: HalfEdgeGraph): HalfEdgePriorityQueueWithPartnerArray {\r\n const sweepHeap = new HalfEdgePriorityQueueWithPartnerArray();\r\n for (const p of graph.allHalfEdges) {\r\n\r\n if (HalfEdgeGraphOps.compareNodesYXUp(p, p.faceSuccessor) < 0) {\r\n sweepHeap.priorityQueue.push(p);\r\n }\r\n }\r\n return sweepHeap;\r\n }\r\n private static snapFractionToNode(xy: Point2d, fraction: number, node: HalfEdge, nodeFraction: number): number{\r\n if (Geometry.isSameCoordinate(xy.x, node.x) && Geometry.isSameCoordinate(xy.y, node.y))\r\n return nodeFraction;\r\n return fraction;\r\n}\r\n private static computeIntersectionFractionsOnEdges(nodeA0: HalfEdge, nodeB0: HalfEdge, fractions: Vector2d, pointA: Point2d, pointB: Point2d): boolean {\r\n const nodeA1 = nodeA0.faceSuccessor;\r\n const ax0 = nodeA0.x;\r\n const ay0 = nodeA0.y;\r\n const ux = nodeA1.x - ax0;\r\n const uy = nodeA1.y - ay0;\r\n const nodeB1 = nodeB0.faceSuccessor;\r\n const bx0 = nodeB0.x;\r\n const by0 = nodeB0.y;\r\n const vx = nodeB1.x - bx0;\r\n const vy = nodeB1.y - by0;\r\n if (SmallSystem.lineSegmentXYUVTransverseIntersectionUnbounded(ax0, ay0, ux, uy,\r\n bx0, by0, vx, vy, fractions)) {\r\n pointA.x = ax0 + fractions.x * ux;\r\n pointA.y = ay0 + fractions.x * uy;\r\n pointB.x = bx0 + fractions.y * vx;\r\n pointB.y = by0 + fractions.y * vy;\r\n fractions.x = this.snapFractionToNode(pointA, fractions.x, nodeA0, 0.0);\r\n fractions.x = this.snapFractionToNode(pointA, fractions.x, nodeA1, 1.0);\r\n fractions.y = this.snapFractionToNode(pointB, fractions.y, nodeB0, 0.0);\r\n fractions.y = this.snapFractionToNode(pointB, fractions.y, nodeB1, 1.0);\r\n return Geometry.isIn01(fractions.x) && Geometry.isIn01(fractions.y);\r\n }\r\n return false;\r\n }\r\n /**\r\n * Split edges at intersections.\r\n * * This is a large operation.\r\n * @param graph\r\n */\r\n public static splitIntersectingEdges(graph: HalfEdgeGraph): GraphSplitData {\r\n const data = new GraphSplitData();\r\n const sweepHeap = this.buildVerticalSweepPriorityQueue(graph);\r\n let nodeA0, nodeB1;\r\n const smallFraction = 1.0e-8;\r\n const largeFraction = 1.0 - smallFraction;\r\n let i;\r\n const fractions = Vector2d.create();\r\n const pointA = Point2d.create();\r\n const pointB = Point2d.create();\r\n let nodeB0;\r\n const popTolerance = Geometry.smallMetricDistance;\r\n while (undefined !== (nodeA0 = sweepHeap.priorityQueue.pop())) {\r\n data.numUpEdge++;\r\n const n0 = sweepHeap.activeEdges.length;\r\n sweepHeap.removeArrayMembersWithY1Below(nodeA0.y - popTolerance);\r\n data.numPopOut += n0 - sweepHeap.activeEdges.length;\r\n for (i = 0; i < sweepHeap.activeEdges.length; i++) {\r\n nodeB0 = sweepHeap.activeEdges[i];\r\n nodeB1 = nodeB0.faceSuccessor;\r\n // const nodeB1 = nodeB0.faceSuccessor;\r\n if (Geometry.isSameCoordinateXY(nodeA0.x, nodeA0.y, nodeB0.x, nodeB0.y)) {\r\n data.numA0B0++;\r\n } else if (Geometry.isSameCoordinateXY(nodeB1.x, nodeB1.y, nodeA0.x, nodeA0.y)) {\r\n data.numA0B1++;\r\n } else {\r\n data.numIntersectionTest++;\r\n if (this.computeIntersectionFractionsOnEdges(nodeA0, nodeB0, fractions, pointA, pointB)) {\r\n if (fractions.x > smallFraction && fractions.x < largeFraction) {\r\n const nodeC0 = graph.splitEdgeAtFraction(nodeA0, fractions.x);\r\n sweepHeap.priorityQueue.push(nodeC0); // The upper portion will be reviewed as a nodeA0 later !!!\r\n data.numSplit++;\r\n }\r\n if (fractions.y > smallFraction && fractions.y < largeFraction) {\r\n const nodeD0 = graph.splitEdgeAtFraction(nodeB0, fractions.y);\r\n sweepHeap.priorityQueue.push(nodeD0); // The upper portion will be reviewed as a nodeA0 later !!!\r\n data.numSplit++;\r\n }\r\n // existing nodeA0 and its shortened edge remain for further intersections\r\n }\r\n }\r\n }\r\n sweepHeap.activeEdges.push(nodeA0);\r\n }\r\n return data;\r\n }\r\n\r\n /**\r\n * Returns a graph structure formed from the given LineSegment array\r\n *\r\n * * Find all intersections among segments, and split them if necessary\r\n * * Record endpoints of every segment in the form X, Y, Theta; This information is stored as a new node and sorted to match up\r\n * vertices.\r\n * * For vertices that match up, pinch the nodes to create vertex loops, which in closed objects, will also eventually form face\r\n * loops\r\n */\r\n public static formGraphFromSegments(lineSegments: LineSegment3d[]): HalfEdgeGraph {\r\n // Structure of an index of the array: { xyTheta: Point3d, node: Node }\r\n const graph = new HalfEdgeGraph();\r\n HalfEdgeGraphOps.segmentArrayToGraphEdges(lineSegments, graph, HalfEdgeMask.BOUNDARY_EDGE);\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n\r\n return graph;\r\n }\r\n\r\n /**\r\n * * Input is random linestrings, not necessarily loops\r\n * * Graph gets full splitEdges, regularize, and triangulate.\r\n * @returns triangulated graph, or undefined if bad data.\r\n */\r\n public static formGraphFromChains(chains: MultiLineStringDataVariant, regularize: boolean = true, mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE): HalfEdgeGraph | undefined {\r\n if (chains.length < 1)\r\n return undefined;\r\n const graph = new HalfEdgeGraph();\r\n const chainSeeds = Triangulator.directCreateChainsFromCoordinates(graph, chains);\r\n for (const seed of chainSeeds)\r\n seed.setMaskAroundFace(mask);\r\n\r\n this.splitIntersectingEdges(graph);\r\n this.clusterAndMergeXYTheta(graph);\r\n if (regularize) {\r\n const context = new RegularizationContext(graph);\r\n context.regularizeGraph(true, true);\r\n }\r\n return graph;\r\n }\r\n\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"RegularizeFace.js","sourceRoot":"","sources":["../../../src/topology/RegularizeFace.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module Topology\n */\n\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\nimport { HalfEdgeGraphOps } from \"./Merging\";\n\n// /* eslint-disable no-console */\n/**\n * * Context for regularizing single faces.\n * @internal\n */\nexport class RegularizationContext {\n // For debugging use ... \"almost always\" undefined.\n // If defined, it is called with each inserted node pair.\n // scale will be either plus or minus one.\n // when it is negative, the node coordinates (both x and y) have been negated.\n // The call is made after full insertion into vertex loop.\n public static announceEdge?: (graph: HalfEdgeGraph, nodeA: HalfEdge, nodeB: HalfEdge, scale: number) => void;\n public constructor(graph: HalfEdgeGraph) {\n this.graph = graph;\n this.upEdges = [];\n this.downEdges = [];\n this.bottomPeaks = [];\n this.topPeaks = [];\n this.localMin = [];\n this.localMax = [];\n }\n\n /**\n * These are public only for testing.\n */\n public graph: HalfEdgeGraph;\n /** array of edges directed upward. Turn can be left or right, but is not large enough to be a min or max */\n public upEdges: HalfEdge[];\n /** array of edges directed downward, Turn can be left or right, but is not large enough to be a min or max */\n public downEdges: HalfEdge[];\n /** Array of edges whose start is an upward peak (right turn, inbound up, outbound down) */\n public topPeaks: HalfEdge[];\n /** Array of edges whose start is an downward peak (right turn, inbound down, outbound up) */\n public bottomPeaks: HalfEdge[];\n\n /** Array of edges at local minima (left turn, inbound down, outbound up). Ensuing chain is up */\n public localMin: HalfEdge[];\n /** Array of edges at local maxima (left turn, inbound up, outbound down). Ensuing chain is down */\n public localMax: HalfEdge[];\n /**\n * Collect (and classify) all the edges around a single face.\n * * The various arrays are collected: upEdges, downEdges, topPeaks, bottomPeaks, upChains, downChains\n * @param faceSeed face to examine\n */\n public collectVerticalEventsAroundFace(faceSeed: HalfEdge) {\n let nodeA = faceSeed;\n let nodeB;\n let nodeC;\n let abUp;\n let bcUp;\n this.upEdges.length = 0;\n this.downEdges.length = 0;\n this.topPeaks.length = 0;\n this.bottomPeaks.length = 0;\n this.localMin.length = 0;\n this.localMax.length = 0;\n do {\n nodeB = nodeA.faceSuccessor;\n nodeC = nodeB.faceSuccessor;\n abUp = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB) < 0;\n bcUp = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC) < 0;\n if (abUp) {\n this.upEdges.push(nodeA);\n if (!bcUp) {\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) < 0)\n this.localMax.push(nodeB);\n else\n this.topPeaks.push(nodeB);\n }\n\n } else { // ab is DOWN\n this.downEdges.push(nodeA);\n if (bcUp) {\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) > 0)\n this.bottomPeaks.push(nodeB);\n else\n this.localMin.push(nodeB);\n }\n }\n nodeA = nodeB;\n } while (nodeA !== faceSeed);\n }\n\n /**\n * Collect (and classify) all the edges in an array.\n * * The various arrays are collected: upEdges, downEdges, topPeaks, bottomPeaks, upChains, downChains\n * @param candidateEdges array of edges.\n */\n public collectVerticalEventFromEdgesInAndArray(candidateEdges: HalfEdge[]) {\n let nodeA;\n let nodeB;\n let nodeC;\n let abUp;\n let bcUp;\n this.upEdges.length = 0;\n this.downEdges.length = 0;\n this.topPeaks.length = 0;\n this.bottomPeaks.length = 0;\n this.localMin.length = 0;\n this.localMax.length = 0;\n for (nodeA of candidateEdges) {\n nodeB = nodeA.faceSuccessor;\n nodeC = nodeB.faceSuccessor;\n abUp = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB) < 0;\n bcUp = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC) < 0;\n if (abUp) {\n this.upEdges.push(nodeA);\n if (!bcUp) {\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) < 0)\n this.localMax.push(nodeB);\n else\n this.topPeaks.push(nodeB);\n }\n\n } else { // ab is DOWN\n this.downEdges.push(nodeA);\n if (bcUp) {\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) > 0)\n this.bottomPeaks.push(nodeB);\n else\n this.localMin.push(nodeB);\n }\n }\n }\n }\n\n private swapArrays() {\n let save = this.downEdges; this.downEdges = this.upEdges; this.upEdges = save;\n save = this.localMax; this.localMax = this.localMin; this.localMin = save;\n save = this.topPeaks; this.topPeaks = this.bottomPeaks; this.bottomPeaks = save;\n }\n\n /**\n * Find the edge (among candidates) which is first struck by a \"rightward\" scan from node\n * * comparisonFunction determines scan sense\n * * HalfEdge.compareNodeYXTheta is an upward scan.\n * * HalfEdge.compareNodeYXThetaDownward is a downward scan.\n * @param node\n * @param candidates Array of nodes to search\n * @param nodeComparisonFunction function for lexical comparison.\n */\n private findTopVisibleEdge(node: HalfEdge, candidates: HalfEdge[],\n directionSign: number) {\n const y0 = node.y;\n const x0 = node.x;\n let dx;\n let distanceRight = Number.MAX_SAFE_INTEGER;\n let result: HalfEdge | undefined;\n for (const rightBase of candidates) {\n const rightTop = rightBase.faceSuccessor;\n if (rightBase === node || rightTop === node)\n continue;\n // for horizontal edge cases -- require edges ends to have strict sign change (no zeros!!)\n const cRight = HalfEdgeGraphOps.compareNodesYXUp(node, rightBase);\n const cTop = HalfEdgeGraphOps.compareNodesYXUp(node, rightTop);\n // console.log(node.id, rightBase.id, rightTop.id, cRight, cTop);\n if (cRight * cTop >= 0)\n continue;\n const fraction = HalfEdge.horizontalScanFraction01(rightBase, y0);\n if (fraction !== undefined) {\n dx = directionSign * (rightBase.fractionToX(fraction) - x0);\n if (dx > 0 && dx < distanceRight) {\n result = rightBase;\n distanceRight = dx;\n }\n }\n }\n return result;\n }\n /**\n *\n * @param downPeak a \"bottom\" node where the interior CCW loop has a local min\n * @param downEdgeStart (optional) node at the start (heading downwards!) of an edge that brackets downPeak on the left.\n * @param upEdgeStart (optional) node at the start (heading up!) of the edge that brackets downPeak on the right.\n */\n private highestUpPeakConnection(downPeak: HalfEdge, downEdgeStart: HalfEdge | undefined, upEdgeStart: HalfEdge | undefined): HalfEdge | undefined {\n let highestPeak;\n\n for (const upPeak of this.topPeaks) {\n const y0 = upPeak.y;\n const x0 = upPeak.x;\n // is upPeak higher than prior upPeak?\n if (highestPeak !== undefined && HalfEdgeGraphOps.compareNodesYXUp(upPeak, highestPeak) < 0)\n continue;\n // is upPeak BELOW downPeak, ABOVE both limit edges lower node, and between limit edge interiors.\n if (HalfEdgeGraphOps.compareNodesYXUp(upPeak, downPeak) < 0) {\n if (downEdgeStart) {\n const fraction = HalfEdge.horizontalScanFraction01(downEdgeStart, y0);\n if (fraction === undefined)\n continue;\n if (x0 <= downEdgeStart.fractionToX(fraction))\n continue;\n }\n if (upEdgeStart) {\n const fraction = HalfEdge.horizontalScanFraction01(upEdgeStart, y0);\n if (fraction === undefined)\n continue;\n if (upEdgeStart.fractionToX(fraction) <= x0)\n continue;\n }\n highestPeak = upPeak;\n }\n }\n return highestPeak;\n }\n\n private updateMaxNode(maxNode: HalfEdge | undefined, candidate: HalfEdge | undefined, compare: (a: HalfEdge, b: HalfEdge) => number): HalfEdge | undefined {\n if (!maxNode)\n return candidate;\n if (!candidate)\n return maxNode;\n // both are defined .. look for positive compare ...\n if (compare(maxNode, candidate) < 0)\n return candidate;\n return maxNode;\n }\n private negateXY() {\n for (const node of this.graph.allHalfEdges) {\n node.x *= -1;\n node.y *= -1;\n }\n }\n private downwardConnectionFromBottomPeak(node: HalfEdge): HalfEdge | undefined {\n let connectTo;\n const upFunction = HalfEdgeGraphOps.compareNodesYXUp;\n const upEdgeBase = this.findTopVisibleEdge(node, this.upEdges, 1.0)!;\n const downEdgeBase = this.findTopVisibleEdge(node, this.downEdges, -1.0)!;\n connectTo = this.updateMaxNode(connectTo, upEdgeBase, upFunction);\n if (downEdgeBase)\n connectTo = this.updateMaxNode(connectTo, downEdgeBase.faceSuccessor, upFunction);\n const upPeakConnection = this.highestUpPeakConnection(node, downEdgeBase, upEdgeBase);\n if (upPeakConnection !== undefined)\n connectTo = this.updateMaxNode(connectTo, upPeakConnection, upFunction);\n return connectTo;\n }\n /** Search around the vertex of nodeA for a nodeA1 such that nodeB is visible in the sector at nodeA1 */\n private findVisibleSector(nodeA: HalfEdge, nodeB: HalfEdge): HalfEdge | undefined {\n let nodeA1 = nodeA;\n do {\n if (HalfEdge.isNodeVisibleInSector(nodeB, nodeA1))\n return nodeA1;\n nodeA1 = nodeA1.vertexSuccessor;\n } while (nodeA1 !== nodeA);\n return undefined;\n }\n /**\n * Create an edge from (some node around the vertex of) nodeA to (some node around the vertex of) nodeB.\n * * looking around the vertex for alternate insertion corrects cusp insertion errors.\n * @param nodeA\n * @param nodeB\n */\n private joinNodes(nodeA: HalfEdge, nodeB: HalfEdge, direction: number): HalfEdge | undefined {\n const nodeC = this.graph.createEdgeXYZXYZ(nodeA.x, nodeA.y, nodeA.z, 0, nodeB.x, nodeB.y, nodeB.z, 0);\n const nodeA1 = this.findVisibleSector(nodeA, nodeB);\n const nodeB1 = this.findVisibleSector(nodeB, nodeA);\n if (nodeA1 !== undefined && nodeB1 !== undefined) {\n HalfEdge.pinch(nodeA1, nodeC);\n HalfEdge.pinch(nodeB1, nodeC.edgeMate);\n if (RegularizationContext.announceEdge)\n RegularizationContext.announceEdge(this.graph, nodeA, nodeB, direction);\n return nodeC;\n }\n return undefined;\n }\n /**\n * Regularize a single face.\n * * Insert edge from any downward interior vertex to something lower\n * * Insert an edge from each upward interior vertex to something higher.\n * * The face is split into smaller faces\n * * Each final face has at most one \"min\" and one \"max\", and is easy to triangulate with a bottom to top sweep.\n * * Normal usage is to sweep in both directions, i.e. use the default (true,true) for the upSweep and downSweep parameters.\n * @param faceSeed any representative half edge on the face\n * @param upSweep true to do the upward sweep.\n * @param downSweep true to do the downward sweep.\n */\n private runRegularization(upSweep: boolean = true, downSweep: boolean = true) {\n if (upSweep) {\n this.bottomPeaks.sort(HalfEdgeGraphOps.compareNodesYXUp);\n for (const bottomPeak of this.bottomPeaks) {\n // console.log(\"SEARCH\", bottomPeak.id, [bottomPeak.x, bottomPeak.y]);\n if (!HalfEdgeGraphOps.isDownPeak(bottomPeak))\n continue;\n const target = this.downwardConnectionFromBottomPeak(bottomPeak);\n if (target !== undefined) {\n // console.log(\"join\", bottomPeak.id, [bottomPeak.x, bottomPeak.y], target.id, [target.x, target.y]);\n this.joinNodes(bottomPeak, target, 1);\n }\n }\n }\n if (downSweep) {\n // flip the whole graph (ouch)\n this.negateXY();\n // swap the various p and down seeds ....\n this.swapArrays();\n this.bottomPeaks.sort(HalfEdgeGraphOps.compareNodesYXUp);\n for (const bottomPeak of this.bottomPeaks) {\n if (!HalfEdgeGraphOps.isDownPeak(bottomPeak))\n continue;\n const target = this.downwardConnectionFromBottomPeak(bottomPeak);\n if (target !== undefined) {\n this.joinNodes(bottomPeak, target, -1);\n }\n }\n this.negateXY();\n this.swapArrays();\n }\n }\n\n /**\n * Regularize a single face.\n * * Insert edge from any downward interior vertex to something lower\n * * Insert an edge from each upward interior vertex to something higher.\n * * The face is split into smaller faces\n * * Each final face has at most one \"min\" and one \"max\", and is easy to triangulate with a bottom to top sweep.\n * * Normal usage is to sweep in both directions, i.e. use the default (true,true) for the upSweep and downSweep parameters.\n * @param faceSeed any representative half edge on the face\n * @param upSweep true to do the upward sweep.\n * @param downSweep true to do the downward sweep.\n */\n public regularizeFace(faceSeed: HalfEdge, upSweep: boolean = true, downSweep: boolean = true) {\n this.collectVerticalEventsAroundFace(faceSeed);\n this.runRegularization(upSweep, downSweep);\n }\n\n public regularizeGraph(upSweep: boolean = true, downSweep: boolean = true) {\n this.collectVerticalEventFromEdgesInAndArray(this.graph.allHalfEdges);\n this.runRegularization(upSweep, downSweep);\n }\n\n /** test if a single face is monotone; if so, return its (single) min */\n public static isMonotoneFace(seed: HalfEdge): HalfEdge | undefined {\n let numMin = 0;\n let numMax = 0;\n let nodeMin: HalfEdge | undefined;\n let nodeA = seed;\n do {\n const nodeB = nodeA.faceSuccessor;\n const nodeC = nodeB.faceSuccessor;\n const ab = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB);\n const bc = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC);\n if (ab * bc <= 0) {\n if (ab > 0) {\n numMin++;\n nodeMin = nodeB;\n }\n if (bc > 0) {\n numMax++;\n }\n }\n } while ((nodeA = nodeA.faceSuccessor) !== seed);\n return numMin === 1 && numMax === 1 ? nodeMin : undefined;\n }\n /** Return faces filtered by area and test function.\n * * find one arbitrary representative of each face\n * * offer the candidate to the mutate function.\n * * collect results\n * @param mappedSeeds when filter returns a HalfEdge, collect it here\n * @param unmappedSeeds when filter does not return a half edge, collect the candidate.\n */\n public static collectMappedFaceRepresentatives(\n graph: HalfEdgeGraph,\n positiveAreaOnly: boolean,\n mutate: (seed: HalfEdge) => HalfEdge | undefined,\n mappedEdges: HalfEdge[] | undefined,\n unMappedSeeds: HalfEdge[] | undefined) {\n if (mappedEdges)\n mappedEdges.length = 0;\n if (unMappedSeeds)\n unMappedSeeds.length = 0;\n const mask = HalfEdgeMask.VISITED;\n graph.clearMask(mask);\n for (const seed of graph.allHalfEdges) {\n if (!seed.getMask(mask)) {\n seed.setMaskAroundFace(mask);\n if (!positiveAreaOnly || seed.signedFaceArea() > 0) {\n const edge = mutate(seed);\n if (edge) {\n if (mappedEdges)\n mappedEdges.push(edge);\n } else {\n if (unMappedSeeds)\n unMappedSeeds.push(seed);\n }\n }\n }\n }\n }\n\n}\n"]}
1
+ {"version":3,"file":"RegularizeFace.js","sourceRoot":"","sources":["../../../src/topology/RegularizeFace.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n\r\n/** @packageDocumentation\r\n * @module Topology\r\n */\r\n\r\nimport { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from \"./Graph\";\r\nimport { HalfEdgeGraphOps } from \"./Merging\";\r\n\r\n// /* eslint-disable no-console */\r\n/**\r\n * * Context for regularizing single faces.\r\n * @internal\r\n */\r\nexport class RegularizationContext {\r\n // For debugging use ... \"almost always\" undefined.\r\n // If defined, it is called with each inserted node pair.\r\n // scale will be either plus or minus one.\r\n // when it is negative, the node coordinates (both x and y) have been negated.\r\n // The call is made after full insertion into vertex loop.\r\n public static announceEdge?: (graph: HalfEdgeGraph, nodeA: HalfEdge, nodeB: HalfEdge, scale: number) => void;\r\n public constructor(graph: HalfEdgeGraph) {\r\n this.graph = graph;\r\n this.upEdges = [];\r\n this.downEdges = [];\r\n this.bottomPeaks = [];\r\n this.topPeaks = [];\r\n this.localMin = [];\r\n this.localMax = [];\r\n }\r\n\r\n /**\r\n * These are public only for testing.\r\n */\r\n public graph: HalfEdgeGraph;\r\n /** array of edges directed upward. Turn can be left or right, but is not large enough to be a min or max */\r\n public upEdges: HalfEdge[];\r\n /** array of edges directed downward, Turn can be left or right, but is not large enough to be a min or max */\r\n public downEdges: HalfEdge[];\r\n /** Array of edges whose start is an upward peak (right turn, inbound up, outbound down) */\r\n public topPeaks: HalfEdge[];\r\n /** Array of edges whose start is an downward peak (right turn, inbound down, outbound up) */\r\n public bottomPeaks: HalfEdge[];\r\n\r\n /** Array of edges at local minima (left turn, inbound down, outbound up). Ensuing chain is up */\r\n public localMin: HalfEdge[];\r\n /** Array of edges at local maxima (left turn, inbound up, outbound down). Ensuing chain is down */\r\n public localMax: HalfEdge[];\r\n /**\r\n * Collect (and classify) all the edges around a single face.\r\n * * The various arrays are collected: upEdges, downEdges, topPeaks, bottomPeaks, upChains, downChains\r\n * @param faceSeed face to examine\r\n */\r\n public collectVerticalEventsAroundFace(faceSeed: HalfEdge) {\r\n let nodeA = faceSeed;\r\n let nodeB;\r\n let nodeC;\r\n let abUp;\r\n let bcUp;\r\n this.upEdges.length = 0;\r\n this.downEdges.length = 0;\r\n this.topPeaks.length = 0;\r\n this.bottomPeaks.length = 0;\r\n this.localMin.length = 0;\r\n this.localMax.length = 0;\r\n do {\r\n nodeB = nodeA.faceSuccessor;\r\n nodeC = nodeB.faceSuccessor;\r\n abUp = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB) < 0;\r\n bcUp = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC) < 0;\r\n if (abUp) {\r\n this.upEdges.push(nodeA);\r\n if (!bcUp) {\r\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) < 0)\r\n this.localMax.push(nodeB);\r\n else\r\n this.topPeaks.push(nodeB);\r\n }\r\n\r\n } else { // ab is DOWN\r\n this.downEdges.push(nodeA);\r\n if (bcUp) {\r\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) > 0)\r\n this.bottomPeaks.push(nodeB);\r\n else\r\n this.localMin.push(nodeB);\r\n }\r\n }\r\n nodeA = nodeB;\r\n } while (nodeA !== faceSeed);\r\n }\r\n\r\n /**\r\n * Collect (and classify) all the edges in an array.\r\n * * The various arrays are collected: upEdges, downEdges, topPeaks, bottomPeaks, upChains, downChains\r\n * @param candidateEdges array of edges.\r\n */\r\n public collectVerticalEventFromEdgesInAndArray(candidateEdges: HalfEdge[]) {\r\n let nodeA;\r\n let nodeB;\r\n let nodeC;\r\n let abUp;\r\n let bcUp;\r\n this.upEdges.length = 0;\r\n this.downEdges.length = 0;\r\n this.topPeaks.length = 0;\r\n this.bottomPeaks.length = 0;\r\n this.localMin.length = 0;\r\n this.localMax.length = 0;\r\n for (nodeA of candidateEdges) {\r\n nodeB = nodeA.faceSuccessor;\r\n nodeC = nodeB.faceSuccessor;\r\n abUp = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB) < 0;\r\n bcUp = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC) < 0;\r\n if (abUp) {\r\n this.upEdges.push(nodeA);\r\n if (!bcUp) {\r\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) < 0)\r\n this.localMax.push(nodeB);\r\n else\r\n this.topPeaks.push(nodeB);\r\n }\r\n\r\n } else { // ab is DOWN\r\n this.downEdges.push(nodeA);\r\n if (bcUp) {\r\n if (HalfEdgeGraphOps.crossProductToTargets(nodeB, nodeA, nodeC) > 0)\r\n this.bottomPeaks.push(nodeB);\r\n else\r\n this.localMin.push(nodeB);\r\n }\r\n }\r\n }\r\n }\r\n\r\n private swapArrays() {\r\n let save = this.downEdges; this.downEdges = this.upEdges; this.upEdges = save;\r\n save = this.localMax; this.localMax = this.localMin; this.localMin = save;\r\n save = this.topPeaks; this.topPeaks = this.bottomPeaks; this.bottomPeaks = save;\r\n }\r\n\r\n /**\r\n * Find the edge (among candidates) which is first struck by a \"rightward\" scan from node\r\n * * comparisonFunction determines scan sense\r\n * * HalfEdge.compareNodeYXTheta is an upward scan.\r\n * * HalfEdge.compareNodeYXThetaDownward is a downward scan.\r\n * @param node\r\n * @param candidates Array of nodes to search\r\n * @param nodeComparisonFunction function for lexical comparison.\r\n */\r\n private findTopVisibleEdge(node: HalfEdge, candidates: HalfEdge[],\r\n directionSign: number) {\r\n const y0 = node.y;\r\n const x0 = node.x;\r\n let dx;\r\n let distanceRight = Number.MAX_SAFE_INTEGER;\r\n let result: HalfEdge | undefined;\r\n for (const rightBase of candidates) {\r\n const rightTop = rightBase.faceSuccessor;\r\n if (rightBase === node || rightTop === node)\r\n continue;\r\n // for horizontal edge cases -- require edges ends to have strict sign change (no zeros!!)\r\n const cRight = HalfEdgeGraphOps.compareNodesYXUp(node, rightBase);\r\n const cTop = HalfEdgeGraphOps.compareNodesYXUp(node, rightTop);\r\n // console.log(node.id, rightBase.id, rightTop.id, cRight, cTop);\r\n if (cRight * cTop >= 0)\r\n continue;\r\n const fraction = HalfEdge.horizontalScanFraction01(rightBase, y0);\r\n if (fraction !== undefined) {\r\n dx = directionSign * (rightBase.fractionToX(fraction) - x0);\r\n if (dx > 0 && dx < distanceRight) {\r\n result = rightBase;\r\n distanceRight = dx;\r\n }\r\n }\r\n }\r\n return result;\r\n }\r\n /**\r\n *\r\n * @param downPeak a \"bottom\" node where the interior CCW loop has a local min\r\n * @param downEdgeStart (optional) node at the start (heading downwards!) of an edge that brackets downPeak on the left.\r\n * @param upEdgeStart (optional) node at the start (heading up!) of the edge that brackets downPeak on the right.\r\n */\r\n private highestUpPeakConnection(downPeak: HalfEdge, downEdgeStart: HalfEdge | undefined, upEdgeStart: HalfEdge | undefined): HalfEdge | undefined {\r\n let highestPeak;\r\n\r\n for (const upPeak of this.topPeaks) {\r\n const y0 = upPeak.y;\r\n const x0 = upPeak.x;\r\n // is upPeak higher than prior upPeak?\r\n if (highestPeak !== undefined && HalfEdgeGraphOps.compareNodesYXUp(upPeak, highestPeak) < 0)\r\n continue;\r\n // is upPeak BELOW downPeak, ABOVE both limit edges lower node, and between limit edge interiors.\r\n if (HalfEdgeGraphOps.compareNodesYXUp(upPeak, downPeak) < 0) {\r\n if (downEdgeStart) {\r\n const fraction = HalfEdge.horizontalScanFraction01(downEdgeStart, y0);\r\n if (fraction === undefined)\r\n continue;\r\n if (x0 <= downEdgeStart.fractionToX(fraction))\r\n continue;\r\n }\r\n if (upEdgeStart) {\r\n const fraction = HalfEdge.horizontalScanFraction01(upEdgeStart, y0);\r\n if (fraction === undefined)\r\n continue;\r\n if (upEdgeStart.fractionToX(fraction) <= x0)\r\n continue;\r\n }\r\n highestPeak = upPeak;\r\n }\r\n }\r\n return highestPeak;\r\n }\r\n\r\n private updateMaxNode(maxNode: HalfEdge | undefined, candidate: HalfEdge | undefined, compare: (a: HalfEdge, b: HalfEdge) => number): HalfEdge | undefined {\r\n if (!maxNode)\r\n return candidate;\r\n if (!candidate)\r\n return maxNode;\r\n // both are defined .. look for positive compare ...\r\n if (compare(maxNode, candidate) < 0)\r\n return candidate;\r\n return maxNode;\r\n }\r\n private negateXY() {\r\n for (const node of this.graph.allHalfEdges) {\r\n node.x *= -1;\r\n node.y *= -1;\r\n }\r\n }\r\n private downwardConnectionFromBottomPeak(node: HalfEdge): HalfEdge | undefined {\r\n let connectTo;\r\n const upFunction = HalfEdgeGraphOps.compareNodesYXUp;\r\n const upEdgeBase = this.findTopVisibleEdge(node, this.upEdges, 1.0)!;\r\n const downEdgeBase = this.findTopVisibleEdge(node, this.downEdges, -1.0)!;\r\n connectTo = this.updateMaxNode(connectTo, upEdgeBase, upFunction);\r\n if (downEdgeBase)\r\n connectTo = this.updateMaxNode(connectTo, downEdgeBase.faceSuccessor, upFunction);\r\n const upPeakConnection = this.highestUpPeakConnection(node, downEdgeBase, upEdgeBase);\r\n if (upPeakConnection !== undefined)\r\n connectTo = this.updateMaxNode(connectTo, upPeakConnection, upFunction);\r\n return connectTo;\r\n }\r\n /** Search around the vertex of nodeA for a nodeA1 such that nodeB is visible in the sector at nodeA1 */\r\n private findVisibleSector(nodeA: HalfEdge, nodeB: HalfEdge): HalfEdge | undefined {\r\n let nodeA1 = nodeA;\r\n do {\r\n if (HalfEdge.isNodeVisibleInSector(nodeB, nodeA1))\r\n return nodeA1;\r\n nodeA1 = nodeA1.vertexSuccessor;\r\n } while (nodeA1 !== nodeA);\r\n return undefined;\r\n }\r\n /**\r\n * Create an edge from (some node around the vertex of) nodeA to (some node around the vertex of) nodeB.\r\n * * looking around the vertex for alternate insertion corrects cusp insertion errors.\r\n * @param nodeA\r\n * @param nodeB\r\n */\r\n private joinNodes(nodeA: HalfEdge, nodeB: HalfEdge, direction: number): HalfEdge | undefined {\r\n const nodeC = this.graph.createEdgeXYZXYZ(nodeA.x, nodeA.y, nodeA.z, 0, nodeB.x, nodeB.y, nodeB.z, 0);\r\n const nodeA1 = this.findVisibleSector(nodeA, nodeB);\r\n const nodeB1 = this.findVisibleSector(nodeB, nodeA);\r\n if (nodeA1 !== undefined && nodeB1 !== undefined) {\r\n HalfEdge.pinch(nodeA1, nodeC);\r\n HalfEdge.pinch(nodeB1, nodeC.edgeMate);\r\n if (RegularizationContext.announceEdge)\r\n RegularizationContext.announceEdge(this.graph, nodeA, nodeB, direction);\r\n return nodeC;\r\n }\r\n return undefined;\r\n }\r\n /**\r\n * Regularize a single face.\r\n * * Insert edge from any downward interior vertex to something lower\r\n * * Insert an edge from each upward interior vertex to something higher.\r\n * * The face is split into smaller faces\r\n * * Each final face has at most one \"min\" and one \"max\", and is easy to triangulate with a bottom to top sweep.\r\n * * Normal usage is to sweep in both directions, i.e. use the default (true,true) for the upSweep and downSweep parameters.\r\n * @param faceSeed any representative half edge on the face\r\n * @param upSweep true to do the upward sweep.\r\n * @param downSweep true to do the downward sweep.\r\n */\r\n private runRegularization(upSweep: boolean = true, downSweep: boolean = true) {\r\n if (upSweep) {\r\n this.bottomPeaks.sort(HalfEdgeGraphOps.compareNodesYXUp);\r\n for (const bottomPeak of this.bottomPeaks) {\r\n // console.log(\"SEARCH\", bottomPeak.id, [bottomPeak.x, bottomPeak.y]);\r\n if (!HalfEdgeGraphOps.isDownPeak(bottomPeak))\r\n continue;\r\n const target = this.downwardConnectionFromBottomPeak(bottomPeak);\r\n if (target !== undefined) {\r\n // console.log(\"join\", bottomPeak.id, [bottomPeak.x, bottomPeak.y], target.id, [target.x, target.y]);\r\n this.joinNodes(bottomPeak, target, 1);\r\n }\r\n }\r\n }\r\n if (downSweep) {\r\n // flip the whole graph (ouch)\r\n this.negateXY();\r\n // swap the various p and down seeds ....\r\n this.swapArrays();\r\n this.bottomPeaks.sort(HalfEdgeGraphOps.compareNodesYXUp);\r\n for (const bottomPeak of this.bottomPeaks) {\r\n if (!HalfEdgeGraphOps.isDownPeak(bottomPeak))\r\n continue;\r\n const target = this.downwardConnectionFromBottomPeak(bottomPeak);\r\n if (target !== undefined) {\r\n this.joinNodes(bottomPeak, target, -1);\r\n }\r\n }\r\n this.negateXY();\r\n this.swapArrays();\r\n }\r\n }\r\n\r\n /**\r\n * Regularize a single face.\r\n * * Insert edge from any downward interior vertex to something lower\r\n * * Insert an edge from each upward interior vertex to something higher.\r\n * * The face is split into smaller faces\r\n * * Each final face has at most one \"min\" and one \"max\", and is easy to triangulate with a bottom to top sweep.\r\n * * Normal usage is to sweep in both directions, i.e. use the default (true,true) for the upSweep and downSweep parameters.\r\n * @param faceSeed any representative half edge on the face\r\n * @param upSweep true to do the upward sweep.\r\n * @param downSweep true to do the downward sweep.\r\n */\r\n public regularizeFace(faceSeed: HalfEdge, upSweep: boolean = true, downSweep: boolean = true) {\r\n this.collectVerticalEventsAroundFace(faceSeed);\r\n this.runRegularization(upSweep, downSweep);\r\n }\r\n\r\n public regularizeGraph(upSweep: boolean = true, downSweep: boolean = true) {\r\n this.collectVerticalEventFromEdgesInAndArray(this.graph.allHalfEdges);\r\n this.runRegularization(upSweep, downSweep);\r\n }\r\n\r\n /** test if a single face is monotone; if so, return its (single) min */\r\n public static isMonotoneFace(seed: HalfEdge): HalfEdge | undefined {\r\n let numMin = 0;\r\n let numMax = 0;\r\n let nodeMin: HalfEdge | undefined;\r\n let nodeA = seed;\r\n do {\r\n const nodeB = nodeA.faceSuccessor;\r\n const nodeC = nodeB.faceSuccessor;\r\n const ab = HalfEdgeGraphOps.compareNodesYXUp(nodeA, nodeB);\r\n const bc = HalfEdgeGraphOps.compareNodesYXUp(nodeB, nodeC);\r\n if (ab * bc <= 0) {\r\n if (ab > 0) {\r\n numMin++;\r\n nodeMin = nodeB;\r\n }\r\n if (bc > 0) {\r\n numMax++;\r\n }\r\n }\r\n } while ((nodeA = nodeA.faceSuccessor) !== seed);\r\n return numMin === 1 && numMax === 1 ? nodeMin : undefined;\r\n }\r\n /** Return faces filtered by area and test function.\r\n * * find one arbitrary representative of each face\r\n * * offer the candidate to the mutate function.\r\n * * collect results\r\n * @param mappedSeeds when filter returns a HalfEdge, collect it here\r\n * @param unmappedSeeds when filter does not return a half edge, collect the candidate.\r\n */\r\n public static collectMappedFaceRepresentatives(\r\n graph: HalfEdgeGraph,\r\n positiveAreaOnly: boolean,\r\n mutate: (seed: HalfEdge) => HalfEdge | undefined,\r\n mappedEdges: HalfEdge[] | undefined,\r\n unMappedSeeds: HalfEdge[] | undefined) {\r\n if (mappedEdges)\r\n mappedEdges.length = 0;\r\n if (unMappedSeeds)\r\n unMappedSeeds.length = 0;\r\n const mask = HalfEdgeMask.VISITED;\r\n graph.clearMask(mask);\r\n for (const seed of graph.allHalfEdges) {\r\n if (!seed.getMask(mask)) {\r\n seed.setMaskAroundFace(mask);\r\n if (!positiveAreaOnly || seed.signedFaceArea() > 0) {\r\n const edge = mutate(seed);\r\n if (edge) {\r\n if (mappedEdges)\r\n mappedEdges.push(edge);\r\n } else {\r\n if (unMappedSeeds)\r\n unMappedSeeds.push(seed);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n}\r\n"]}