@itwin/core-geometry 5.2.0 → 5.2.1

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +6 -1
  2. package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
  3. package/lib/cjs/curve/Arc3d.js +5 -7
  4. package/lib/cjs/curve/Arc3d.js.map +1 -1
  5. package/lib/cjs/curve/CurveOps.d.ts +2 -5
  6. package/lib/cjs/curve/CurveOps.d.ts.map +1 -1
  7. package/lib/cjs/curve/CurveOps.js +2 -5
  8. package/lib/cjs/curve/CurveOps.js.map +1 -1
  9. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts +50 -15
  10. package/lib/cjs/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  11. package/lib/cjs/curve/Query/PlanarSubdivision.js +102 -84
  12. package/lib/cjs/curve/Query/PlanarSubdivision.js.map +1 -1
  13. package/lib/cjs/curve/RegionOps.d.ts +44 -25
  14. package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
  15. package/lib/cjs/curve/RegionOps.js +74 -39
  16. package/lib/cjs/curve/RegionOps.js.map +1 -1
  17. package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  18. package/lib/cjs/curve/RegionOpsClassificationSweeps.js +8 -8
  19. package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
  20. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  21. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  22. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  23. package/lib/cjs/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  24. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +2 -1
  25. package/lib/cjs/geometry3d/GrowableXYArray.d.ts.map +1 -1
  26. package/lib/cjs/geometry3d/GrowableXYArray.js +2 -1
  27. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  28. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts +2 -1
  29. package/lib/cjs/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  30. package/lib/cjs/geometry3d/GrowableXYZArray.js +2 -1
  31. package/lib/cjs/geometry3d/GrowableXYZArray.js.map +1 -1
  32. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts +9 -16
  33. package/lib/cjs/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  34. package/lib/cjs/geometry3d/IndexedXYZCollection.js +3 -3
  35. package/lib/cjs/geometry3d/IndexedXYZCollection.js.map +1 -1
  36. package/lib/cjs/geometry3d/PolylineOps.d.ts +2 -2
  37. package/lib/cjs/geometry3d/PolylineOps.js +2 -2
  38. package/lib/cjs/geometry3d/PolylineOps.js.map +1 -1
  39. package/lib/cjs/numerics/ClusterableArray.d.ts.map +1 -1
  40. package/lib/cjs/numerics/ClusterableArray.js +2 -2
  41. package/lib/cjs/numerics/ClusterableArray.js.map +1 -1
  42. package/lib/cjs/topology/Merging.d.ts +15 -7
  43. package/lib/cjs/topology/Merging.d.ts.map +1 -1
  44. package/lib/cjs/topology/Merging.js +15 -10
  45. package/lib/cjs/topology/Merging.js.map +1 -1
  46. package/lib/esm/curve/Arc3d.d.ts.map +1 -1
  47. package/lib/esm/curve/Arc3d.js +5 -7
  48. package/lib/esm/curve/Arc3d.js.map +1 -1
  49. package/lib/esm/curve/CurveOps.d.ts +2 -5
  50. package/lib/esm/curve/CurveOps.d.ts.map +1 -1
  51. package/lib/esm/curve/CurveOps.js +2 -5
  52. package/lib/esm/curve/CurveOps.js.map +1 -1
  53. package/lib/esm/curve/Query/PlanarSubdivision.d.ts +50 -15
  54. package/lib/esm/curve/Query/PlanarSubdivision.d.ts.map +1 -1
  55. package/lib/esm/curve/Query/PlanarSubdivision.js +102 -84
  56. package/lib/esm/curve/Query/PlanarSubdivision.js.map +1 -1
  57. package/lib/esm/curve/RegionOps.d.ts +44 -25
  58. package/lib/esm/curve/RegionOps.d.ts.map +1 -1
  59. package/lib/esm/curve/RegionOps.js +72 -37
  60. package/lib/esm/curve/RegionOps.js.map +1 -1
  61. package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
  62. package/lib/esm/curve/RegionOpsClassificationSweeps.js +8 -8
  63. package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
  64. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts +1 -0
  65. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.d.ts.map +1 -1
  66. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js +102 -92
  67. package/lib/esm/curve/internalContexts/CurveCurveIntersectXY.js.map +1 -1
  68. package/lib/esm/geometry3d/GrowableXYArray.d.ts +2 -1
  69. package/lib/esm/geometry3d/GrowableXYArray.d.ts.map +1 -1
  70. package/lib/esm/geometry3d/GrowableXYArray.js +2 -1
  71. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  72. package/lib/esm/geometry3d/GrowableXYZArray.d.ts +2 -1
  73. package/lib/esm/geometry3d/GrowableXYZArray.d.ts.map +1 -1
  74. package/lib/esm/geometry3d/GrowableXYZArray.js +2 -1
  75. package/lib/esm/geometry3d/GrowableXYZArray.js.map +1 -1
  76. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts +9 -16
  77. package/lib/esm/geometry3d/IndexedXYZCollection.d.ts.map +1 -1
  78. package/lib/esm/geometry3d/IndexedXYZCollection.js +3 -3
  79. package/lib/esm/geometry3d/IndexedXYZCollection.js.map +1 -1
  80. package/lib/esm/geometry3d/PolylineOps.d.ts +2 -2
  81. package/lib/esm/geometry3d/PolylineOps.js +2 -2
  82. package/lib/esm/geometry3d/PolylineOps.js.map +1 -1
  83. package/lib/esm/numerics/ClusterableArray.d.ts.map +1 -1
  84. package/lib/esm/numerics/ClusterableArray.js +2 -2
  85. package/lib/esm/numerics/ClusterableArray.js.map +1 -1
  86. package/lib/esm/topology/Merging.d.ts +15 -7
  87. package/lib/esm/topology/Merging.d.ts.map +1 -1
  88. package/lib/esm/topology/Merging.js +15 -10
  89. package/lib/esm/topology/Merging.js.map +1 -1
  90. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"CurveOps.d.ts","sourceRoot":"","sources":["../../../src/curve/CurveOps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CurveOps.d.ts","sourceRoot":"","sources":["../../../src/curve/CurveOps.ts"],"names":[],"mappings":"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"}
@@ -183,8 +183,7 @@ export class CurveOps {
183
183
  /**
184
184
  * Check whether or not the curves are planar, and if so, return a localToWorld frame.
185
185
  * @param curves input geometry: curves or points.
186
- * @param tolerance optional maximum allowable planar deviation, default [[Geometry.smallMetricDistance]].
187
- * @param result optional pre-allocated object to populate and return.
186
+ * @param options bundle of options.
188
187
  * @returns localToWorld frame `T` for coplanar curves, or undefined if they are not coplanar.
189
188
  * `T` satisfies:
190
189
  * * `T.origin` is in the plane.
@@ -204,9 +203,7 @@ export class CurveOps {
204
203
  * Check whether or not the curves lie in a straight line, and if so, return a colinear ray.
205
204
  * * This test does not take curve traversal or point order into account.
206
205
  * @param curves input geometry: curves or points.
207
- * @param xyOnly whether to ignore z-coordinates of input geometry.
208
- * @param tolerance optional maximum allowable linear deviation, default [[Geometry.smallMetricDistance]].
209
- * @param result optional pre-allocated object to populate and return.
206
+ * @param options bundle of options.
210
207
  * @returns ray colinear with input, or undefined if input is not colinear.
211
208
  */
212
209
  static isColinear(curves, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"CurveOps.js","sourceRoot":"","sources":["../../../src/curve/CurveOps.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 Curve\r\n */\r\n\r\nimport { AxisIndex, Geometry } from \"../Geometry\";\r\nimport { FrameBuilder } from \"../geometry3d/FrameBuilder\";\r\nimport { MultiLineStringDataVariant } from \"../geometry3d/IndexedXYZCollection\";\r\nimport { Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { Range3d } from \"../geometry3d/Range\";\r\nimport { Ray3d } from \"../geometry3d/Ray3d\";\r\nimport { Transform } from \"../geometry3d/Transform\";\r\nimport { BagOfCurves, CurveCollection } from \"./CurveCollection\";\r\nimport { CurvePrimitive } from \"./CurvePrimitive\";\r\nimport { AnyChain, AnyCurve } from \"./CurveTypes\";\r\nimport { GeometryQuery } from \"./GeometryQuery\";\r\nimport { MultiChainCollector } from \"./internalContexts/MultiChainCollector\";\r\nimport { CurveChainWireOffsetContext } from \"./internalContexts/PolygonOffsetContext\";\r\nimport { LineString3d } from \"./LineString3d\";\r\nimport { Loop } from \"./Loop\";\r\nimport { OffsetOptions } from \"./OffsetOptions\";\r\nimport { Path } from \"./Path\";\r\nimport { StrokeOptions } from \"./StrokeOptions\";\r\n\r\n /**\r\n * Options bundle for use in [[CurveOps.isPlanar]] and [[CurveOps.isColinear]].\r\n * @public\r\n */\r\n export interface PlanarColinearOptions {\r\n /** Maximum allowable distance that geometry can deviate from planarity/colinearity. Default is [[Geometry.smallMetricDistance]]. */\r\n maxDeviation?: number;\r\n /** Whether colinearity test ignores z-coordinates. Default is `false`. */\r\n xyColinear?: boolean;\r\n /** Radian tolerance for xy-colinearity, measuring maximum angular deviation from a vertical plane. Default is [[Geometry.smallAngleRadians]]. */\r\n radianTolerance?: number;\r\n /** Pre-allocated object to populate with the computed plane-to-world transformation and return when planarity test succeeds. */\r\n localToWorld?: Transform;\r\n /** Pre-allocated object to populate with the computed line and return when colinear test succeeds. */\r\n colinearRay?: Ray3d;\r\n }\r\n\r\n/**\r\n * Static methods for miscellaneous curve operations.\r\n * @public\r\n */\r\nexport class CurveOps {\r\n /** Recursively sum curve lengths, allowing CurvePrimitive, CurveCollection, or array of such at any level. */\r\n public static sumLengths(curves: AnyCurve | AnyCurve[]): number {\r\n let mySum = 0;\r\n if (curves instanceof CurvePrimitive) {\r\n mySum += curves.curveLength();\r\n } else if (curves instanceof CurveCollection) {\r\n mySum += curves.sumLengths();\r\n } else if (Array.isArray(curves)) {\r\n for (const data1 of curves)\r\n mySum += this.sumLengths(data1);\r\n }\r\n return mySum;\r\n }\r\n /** Recursively extend the range by each curve's range, allowing CurvePrimitive, CurveCollection, or array of such at any level. */\r\n public static extendRange(range: Range3d, curves: AnyCurve | AnyCurve[], transform?: Transform): Range3d {\r\n if (Array.isArray(curves)) {\r\n for (const data1 of curves)\r\n this.extendRange(range, data1, transform);\r\n } else {\r\n curves.extendRange(range, transform);\r\n }\r\n return range;\r\n }\r\n /**\r\n * Construct a separate xy-offset for each input curve.\r\n * * For best offset results, the inputs should be parallel to the xy-plane.\r\n * @param curves input curve(s), z-coordinates ignored. Only curves of type [[AnyChain]] are handled.\r\n * @param offset offset distance (positive to left of curve, negative to right)\r\n * @param result array to collect offset curves\r\n * @returns summed length of offset curves\r\n */\r\n public static appendXYOffsets(curves: AnyCurve | AnyCurve[] | undefined, offset: number, result: AnyCurve[]): number {\r\n let summedLengths = 0;\r\n if (curves instanceof CurvePrimitive) {\r\n const resultA = CurveChainWireOffsetContext.constructCurveXYOffset(Path.create(curves), offset);\r\n if (resultA) {\r\n summedLengths += this.sumLengths(resultA);\r\n result.push(resultA);\r\n }\r\n } else if (curves instanceof Loop || curves instanceof Path) {\r\n const resultA = CurveChainWireOffsetContext.constructCurveXYOffset(curves, offset);\r\n if (resultA) {\r\n summedLengths += this.sumLengths(resultA);\r\n result.push(resultA);\r\n }\r\n } else if (curves instanceof BagOfCurves) {\r\n for (const q of curves.children)\r\n summedLengths += this.appendXYOffsets(q, offset, result);\r\n } else if (Array.isArray(curves)) {\r\n for (const q of curves)\r\n summedLengths += this.appendXYOffsets(q, offset, result);\r\n }\r\n return summedLengths;\r\n }\r\n /**\r\n * Restructure curve fragments as Paths and Loops, and construct xy-offsets of the chains.\r\n * * If the inputs do not form Loop(s), the classification of offsets is suspect.\r\n * * For best offset results, the inputs should be parallel to the xy-plane.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained and offset\r\n * @param offsetDistance offset distance, applied to both sides of each fragment to produce inside and outside xy-offset curves.\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when joining head-to-tail\r\n * @returns object with named chains, insideOffsets, outsideOffsets\r\n */\r\n public static collectInsideAndOutsideXYOffsets(fragments: AnyCurve[], offsetDistance: number, gapTolerance: number): { insideOffsets: AnyCurve[], outsideOffsets: AnyCurve[], chains?: AnyChain } {\r\n const collector = new MultiChainCollector(gapTolerance, gapTolerance);\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n const chains = collector.grabResult(true);\r\n const myOffsetA: CurveCollection[] = [];\r\n const myOffsetB: CurveCollection[] = [];\r\n const offsetLengthA = CurveOps.appendXYOffsets(chains, offsetDistance, myOffsetA);\r\n const offsetLengthB = CurveOps.appendXYOffsets(chains, -offsetDistance, myOffsetB);\r\n if (offsetLengthA > offsetLengthB) {\r\n return { outsideOffsets: myOffsetA, insideOffsets: myOffsetB, chains };\r\n } else {\r\n return { insideOffsets: myOffsetA, outsideOffsets: myOffsetB, chains };\r\n }\r\n }\r\n /**\r\n * Construct curves that are offset from a Path or Loop as viewed in xy-plane (ignoring z).\r\n * * The construction will remove \"some\" local effects of features smaller than the offset distance, but will not detect self intersection among widely separated edges.\r\n * @param curves base curves.\r\n * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object.\r\n */\r\n public static constructCurveXYOffset(curves: Path | Loop, offsetDistanceOrOptions: number | OffsetOptions): CurveCollection | undefined {\r\n return CurveChainWireOffsetContext.constructCurveXYOffset(curves, offsetDistanceOrOptions);\r\n }\r\n /**\r\n * Create the offset of a single curve primitive as viewed in the xy-plane (ignoring z).\r\n * @param curve primitive to offset\r\n * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object\r\n */\r\n public static createSingleOffsetPrimitiveXY(curve: CurvePrimitive, offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined {\r\n return CurveChainWireOffsetContext.createSingleOffsetPrimitiveXY(curve, offsetDistanceOrOptions);\r\n }\r\n /**\r\n * Restructure curve fragments as Paths and Loops.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when assembling fragments head-to-tail\r\n * @param planeTolerance tolerance for considering a closed chain to be planar. If undefined, only create Path. If defined, create Loops for closed chains within tolerance of a plane.\r\n * @returns chains, possibly wrapped in a [[BagOfCurves]].\r\n */\r\n public static collectChains(fragments: AnyCurve[], gapTolerance: number = Geometry.smallMetricDistance, planeTolerance?: number): AnyChain | undefined {\r\n const collector = new MultiChainCollector(gapTolerance, planeTolerance);\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n return collector.grabResult(true);\r\n }\r\n /**\r\n * Restructure curve fragments, to be stroked and passed into the callback.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained and stroked\r\n * @param announceChain callback to process each stroked Path and Loop\r\n * @param strokeOptions options for stroking the chains\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when assembling fragments head-to-tail. Also used for removing duplicate points in the stroked chains.\r\n * @param _planeTolerance unused, pass undefined\r\n */\r\n public static collectChainsAsLineString3d(fragments: AnyCurve[], announceChain: (chainPoints: LineString3d) => void, strokeOptions?: StrokeOptions, gapTolerance: number = Geometry.smallMetricDistance, _planeTolerance?: number) {\r\n const collector = new MultiChainCollector(gapTolerance); // no planarity tolerance needed\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n collector.announceChainsAsLineString3d(announceChain, strokeOptions);\r\n }\r\n /**\r\n * Compute the range of the curves in the local coordinates of a constructed localToWorld frame.\r\n * @param curves input geometry: curves or points.\r\n * @param localRange pre-allocated object to populate with the computed local range.\r\n * @param localToWorld optional pre-allocated object to populate with the computed frame.\r\n * @returns whether the frame was successfully computed.\r\n */\r\n public static computeLocalRange(curves: AnyCurve | MultiLineStringDataVariant, localRange: Range3d, localToWorld?: Transform): boolean {\r\n const builderData: any[] = [curves];\r\n if (localToWorld)\r\n builderData.push(localToWorld);\r\n localToWorld = FrameBuilder.createRightHandedFrame(Vector3d.unitZ(), ...builderData);\r\n if (!localToWorld)\r\n return false;\r\n const worldToLocal = localToWorld.inverse();\r\n localRange.setNull();\r\n if (Array.isArray(curves) || !(curves instanceof GeometryQuery))\r\n Range3d.createFromVariantData(curves, worldToLocal, localRange);\r\n else\r\n this.extendRange(localRange, curves, worldToLocal);\r\n return true;\r\n }\r\n /**\r\n * Check whether or not the curves are planar, and if so, return a localToWorld frame.\r\n * @param curves input geometry: curves or points.\r\n * @param tolerance optional maximum allowable planar deviation, default [[Geometry.smallMetricDistance]].\r\n * @param result optional pre-allocated object to populate and return.\r\n * @returns localToWorld frame `T` for coplanar curves, or undefined if they are not coplanar.\r\n * `T` satisfies:\r\n * * `T.origin` is in the plane.\r\n * * `T.matrix.columnZ()` is the plane unit normal (or its negative).\r\n * * `T.matrix.isRigid()` returns true.\r\n * * `T.inverse()` is worldToLocal; apply to input geometry to rotate it into the xy-plane.\r\n */\r\n public static isPlanar(curves: AnyCurve | MultiLineStringDataVariant, options?: PlanarColinearOptions): Transform | undefined {\r\n const localRange = Range3d.create();\r\n const localToWorld = options?.localToWorld ?? Transform.createIdentity();\r\n if (!this.computeLocalRange(curves, localRange, localToWorld))\r\n return undefined;\r\n const maxAltitude = options?.maxDeviation ?? Geometry.smallMetricDistance;\r\n return (localRange.zLength() <= Math.abs(maxAltitude)) ? localToWorld : undefined;\r\n }\r\n /**\r\n * Check whether or not the curves lie in a straight line, and if so, return a colinear ray.\r\n * * This test does not take curve traversal or point order into account.\r\n * @param curves input geometry: curves or points.\r\n * @param xyOnly whether to ignore z-coordinates of input geometry.\r\n * @param tolerance optional maximum allowable linear deviation, default [[Geometry.smallMetricDistance]].\r\n * @param result optional pre-allocated object to populate and return.\r\n * @returns ray colinear with input, or undefined if input is not colinear.\r\n */\r\n public static isColinear(curves: AnyCurve | MultiLineStringDataVariant, options?: PlanarColinearOptions): Ray3d | undefined {\r\n const localRange = Range3d.create();\r\n const localToWorld = options?.localToWorld ?? Transform.createIdentity();\r\n if (!this.computeLocalRange(curves, localRange, localToWorld))\r\n return undefined;\r\n const maxAltitude = Math.abs(options?.maxDeviation ?? Geometry.smallMetricDistance);\r\n if (localRange.zLength() > maxAltitude)\r\n return undefined; // non-planar\r\n\r\n const ray = options?.colinearRay ?? Ray3d.createZero();\r\n ray.origin.setFrom(localToWorld.origin);\r\n\r\n const xLength = localRange.xLength();\r\n const yLength = localRange.yLength();\r\n if (xLength <= maxAltitude && yLength <= maxAltitude) {\r\n ray.direction.setZero();\r\n return ray; // the input is essentially a point\r\n }\r\n if (yLength <= maxAltitude) {\r\n localToWorld.matrix.columnX(ray.direction);\r\n return ray; // the input lies along local x-axis\r\n }\r\n if (xLength <= maxAltitude) {\r\n localToWorld.matrix.columnY(ray.direction);\r\n return ray; // the input lies along local y-axis\r\n }\r\n if (!options?.xyColinear)\r\n return undefined; // non-colinear\r\n\r\n const angleTolerance = Math.abs(options?.radianTolerance ?? Geometry.smallAngleRadians);\r\n const verticalPlaneDeviation = Math.abs(localToWorld.matrix.columnDotXYZ(AxisIndex.Z, 0, 0, 1));\r\n if (verticalPlaneDeviation > angleTolerance) // cos(t + pi/2) = -sin(t) ~ -t for small t\r\n return undefined; // non-xy-colinear\r\n\r\n if (xLength > yLength)\r\n localToWorld.matrix.columnX(ray.direction);\r\n else\r\n localToWorld.matrix.columnY(ray.direction);\r\n ray.direction.z = 0.0;\r\n return ray; // xy-colinear (plane is vertical)\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"CurveOps.js","sourceRoot":"","sources":["../../../src/curve/CurveOps.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 Curve\r\n */\r\n\r\nimport { AxisIndex, Geometry } from \"../Geometry\";\r\nimport { FrameBuilder } from \"../geometry3d/FrameBuilder\";\r\nimport { MultiLineStringDataVariant } from \"../geometry3d/IndexedXYZCollection\";\r\nimport { Vector3d } from \"../geometry3d/Point3dVector3d\";\r\nimport { Range3d } from \"../geometry3d/Range\";\r\nimport { Ray3d } from \"../geometry3d/Ray3d\";\r\nimport { Transform } from \"../geometry3d/Transform\";\r\nimport { BagOfCurves, CurveCollection } from \"./CurveCollection\";\r\nimport { CurvePrimitive } from \"./CurvePrimitive\";\r\nimport { AnyChain, AnyCurve } from \"./CurveTypes\";\r\nimport { GeometryQuery } from \"./GeometryQuery\";\r\nimport { MultiChainCollector } from \"./internalContexts/MultiChainCollector\";\r\nimport { CurveChainWireOffsetContext } from \"./internalContexts/PolygonOffsetContext\";\r\nimport { LineString3d } from \"./LineString3d\";\r\nimport { Loop } from \"./Loop\";\r\nimport { OffsetOptions } from \"./OffsetOptions\";\r\nimport { Path } from \"./Path\";\r\nimport { StrokeOptions } from \"./StrokeOptions\";\r\n\r\n /**\r\n * Options bundle for use in [[CurveOps.isPlanar]] and [[CurveOps.isColinear]].\r\n * @public\r\n */\r\n export interface PlanarColinearOptions {\r\n /** Maximum allowable distance that geometry can deviate from planarity/colinearity. Default is [[Geometry.smallMetricDistance]]. */\r\n maxDeviation?: number;\r\n /** Whether colinearity test ignores z-coordinates. Default is `false`. */\r\n xyColinear?: boolean;\r\n /** Radian tolerance for xy-colinearity, measuring maximum angular deviation from a vertical plane. Default is [[Geometry.smallAngleRadians]]. */\r\n radianTolerance?: number;\r\n /** Pre-allocated object to populate with the computed plane-to-world transformation and return when planarity test succeeds. */\r\n localToWorld?: Transform;\r\n /** Pre-allocated object to populate with the computed line and return when colinear test succeeds. */\r\n colinearRay?: Ray3d;\r\n }\r\n\r\n/**\r\n * Static methods for miscellaneous curve operations.\r\n * @public\r\n */\r\nexport class CurveOps {\r\n /** Recursively sum curve lengths, allowing CurvePrimitive, CurveCollection, or array of such at any level. */\r\n public static sumLengths(curves: AnyCurve | AnyCurve[]): number {\r\n let mySum = 0;\r\n if (curves instanceof CurvePrimitive) {\r\n mySum += curves.curveLength();\r\n } else if (curves instanceof CurveCollection) {\r\n mySum += curves.sumLengths();\r\n } else if (Array.isArray(curves)) {\r\n for (const data1 of curves)\r\n mySum += this.sumLengths(data1);\r\n }\r\n return mySum;\r\n }\r\n /** Recursively extend the range by each curve's range, allowing CurvePrimitive, CurveCollection, or array of such at any level. */\r\n public static extendRange(range: Range3d, curves: AnyCurve | AnyCurve[], transform?: Transform): Range3d {\r\n if (Array.isArray(curves)) {\r\n for (const data1 of curves)\r\n this.extendRange(range, data1, transform);\r\n } else {\r\n curves.extendRange(range, transform);\r\n }\r\n return range;\r\n }\r\n /**\r\n * Construct a separate xy-offset for each input curve.\r\n * * For best offset results, the inputs should be parallel to the xy-plane.\r\n * @param curves input curve(s), z-coordinates ignored. Only curves of type [[AnyChain]] are handled.\r\n * @param offset offset distance (positive to left of curve, negative to right)\r\n * @param result array to collect offset curves\r\n * @returns summed length of offset curves\r\n */\r\n public static appendXYOffsets(curves: AnyCurve | AnyCurve[] | undefined, offset: number, result: AnyCurve[]): number {\r\n let summedLengths = 0;\r\n if (curves instanceof CurvePrimitive) {\r\n const resultA = CurveChainWireOffsetContext.constructCurveXYOffset(Path.create(curves), offset);\r\n if (resultA) {\r\n summedLengths += this.sumLengths(resultA);\r\n result.push(resultA);\r\n }\r\n } else if (curves instanceof Loop || curves instanceof Path) {\r\n const resultA = CurveChainWireOffsetContext.constructCurveXYOffset(curves, offset);\r\n if (resultA) {\r\n summedLengths += this.sumLengths(resultA);\r\n result.push(resultA);\r\n }\r\n } else if (curves instanceof BagOfCurves) {\r\n for (const q of curves.children)\r\n summedLengths += this.appendXYOffsets(q, offset, result);\r\n } else if (Array.isArray(curves)) {\r\n for (const q of curves)\r\n summedLengths += this.appendXYOffsets(q, offset, result);\r\n }\r\n return summedLengths;\r\n }\r\n /**\r\n * Restructure curve fragments as Paths and Loops, and construct xy-offsets of the chains.\r\n * * If the inputs do not form Loop(s), the classification of offsets is suspect.\r\n * * For best offset results, the inputs should be parallel to the xy-plane.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained and offset\r\n * @param offsetDistance offset distance, applied to both sides of each fragment to produce inside and outside xy-offset curves.\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when joining head-to-tail\r\n * @returns object with named chains, insideOffsets, outsideOffsets\r\n */\r\n public static collectInsideAndOutsideXYOffsets(fragments: AnyCurve[], offsetDistance: number, gapTolerance: number): { insideOffsets: AnyCurve[], outsideOffsets: AnyCurve[], chains?: AnyChain } {\r\n const collector = new MultiChainCollector(gapTolerance, gapTolerance);\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n const chains = collector.grabResult(true);\r\n const myOffsetA: CurveCollection[] = [];\r\n const myOffsetB: CurveCollection[] = [];\r\n const offsetLengthA = CurveOps.appendXYOffsets(chains, offsetDistance, myOffsetA);\r\n const offsetLengthB = CurveOps.appendXYOffsets(chains, -offsetDistance, myOffsetB);\r\n if (offsetLengthA > offsetLengthB) {\r\n return { outsideOffsets: myOffsetA, insideOffsets: myOffsetB, chains };\r\n } else {\r\n return { insideOffsets: myOffsetA, outsideOffsets: myOffsetB, chains };\r\n }\r\n }\r\n /**\r\n * Construct curves that are offset from a Path or Loop as viewed in xy-plane (ignoring z).\r\n * * The construction will remove \"some\" local effects of features smaller than the offset distance, but will not detect self intersection among widely separated edges.\r\n * @param curves base curves.\r\n * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object.\r\n */\r\n public static constructCurveXYOffset(curves: Path | Loop, offsetDistanceOrOptions: number | OffsetOptions): CurveCollection | undefined {\r\n return CurveChainWireOffsetContext.constructCurveXYOffset(curves, offsetDistanceOrOptions);\r\n }\r\n /**\r\n * Create the offset of a single curve primitive as viewed in the xy-plane (ignoring z).\r\n * @param curve primitive to offset\r\n * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object\r\n */\r\n public static createSingleOffsetPrimitiveXY(curve: CurvePrimitive, offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined {\r\n return CurveChainWireOffsetContext.createSingleOffsetPrimitiveXY(curve, offsetDistanceOrOptions);\r\n }\r\n /**\r\n * Restructure curve fragments as Paths and Loops.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when assembling fragments head-to-tail\r\n * @param planeTolerance tolerance for considering a closed chain to be planar. If undefined, only create Path. If defined, create Loops for closed chains within tolerance of a plane.\r\n * @returns chains, possibly wrapped in a [[BagOfCurves]].\r\n */\r\n public static collectChains(fragments: AnyCurve[], gapTolerance: number = Geometry.smallMetricDistance, planeTolerance?: number): AnyChain | undefined {\r\n const collector = new MultiChainCollector(gapTolerance, planeTolerance);\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n return collector.grabResult(true);\r\n }\r\n /**\r\n * Restructure curve fragments, to be stroked and passed into the callback.\r\n * * Chain formation is dependent upon input fragment order, as a greedy algorithm is employed.\r\n * @param fragments fragments to be chained and stroked\r\n * @param announceChain callback to process each stroked Path and Loop\r\n * @param strokeOptions options for stroking the chains\r\n * @param gapTolerance distance to be treated as \"effectively zero\" when assembling fragments head-to-tail. Also used for removing duplicate points in the stroked chains.\r\n * @param _planeTolerance unused, pass undefined\r\n */\r\n public static collectChainsAsLineString3d(fragments: AnyCurve[], announceChain: (chainPoints: LineString3d) => void, strokeOptions?: StrokeOptions, gapTolerance: number = Geometry.smallMetricDistance, _planeTolerance?: number) {\r\n const collector = new MultiChainCollector(gapTolerance); // no planarity tolerance needed\r\n for (const s of fragments) {\r\n collector.captureCurve(s);\r\n }\r\n collector.announceChainsAsLineString3d(announceChain, strokeOptions);\r\n }\r\n /**\r\n * Compute the range of the curves in the local coordinates of a constructed localToWorld frame.\r\n * @param curves input geometry: curves or points.\r\n * @param localRange pre-allocated object to populate with the computed local range.\r\n * @param localToWorld optional pre-allocated object to populate with the computed frame.\r\n * @returns whether the frame was successfully computed.\r\n */\r\n public static computeLocalRange(curves: AnyCurve | MultiLineStringDataVariant, localRange: Range3d, localToWorld?: Transform): boolean {\r\n const builderData: any[] = [curves];\r\n if (localToWorld)\r\n builderData.push(localToWorld);\r\n localToWorld = FrameBuilder.createRightHandedFrame(Vector3d.unitZ(), ...builderData);\r\n if (!localToWorld)\r\n return false;\r\n const worldToLocal = localToWorld.inverse();\r\n localRange.setNull();\r\n if (Array.isArray(curves) || !(curves instanceof GeometryQuery))\r\n Range3d.createFromVariantData(curves, worldToLocal, localRange);\r\n else\r\n this.extendRange(localRange, curves, worldToLocal);\r\n return true;\r\n }\r\n /**\r\n * Check whether or not the curves are planar, and if so, return a localToWorld frame.\r\n * @param curves input geometry: curves or points.\r\n * @param options bundle of options.\r\n * @returns localToWorld frame `T` for coplanar curves, or undefined if they are not coplanar.\r\n * `T` satisfies:\r\n * * `T.origin` is in the plane.\r\n * * `T.matrix.columnZ()` is the plane unit normal (or its negative).\r\n * * `T.matrix.isRigid()` returns true.\r\n * * `T.inverse()` is worldToLocal; apply to input geometry to rotate it into the xy-plane.\r\n */\r\n public static isPlanar(curves: AnyCurve | MultiLineStringDataVariant, options?: PlanarColinearOptions): Transform | undefined {\r\n const localRange = Range3d.create();\r\n const localToWorld = options?.localToWorld ?? Transform.createIdentity();\r\n if (!this.computeLocalRange(curves, localRange, localToWorld))\r\n return undefined;\r\n const maxAltitude = options?.maxDeviation ?? Geometry.smallMetricDistance;\r\n return (localRange.zLength() <= Math.abs(maxAltitude)) ? localToWorld : undefined;\r\n }\r\n /**\r\n * Check whether or not the curves lie in a straight line, and if so, return a colinear ray.\r\n * * This test does not take curve traversal or point order into account.\r\n * @param curves input geometry: curves or points.\r\n * @param options bundle of options.\r\n * @returns ray colinear with input, or undefined if input is not colinear.\r\n */\r\n public static isColinear(curves: AnyCurve | MultiLineStringDataVariant, options?: PlanarColinearOptions): Ray3d | undefined {\r\n const localRange = Range3d.create();\r\n const localToWorld = options?.localToWorld ?? Transform.createIdentity();\r\n if (!this.computeLocalRange(curves, localRange, localToWorld))\r\n return undefined;\r\n const maxAltitude = Math.abs(options?.maxDeviation ?? Geometry.smallMetricDistance);\r\n if (localRange.zLength() > maxAltitude)\r\n return undefined; // non-planar\r\n\r\n const ray = options?.colinearRay ?? Ray3d.createZero();\r\n ray.origin.setFrom(localToWorld.origin);\r\n\r\n const xLength = localRange.xLength();\r\n const yLength = localRange.yLength();\r\n if (xLength <= maxAltitude && yLength <= maxAltitude) {\r\n ray.direction.setZero();\r\n return ray; // the input is essentially a point\r\n }\r\n if (yLength <= maxAltitude) {\r\n localToWorld.matrix.columnX(ray.direction);\r\n return ray; // the input lies along local x-axis\r\n }\r\n if (xLength <= maxAltitude) {\r\n localToWorld.matrix.columnY(ray.direction);\r\n return ray; // the input lies along local y-axis\r\n }\r\n if (!options?.xyColinear)\r\n return undefined; // non-colinear\r\n\r\n const angleTolerance = Math.abs(options?.radianTolerance ?? Geometry.smallAngleRadians);\r\n const verticalPlaneDeviation = Math.abs(localToWorld.matrix.columnDotXYZ(AxisIndex.Z, 0, 0, 1));\r\n if (verticalPlaneDeviation > angleTolerance) // cos(t + pi/2) = -sin(t) ~ -t for small t\r\n return undefined; // non-xy-colinear\r\n\r\n if (xLength > yLength)\r\n localToWorld.matrix.columnX(ray.direction);\r\n else\r\n localToWorld.matrix.columnY(ray.direction);\r\n ray.direction.z = 0.0;\r\n return ray; // xy-colinear (plane is vertical)\r\n }\r\n}\r\n"]}
@@ -8,20 +8,28 @@ import { ParityRegion } from "../ParityRegion";
8
8
  */
9
9
  export declare class PlanarSubdivision {
10
10
  /**
11
- * Create a graph from an array of curves, and an array of the curves' precomputed intersections.
12
- * Z-coordinates are ignored.
11
+ * Create a graph from curves and precomputed intersections.
12
+ * * Z-coordinates are ignored.
13
+ * @param primitives input curves
14
+ * @param allPairs array of curve-curve xy-intersections
15
+ * @param mergeTolerance optional distance tolerance for clustering vertices. Default value is [[Geometry.smallMetricDistance]].
13
16
  */
14
17
  static assembleHalfEdgeGraph(primitives: CurvePrimitive[], allPairs: CurveLocationDetailPair[], mergeTolerance?: number): HalfEdgeGraph;
15
18
  /**
16
- * Create a pair of mated half edges referencing an interval of a primitive.
17
- * * no action if start and end points are identical.
19
+ * Filter for trivial curve fragment: fast computation if line segment; otherwise clip, flatten, and measure.
20
+ * * Different metrics are employed for expedience.
21
+ */
22
+ private static isCurveTrivialXY;
23
+ /**
24
+ * Create a pair of mated half edges referencing a non-trivial interval of a primitive.
18
25
  * @param graph containing graph
19
26
  * @param p the curve
20
27
  * @param point0 start point
21
28
  * @param fraction0 starting fraction
22
29
  * @param point1 end point
23
30
  * @param fraction1 end fraction
24
- * @returns end point and fraction, or start point and fraction if no action
31
+ * @param mergeTolerance optional maximum xy-length of a trivial edge
32
+ * @returns end point and fraction
25
33
  */
26
34
  private static addHalfEdge;
27
35
  /**
@@ -39,27 +47,54 @@ export declare class PlanarSubdivision {
39
47
  /**
40
48
  * Create a [[Loop]] for the given face or super face.
41
49
  * @param face a node in the face loop, or an array of HalfEdges that comprise a loop (e.g., a super face).
42
- * @param announce optional callback invoked on each edge/curve of the face/Loop.
43
- * @param compress whether to consolidate adjacent curves in the output Loop (default `false`).
44
- * If `announce` is provided, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
45
- * @param closureTol absolute xy-distance for confirming the returned Loop is closed (default [[Geometry.smallMetricDistance]]).
50
+ * @param options bundle of options.
46
51
  * @returns the Loop, or `undefined` if it is not closed within xy-tolerance.
47
52
  */
48
- static createLoopInFace(face: HalfEdge | HalfEdge[], announce?: (he: HalfEdge, curve: CurvePrimitive, loop: Loop) => void, compress?: boolean, closureTol?: number): Loop | undefined;
53
+ static createLoopInFace(face: HalfEdge | HalfEdge[], options?: PlanarSubdivision.CreateRegionInFaceOptions): Loop | undefined;
49
54
  /**
50
55
  * Create a [[Loop]] or [[ParityRegion]] for the given face.
51
56
  * * A ParityRegion is created for a split-washer type face by removing bridge edges.
52
57
  * @param face a node in the face loop.
53
- * @param bridgeMask mask preset on bridge edges (default is `HalfEdgeMask.BRIDGE_EDGE`).
54
- * @param visitMask mask to use for visiting edges in the face loop (default is `HalfEdgeMask.VISITED`).
55
- * @param closureTol absolute xy-distance for confirming the returned Loop is closed (default [[Geometry.smallMetricDistance]]).
56
- * @returns the Loop or ParityRegion, or `undefined` if one could not be computed
58
+ * @param options bundle of options.
59
+ * @returns the Loop or ParityRegion, or `undefined` if one could not be computed.
57
60
  */
58
- static createLoopOrParityRegionInFace(face: HalfEdge, bridgeMask?: HalfEdgeMask, visitMask?: HalfEdgeMask, closureTol?: number): Loop | ParityRegion | undefined;
61
+ static createLoopOrParityRegionInFace(face: HalfEdge, options?: PlanarSubdivision.CreateRegionInFaceOptions): Loop | ParityRegion | undefined;
59
62
  /** Return true if there are only two edges in the face loop, and their start curvatures are the same. */
60
63
  private static isNullFace;
61
64
  /** Look across edge mates (possibly several) for a non-null mate face. */
62
65
  private static getNonNullEdgeMate;
63
66
  static collectSignedLoopSetsInHalfEdgeGraph(graph: HalfEdgeGraph, zeroAreaTolerance?: number): SignedLoops[];
64
67
  }
68
+ /**
69
+ * @internal
70
+ */
71
+ export declare namespace PlanarSubdivision {
72
+ /** Options bundle for [[PlanarSubdivision.createLoopInFace]] and [[PlanarSubdivision.createLoopOrParityRegionInFace]]. */
73
+ interface CreateRegionInFaceOptions {
74
+ /**
75
+ * Optional callback invoked on each `edge` before its `curve` is added to `loop`.
76
+ * * Note that if a [[ParityRegion]] is being constructed, `curve` and `loop` may subsequently be reversed.
77
+ */
78
+ announceEdge?: (edge: HalfEdge, curve: CurvePrimitive, loop: Loop) => void;
79
+ /**
80
+ * Whether to consolidate adjacent curves in an output [[Loop]]. Default value is `false`.
81
+ * * If `announce` is defined, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
82
+ */
83
+ compress?: boolean;
84
+ /** Absolute xy-distance for confirming a returned Loop is closed. Default value is [[Geometry.smallMetricDistance]]. */
85
+ closureTol?: number;
86
+ /**
87
+ * Mask preset on bridge edges. Default value is `HalfEdgeMask.BRIDGE_EDGE`.
88
+ * * This mask is used to distinguish a split-washer type face, which can result in a [[ParityRegion]].
89
+ */
90
+ bridgeMask?: HalfEdgeMask;
91
+ /** Mask to use for visiting edges when creating a [[ParityRegion]] from a split-washer type face. Default value is `HalfEdgeMask.VISITED`. */
92
+ visitMask?: HalfEdgeMask;
93
+ /**
94
+ * Optional z-coordinate for the result region.
95
+ * * If undefined, graph z-coordinates are used, but this may result in a non-planar region if the graph is not planar!
96
+ */
97
+ z?: number;
98
+ }
99
+ }
65
100
  //# sourceMappingURL=PlanarSubdivision.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlanarSubdivision.d.ts","sourceRoot":"","sources":["../../../../src/curve/Query/PlanarSubdivision.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAI7E,OAAO,EAAuB,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD,OAAO,EAAE,IAAI,EAAsB,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAyE/C;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;;OAGG;WACW,qBAAqB,CACjC,UAAU,EAAE,cAAc,EAAE,EAC5B,QAAQ,EAAE,uBAAuB,EAAE,EACnC,cAAc,GAAE,MAAqC,GACpD,aAAa;IA2ChB;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAwB1B;;;;;;OAMG;WACW,iBAAiB,CAC7B,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,GAAE,MAAgB,EAAE,YAAY,CAAC,EAAE,OAAO,GAC7F,MAAM;IAeT,sDAAsD;IACtD,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAUtC,kDAAkD;IAClD,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAShC;;;;;;;;OAQG;WACW,gBAAgB,CAC5B,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,EAC3B,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,EACpE,QAAQ,GAAE,OAAe,EACzB,UAAU,GAAE,MAAqC,GAChD,IAAI,GAAG,SAAS;IAyBnB;;;;;;;;OAQG;WACW,8BAA8B,CAC1C,IAAI,EAAE,QAAQ,EACd,UAAU,GAAE,YAAuC,EACnD,SAAS,GAAE,YAAmC,EAC9C,UAAU,GAAE,MAAqC,GAChD,IAAI,GAAG,YAAY,GAAG,SAAS;IAiClC,yGAAyG;IACzG,OAAO,CAAC,MAAM,CAAC,UAAU;IAWzB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAC,kBAAkB;WAWnB,oCAAoC,CAAC,KAAK,EAAE,aAAa,EAAE,iBAAiB,GAAE,MAAgB,GAAG,WAAW,EAAE;CAmC7H"}
1
+ {"version":3,"file":"PlanarSubdivision.d.ts","sourceRoot":"","sources":["../../../../src/curve/Query/PlanarSubdivision.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAI7E,OAAO,EAAuB,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAInD,OAAO,EAAE,IAAI,EAAsB,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AA6F/C;;GAEG;AACH,qBAAa,iBAAiB;IAC5B;;;;;;OAMG;WACW,qBAAqB,CACjC,UAAU,EAAE,cAAc,EAAE,EAC5B,QAAQ,EAAE,uBAAuB,EAAE,EACnC,cAAc,GAAE,MAAqC,GACpD,aAAa;IA4ChB;;;MAGE;IACF,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAW/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAwB1B;;;;;;OAMG;WACW,iBAAiB,CAC7B,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,GAAE,MAAgB,EAAE,YAAY,CAAC,EAAE,OAAO,GAC7F,MAAM;IAeT,sDAAsD;IACtD,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAUtC,kDAAkD;IAClD,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAYhC;;;;;OAKG;WACW,gBAAgB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,EAAE,EAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC,yBAAyB,GAAG,IAAI,GAAG,SAAS;IAwBpI;;;;;;OAMG;WACW,8BAA8B,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,iBAAiB,CAAC,yBAAyB,GAAG,IAAI,GAAG,YAAY,GAAG,SAAS;IAqCpJ,yGAAyG;IACzG,OAAO,CAAC,MAAM,CAAC,UAAU;IAWzB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAC,kBAAkB;WAWnB,oCAAoC,CAAC,KAAK,EAAE,aAAa,EAAE,iBAAiB,GAAE,MAAgB,GAAG,WAAW,EAAE;CAkC7H;AAED;;EAEE;AACF,yBAAiB,iBAAiB,CAAC;IACjC,0HAA0H;IAC1H,UAAiB,yBAAyB;QACxC;;;WAGG;QACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;QAC3E;;;WAGG;QACH,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,wHAAwH;QACxH,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB;;;WAGG;QACH,UAAU,CAAC,EAAE,YAAY,CAAC;QAC1B,8IAA8I;QAC9I,SAAS,CAAC,EAAE,YAAY,CAAC;QACzB;;;WAGG;QACH,CAAC,CAAC,EAAE,MAAM,CAAC;KACZ;CACF"}
@@ -4,6 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { assert } from "@itwin/core-bentley";
6
6
  import { Geometry } from "../../Geometry";
7
+ import { Transform } from "../../geometry3d/Transform";
7
8
  import { HalfEdgeGraph, HalfEdgeMask } from "../../topology/Graph";
8
9
  import { HalfEdgeGraphSearch } from "../../topology/HalfEdgeGraphSearch";
9
10
  import { HalfEdgeGraphMerge } from "../../topology/Merging";
@@ -18,6 +19,25 @@ import { RegionGroupMember, RegionGroupOpType } from "../RegionOpsClassification
18
19
  /** @packageDocumentation
19
20
  * @module Curve
20
21
  */
22
+ function computeSortAngle(curve, fraction, reverse) {
23
+ const ray = curve.fractionToPointAndDerivative(fraction);
24
+ const s = reverse ? -1.0 : 1.0;
25
+ return Math.atan2(s * ray.direction.y, s * ray.direction.x);
26
+ }
27
+ function getFractionOnCurve(pair, curve) {
28
+ if (pair.detailA.curve === curve)
29
+ return pair.detailA.fraction;
30
+ if (pair.detailB.curve === curve)
31
+ return pair.detailB.fraction;
32
+ return undefined;
33
+ }
34
+ function getDetailOnCurve(pair, curve) {
35
+ if (pair.detailA.curve === curve)
36
+ return pair.detailA;
37
+ if (pair.detailB.curve === curve)
38
+ return pair.detailB;
39
+ return undefined;
40
+ }
21
41
  class MapCurvePrimitiveToCurveLocationDetailPairArray {
22
42
  primitiveToPair = new Map();
23
43
  // index assigned to this primitive (for debugging)
@@ -80,8 +100,11 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray {
80
100
  */
81
101
  export class PlanarSubdivision {
82
102
  /**
83
- * Create a graph from an array of curves, and an array of the curves' precomputed intersections.
84
- * Z-coordinates are ignored.
103
+ * Create a graph from curves and precomputed intersections.
104
+ * * Z-coordinates are ignored.
105
+ * @param primitives input curves
106
+ * @param allPairs array of curve-curve xy-intersections
107
+ * @param mergeTolerance optional distance tolerance for clustering vertices. Default value is [[Geometry.smallMetricDistance]].
85
108
  */
86
109
  static assembleHalfEdgeGraph(primitives, allPairs, mergeTolerance = Geometry.smallMetricDistance) {
87
110
  // map from key CurvePrimitive to CurveLocationDetailPair
@@ -127,31 +150,45 @@ export class PlanarSubdivision {
127
150
  return graph;
128
151
  }
129
152
  /**
130
- * Create a pair of mated half edges referencing an interval of a primitive.
131
- * * no action if start and end points are identical.
153
+ * Filter for trivial curve fragment: fast computation if line segment; otherwise clip, flatten, and measure.
154
+ * * Different metrics are employed for expedience.
155
+ */
156
+ static isCurveTrivialXY(p, point0, fraction0, point1, fraction1, mergeTolerance) {
157
+ if (Geometry.isSmallRelative(fraction0 - fraction1))
158
+ return true;
159
+ if (!(p instanceof LineSegment3d)) {
160
+ const p0 = p.clonePartialCurve(fraction0, fraction1);
161
+ if (p0?.tryTransformInPlace(Transform.createRowValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0))) // flatten
162
+ return p0.curveLength() <= mergeTolerance; // Euclidean
163
+ }
164
+ return point0.isAlmostEqualXY(point1, mergeTolerance); // Manhattan
165
+ }
166
+ /**
167
+ * Create a pair of mated half edges referencing a non-trivial interval of a primitive.
132
168
  * @param graph containing graph
133
169
  * @param p the curve
134
170
  * @param point0 start point
135
171
  * @param fraction0 starting fraction
136
172
  * @param point1 end point
137
173
  * @param fraction1 end fraction
138
- * @returns end point and fraction, or start point and fraction if no action
174
+ * @param mergeTolerance optional maximum xy-length of a trivial edge
175
+ * @returns end point and fraction
139
176
  */
140
177
  static addHalfEdge(graph, p, point0, fraction0, point1, fraction1, mergeTolerance = Geometry.smallMetricDistance) {
141
- if (point0.isAlmostEqualXY(point1, mergeTolerance))
142
- return { point: point0, fraction: fraction0 };
143
- const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0);
144
- if (p.parent && p.parent instanceof RegionGroupMember && p.parent.parentGroup.groupOpType === RegionGroupOpType.NonBounding)
145
- halfEdge.setMaskAroundEdge(HalfEdgeMask.BRIDGE_EDGE);
146
- const detail01 = CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
147
- const mate = halfEdge.edgeMate;
148
- halfEdge.edgeTag = detail01;
149
- halfEdge.sortData = 1.0;
150
- mate.edgeTag = detail01;
151
- mate.sortData = -1.0;
152
- halfEdge.sortAngle = sortAngle(p, fraction0, false);
153
- mate.sortAngle = sortAngle(p, fraction1, true);
154
- return { point: point1, fraction: fraction1 };
178
+ if (!this.isCurveTrivialXY(p, point0, fraction0, point1, fraction1, mergeTolerance)) {
179
+ const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0);
180
+ if (p.parent && p.parent instanceof RegionGroupMember && p.parent.parentGroup.groupOpType === RegionGroupOpType.NonBounding)
181
+ halfEdge.setMaskAroundEdge(HalfEdgeMask.BRIDGE_EDGE);
182
+ const detail01 = CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1);
183
+ const mate = halfEdge.edgeMate;
184
+ halfEdge.edgeTag = detail01;
185
+ halfEdge.sortData = 1.0;
186
+ mate.edgeTag = detail01;
187
+ mate.sortData = -1.0;
188
+ halfEdge.sortAngle = computeSortAngle(p, fraction0, false);
189
+ mate.sortAngle = computeSortAngle(p, fraction1, true);
190
+ }
191
+ return { point: point1, fraction: fraction1 }; // where the next curve fragment starts
155
192
  }
156
193
  /**
157
194
  * Based on computed (and toleranced) area, push the loop (pointer) onto the appropriate array of positive, negative,
@@ -187,32 +224,31 @@ export class PlanarSubdivision {
187
224
  return undefined;
188
225
  }
189
226
  /** Create the geometry for a topological edge. */
190
- static createCurveInEdge(edge) {
227
+ static createCurveInEdge(edge, z) {
228
+ let result;
191
229
  const info = this.extractGeometryFromEdge(edge);
192
- if (info) {
193
- if (info.reversed)
194
- return info.detail.curve.clonePartialCurve(info.detail.fraction1, info.detail.fraction);
195
- return info.detail.curve.clonePartialCurve(info.detail.fraction, info.detail.fraction1);
230
+ if (info && info.detail.curve && info.detail.fraction1) {
231
+ const f0 = info.reversed ? info.detail.fraction1 : info.detail.fraction;
232
+ const f1 = info.reversed ? info.detail.fraction : info.detail.fraction1;
233
+ result = info.detail.curve.clonePartialCurve(f0, f1);
234
+ if (result && z !== undefined)
235
+ result.tryTransformInPlace(Transform.createRowValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, z));
196
236
  }
197
- return undefined;
237
+ return result;
198
238
  }
199
239
  /**
200
240
  * Create a [[Loop]] for the given face or super face.
201
241
  * @param face a node in the face loop, or an array of HalfEdges that comprise a loop (e.g., a super face).
202
- * @param announce optional callback invoked on each edge/curve of the face/Loop.
203
- * @param compress whether to consolidate adjacent curves in the output Loop (default `false`).
204
- * If `announce` is provided, no compression is performed, as edges and curves would no longer be in 1-1 correspondence.
205
- * @param closureTol absolute xy-distance for confirming the returned Loop is closed (default [[Geometry.smallMetricDistance]]).
242
+ * @param options bundle of options.
206
243
  * @returns the Loop, or `undefined` if it is not closed within xy-tolerance.
207
244
  */
208
- static createLoopInFace(face, announce, compress = false, closureTol = Geometry.smallMetricDistance) {
209
- if (announce)
210
- compress = false;
245
+ static createLoopInFace(face, options) {
246
+ const consolidate = options?.announceEdge ? false : options?.compress ?? false; // can't compress if announcing
211
247
  const loop = Loop.create();
212
- const addEdgeCurve = (he) => {
213
- const curve = this.createCurveInEdge(he);
248
+ const addEdgeCurve = (edge) => {
249
+ const curve = this.createCurveInEdge(edge, options?.z);
214
250
  if (curve) {
215
- announce?.(he, curve, loop);
251
+ options?.announceEdge?.(edge, curve, loop);
216
252
  loop.tryAddChild(curve);
217
253
  }
218
254
  };
@@ -220,12 +256,12 @@ export class PlanarSubdivision {
220
256
  face.forEach(addEdgeCurve);
221
257
  else
222
258
  face.announceEdgesInFace(addEdgeCurve);
223
- if (compress) {
224
- const options = new ConsolidateAdjacentCurvePrimitivesOptions();
225
- options.consolidateLoopSeam = true;
226
- RegionOps.consolidateAdjacentPrimitives(loop, options);
259
+ if (consolidate) {
260
+ const consolidateOptions = new ConsolidateAdjacentCurvePrimitivesOptions();
261
+ consolidateOptions.consolidateLoopSeam = true;
262
+ RegionOps.consolidateAdjacentPrimitives(loop, consolidateOptions);
227
263
  }
228
- if (loop.isPhysicallyClosedCurve(closureTol, true))
264
+ if (loop.isPhysicallyClosedCurve(options?.closureTol, true))
229
265
  return loop;
230
266
  assert(() => false, "face is not physically closed");
231
267
  return undefined;
@@ -234,17 +270,19 @@ export class PlanarSubdivision {
234
270
  * Create a [[Loop]] or [[ParityRegion]] for the given face.
235
271
  * * A ParityRegion is created for a split-washer type face by removing bridge edges.
236
272
  * @param face a node in the face loop.
237
- * @param bridgeMask mask preset on bridge edges (default is `HalfEdgeMask.BRIDGE_EDGE`).
238
- * @param visitMask mask to use for visiting edges in the face loop (default is `HalfEdgeMask.VISITED`).
239
- * @param closureTol absolute xy-distance for confirming the returned Loop is closed (default [[Geometry.smallMetricDistance]]).
240
- * @returns the Loop or ParityRegion, or `undefined` if one could not be computed
273
+ * @param options bundle of options.
274
+ * @returns the Loop or ParityRegion, or `undefined` if one could not be computed.
241
275
  */
242
- static createLoopOrParityRegionInFace(face, bridgeMask = HalfEdgeMask.BRIDGE_EDGE, visitMask = HalfEdgeMask.VISITED, closureTol = Geometry.smallMetricDistance) {
276
+ static createLoopOrParityRegionInFace(face, options) {
243
277
  let region;
244
- if (face.isSplitWasherFace(bridgeMask)) {
278
+ const visitMask = options?.visitMask ?? HalfEdgeMask.VISITED;
279
+ const bridgeMask = options?.bridgeMask ?? HalfEdgeMask.BRIDGE_EDGE;
280
+ let startBridgeEdge;
281
+ // is it a split-washer face?
282
+ if (face.isSplitWasherFace(bridgeMask) && (startBridgeEdge = face.findMaskAroundFace(bridgeMask, true))) {
245
283
  const loops = [];
246
284
  const loopEdges = [];
247
- const bridgeStack = [face.findMaskAroundFace(bridgeMask, true)];
285
+ const bridgeStack = [startBridgeEdge];
248
286
  const announceEdge = (he) => { he.setMask(visitMask); loopEdges.push(he); };
249
287
  const announceBridge = (he) => { if (!he.isMaskSet(visitMask))
250
288
  bridgeStack.push(he); };
@@ -258,7 +296,7 @@ export class PlanarSubdivision {
258
296
  continue;
259
297
  loopEdges.length = 0;
260
298
  if (loopSeed.announceEdgesInSuperFace(bridgeMask, announceEdge, announceBridge)) {
261
- const loop = this.createLoopInFace(loopEdges, undefined, true, closureTol);
299
+ const loop = this.createLoopInFace(loopEdges, options);
262
300
  if (loop) {
263
301
  loops.push(loop);
264
302
  continue;
@@ -270,7 +308,7 @@ export class PlanarSubdivision {
270
308
  region = RegionOps.simplifyRegion(region);
271
309
  }
272
310
  else {
273
- region = this.createLoopInFace(face, undefined, true, closureTol);
311
+ region = this.createLoopInFace(face, options);
274
312
  }
275
313
  return (region && (region instanceof Loop || region instanceof ParityRegion)) ? region : undefined;
276
314
  }
@@ -307,24 +345,23 @@ export class PlanarSubdivision {
307
345
  const edges = [];
308
346
  for (const faceSeed of faceSeeds) {
309
347
  const isNullFace = this.isNullFace(faceSeed);
310
- const loop = this.createLoopInFace(faceSeed, (he, curveC, loopC) => {
311
- if (!isNullFace) {
312
- const mate = this.getNonNullEdgeMate(graph, he);
313
- if (mate !== undefined) {
314
- const e = edgeMap.get(mate);
315
- if (e === undefined) {
316
- // Record this as loopA,edgeA of a shared edge to be completed later from the other side of the edge
317
- const e1 = new LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
318
- edgeMap.set(he, e1);
319
- }
320
- else if (e instanceof LoopCurveLoopCurve) {
321
- e.setB(loopC, curveC);
322
- edges.push(e);
323
- edgeMap.delete(mate);
324
- }
348
+ const announceEdge = isNullFace ? undefined : (he, curveC, loopC) => {
349
+ const mate = this.getNonNullEdgeMate(graph, he);
350
+ if (mate !== undefined) {
351
+ const e = edgeMap.get(mate);
352
+ if (e === undefined) {
353
+ // Record this as loopA,edgeA of a shared edge to be completed later from the other side of the edge
354
+ const e1 = new LoopCurveLoopCurve(loopC, curveC, undefined, undefined);
355
+ edgeMap.set(he, e1);
356
+ }
357
+ else if (e instanceof LoopCurveLoopCurve) {
358
+ e.setB(loopC, curveC);
359
+ edges.push(e);
360
+ edgeMap.delete(mate);
325
361
  }
326
362
  }
327
- });
363
+ };
364
+ const loop = this.createLoopInFace(faceSeed, { announceEdge });
328
365
  if (loop)
329
366
  this.collectSignedLoop(loop, componentAreas, zeroAreaTolerance, isNullFace);
330
367
  }
@@ -335,23 +372,4 @@ export class PlanarSubdivision {
335
372
  return result;
336
373
  }
337
374
  }
338
- function sortAngle(curve, fraction, reverse) {
339
- const ray = curve.fractionToPointAndDerivative(fraction);
340
- const s = reverse ? -1.0 : 1.0;
341
- return Math.atan2(s * ray.direction.y, s * ray.direction.x);
342
- }
343
- function getFractionOnCurve(pair, curve) {
344
- if (pair.detailA.curve === curve)
345
- return pair.detailA.fraction;
346
- if (pair.detailB.curve === curve)
347
- return pair.detailB.fraction;
348
- return undefined;
349
- }
350
- function getDetailOnCurve(pair, curve) {
351
- if (pair.detailA.curve === curve)
352
- return pair.detailA;
353
- if (pair.detailB.curve === curve)
354
- return pair.detailB;
355
- return undefined;
356
- }
357
375
  //# sourceMappingURL=PlanarSubdivision.js.map