@itwin/core-geometry 5.9.0-dev.1 → 5.9.0-dev.2
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.
- package/CHANGELOG.md +8 -1
- package/lib/cjs/Geometry.d.ts +2 -1
- package/lib/cjs/Geometry.d.ts.map +1 -1
- package/lib/cjs/Geometry.js.map +1 -1
- package/lib/cjs/curve/Arc3d.d.ts.map +1 -1
- package/lib/cjs/curve/Arc3d.js +7 -6
- package/lib/cjs/curve/Arc3d.js.map +1 -1
- package/lib/cjs/curve/CurveFactory.d.ts +73 -1
- package/lib/cjs/curve/CurveFactory.d.ts.map +1 -1
- package/lib/cjs/curve/CurveFactory.js +228 -1
- package/lib/cjs/curve/CurveFactory.js.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.js +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/cjs/numerics/Polynomials.d.ts +1 -1
- package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
- package/lib/cjs/numerics/Polynomials.js +21 -9
- package/lib/cjs/numerics/Polynomials.js.map +1 -1
- package/lib/esm/Geometry.d.ts +2 -1
- package/lib/esm/Geometry.d.ts.map +1 -1
- package/lib/esm/Geometry.js.map +1 -1
- package/lib/esm/curve/Arc3d.d.ts.map +1 -1
- package/lib/esm/curve/Arc3d.js +7 -6
- package/lib/esm/curve/Arc3d.js.map +1 -1
- package/lib/esm/curve/CurveFactory.d.ts +73 -1
- package/lib/esm/curve/CurveFactory.d.ts.map +1 -1
- package/lib/esm/curve/CurveFactory.js +228 -1
- package/lib/esm/curve/CurveFactory.js.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.js +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/esm/numerics/Polynomials.d.ts +1 -1
- package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
- package/lib/esm/numerics/Polynomials.js +21 -9
- package/lib/esm/numerics/Polynomials.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PlaneAltitudeEvaluator } from "../Geometry";
|
|
1
|
+
import { PerpParallelOptions, PlaneAltitudeEvaluator } from "../Geometry";
|
|
2
2
|
import { Angle } from "../geometry3d/Angle";
|
|
3
3
|
import { AngleSweep } from "../geometry3d/AngleSweep";
|
|
4
4
|
import { Ellipsoid, GeodesicPathPoint } from "../geometry3d/Ellipsoid";
|
|
@@ -88,6 +88,27 @@ export interface CreateFilletsInLineStringOptions {
|
|
|
88
88
|
*/
|
|
89
89
|
filletClosure?: boolean;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Options used for method [[CurveFactory.fromFilletedLineString]].
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
export interface FilletedLineStringOptions {
|
|
96
|
+
/**
|
|
97
|
+
* Options for {@link Vector3d.isParallelTo}.
|
|
98
|
+
* Default: See the documentation for {@link PerpParallelOptions}
|
|
99
|
+
*/
|
|
100
|
+
parallelOptions?: PerpParallelOptions;
|
|
101
|
+
/**
|
|
102
|
+
* Distance tolerance for detecting equal points.
|
|
103
|
+
* Default: {@link Geometry.smallMetricDistance}.
|
|
104
|
+
*/
|
|
105
|
+
distanceTol?: number;
|
|
106
|
+
/**
|
|
107
|
+
* Whether to allow relaxed validation of the filleted linestring, which allows more chains to serve as valid input.
|
|
108
|
+
* Default: false.
|
|
109
|
+
*/
|
|
110
|
+
relaxedValidation?: boolean;
|
|
111
|
+
}
|
|
91
112
|
/**
|
|
92
113
|
* The `CurveFactory` class contains methods for specialized curve constructions.
|
|
93
114
|
* @public
|
|
@@ -111,6 +132,57 @@ export declare class CurveFactory {
|
|
|
111
132
|
* @param allowCuspOrOptions flag to allow cusps in output (default `true`), or a list of extended options.
|
|
112
133
|
*/
|
|
113
134
|
static createFilletsInLineString(points: LineString3d | IndexedXYZCollection | Point3d[], radius: number | number[], allowCuspOrOptions?: boolean | CreateFilletsInLineStringOptions): Path | undefined;
|
|
135
|
+
/** If an open filletedLineString starts/ends with an arc, add a zero-length line segment to its start/end. */
|
|
136
|
+
private static validateOpenPathStartEnd;
|
|
137
|
+
/**
|
|
138
|
+
* Split `arc` according to the partition given by `fractions` and append the pieces to `output` with zero-length
|
|
139
|
+
* line segments in between.
|
|
140
|
+
* @param fractions a complete partition of the fractional parameter space, e.g., [0, 0.5, 1] splits the arc into
|
|
141
|
+
* two pieces.
|
|
142
|
+
*/
|
|
143
|
+
private static splitAndAppendArc;
|
|
144
|
+
/**
|
|
145
|
+
* Update the path for relaxed validation:
|
|
146
|
+
* * If there are 2 connected arcs, add a zero-length line segment between them.
|
|
147
|
+
* * If there is a pair of arc and line segment/string with non-parallel tangents, add a zero-length line segment
|
|
148
|
+
* between them.
|
|
149
|
+
* * If there is an arc with sweep degrees in [180, 360), break the arc into 2 pieces separated by a zero-length
|
|
150
|
+
* line segment. Similarly, break a 360-degree arc into 3 pieces separated by 2 zero-length line segments. Return
|
|
151
|
+
* `undefined` if there is an arc with sweep greater than 360 degrees.
|
|
152
|
+
*/
|
|
153
|
+
private static updatePathForRelaxedValidation;
|
|
154
|
+
/**
|
|
155
|
+
* Verify each neighboring curve to an arc is a line segment/string. Also verify arc tangents are parallel
|
|
156
|
+
* (but not anti-parallel) to neighboring line segment/string tangents.
|
|
157
|
+
*/
|
|
158
|
+
private static validateArcNeighbors;
|
|
159
|
+
/** Validate a filleted line string. */
|
|
160
|
+
private static validateFilletedLineString;
|
|
161
|
+
/** If we have 2 connected arcs (with a zero-length line segment in between), add the joint with zero radius. */
|
|
162
|
+
private static addJointBetweenConnectedArcs;
|
|
163
|
+
/**
|
|
164
|
+
* Extract points and radii from a valid filleted linestring.
|
|
165
|
+
* * A valid filleted linestring is a `CurveChain` that satisfies the following conditions:
|
|
166
|
+
* * Its children have type `Arc3d`, `LineSegment3d`, or `LineString3d`.
|
|
167
|
+
* * Each `Arc3d` is circular.
|
|
168
|
+
* * Each `Arc3d` sweep is less than 180 degrees.
|
|
169
|
+
* * Each `Arc3d` cannot be adjacent to another `Arc3d`.
|
|
170
|
+
* * Each `Arc3d` is G1 continuous with each of its neighbors, i.e., at their common point, the curves have the same
|
|
171
|
+
* tangent direction.
|
|
172
|
+
* * To treat more input chains as valid, pass `options.relaxedValidation = true`. Internally, this setting performs
|
|
173
|
+
* several transformations on the input to produce a valid filleted linestring:
|
|
174
|
+
* * Each `Arc3d` whose sweep is between 180 and 360 degrees is split into 2 arcs of equal sweep separated by a
|
|
175
|
+
* zero-length `LineSegment3d`. A 360-degree arc is split into 3 arcs of equal sweep separated by 2 zero-length
|
|
176
|
+
* `LineSegment3d`s. Arcs with sweep greater than 360 degrees are not allowed.
|
|
177
|
+
* * Adjacent `Arc3d`s are separated by a zero-length `LineSegment3d`.
|
|
178
|
+
* * An `Arc3d` that is not G1 continuous with its neighbor is separated from its neighbor by a zero-length
|
|
179
|
+
* `LineSegment3d`.
|
|
180
|
+
* @param filletedLineString A linestring with corner fillets, e.g., as created by {@link CurveFactory.createFilletsInLineString}.
|
|
181
|
+
* @param options optional validation settings.
|
|
182
|
+
* @returns Array of [point, radius] pairs extracted from input, or `undefined` if the input is not valid. A radius
|
|
183
|
+
* of zero means no fillet at the vertex.
|
|
184
|
+
*/
|
|
185
|
+
static fromFilletedLineString(filletedLineString: CurveChain, options?: FilletedLineStringOptions): Array<[Point3d, number]> | undefined;
|
|
114
186
|
/**
|
|
115
187
|
* Create a `Loop` with given xy corners and fixed z.
|
|
116
188
|
* * The corners always proceed counter clockwise from lower left.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CurveFactory.d.ts","sourceRoot":"","sources":["../../../src/curve/CurveFactory.ts"],"names":[],"mappings":"AAUA,OAAO,EAAkC,sBAAsB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"CurveFactory.d.ts","sourceRoot":"","sources":["../../../src/curve/CurveFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -129,7 +129,7 @@ class CurveFactory {
|
|
|
129
129
|
continue;
|
|
130
130
|
const bA = blendArray[Geometry_1.Geometry.modulo(i - 1, n)];
|
|
131
131
|
const bC = blendArray[Geometry_1.Geometry.modulo(i + 1, n)];
|
|
132
|
-
if (bB.fraction10 > 1 || bB.fraction12 > 1 ||
|
|
132
|
+
if (bB.fraction10 > 1 || bB.fraction12 > 1 || bB.fraction10 + bA.fraction12 > 1 || bB.fraction12 + bC.fraction10 > 1) {
|
|
133
133
|
bB.fraction10 = bB.fraction12 = 0;
|
|
134
134
|
bB.arc = undefined;
|
|
135
135
|
}
|
|
@@ -146,6 +146,233 @@ class CurveFactory {
|
|
|
146
146
|
}
|
|
147
147
|
return path;
|
|
148
148
|
}
|
|
149
|
+
/** If an open filletedLineString starts/ends with an arc, add a zero-length line segment to its start/end. */
|
|
150
|
+
static validateOpenPathStartEnd(filletedLineString) {
|
|
151
|
+
const numOfChildren = filletedLineString.children.length;
|
|
152
|
+
(0, core_bentley_1.assert)(numOfChildren > 0);
|
|
153
|
+
const firstChild = filletedLineString.children[0];
|
|
154
|
+
const lastChild = filletedLineString.children[numOfChildren - 1];
|
|
155
|
+
if (firstChild instanceof Arc3d_1.Arc3d) {
|
|
156
|
+
const startPoint = firstChild.startPoint();
|
|
157
|
+
filletedLineString = Path_1.Path.create(LineSegment3d_1.LineSegment3d.create(startPoint, startPoint), ...filletedLineString.children);
|
|
158
|
+
}
|
|
159
|
+
if (lastChild instanceof Arc3d_1.Arc3d) {
|
|
160
|
+
const endPoint = lastChild.endPoint();
|
|
161
|
+
filletedLineString = Path_1.Path.create(...filletedLineString.children, LineSegment3d_1.LineSegment3d.create(endPoint, endPoint));
|
|
162
|
+
}
|
|
163
|
+
return filletedLineString;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Split `arc` according to the partition given by `fractions` and append the pieces to `output` with zero-length
|
|
167
|
+
* line segments in between.
|
|
168
|
+
* @param fractions a complete partition of the fractional parameter space, e.g., [0, 0.5, 1] splits the arc into
|
|
169
|
+
* two pieces.
|
|
170
|
+
*/
|
|
171
|
+
static splitAndAppendArc(output, arc, fractions) {
|
|
172
|
+
const pt = Point3dVector3d_1.Point3d.createZero();
|
|
173
|
+
for (let k = 0; k < fractions.length - 1; k++) {
|
|
174
|
+
output.tryAddChild(arc.clonePartialCurve(fractions[k], fractions[k + 1]));
|
|
175
|
+
if (k + 1 < fractions.length - 1) {
|
|
176
|
+
arc.fractionToPoint(fractions[k + 1], pt);
|
|
177
|
+
output.tryAddChild(LineSegment3d_1.LineSegment3d.create(pt, pt));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Update the path for relaxed validation:
|
|
183
|
+
* * If there are 2 connected arcs, add a zero-length line segment between them.
|
|
184
|
+
* * If there is a pair of arc and line segment/string with non-parallel tangents, add a zero-length line segment
|
|
185
|
+
* between them.
|
|
186
|
+
* * If there is an arc with sweep degrees in [180, 360), break the arc into 2 pieces separated by a zero-length
|
|
187
|
+
* line segment. Similarly, break a 360-degree arc into 3 pieces separated by 2 zero-length line segments. Return
|
|
188
|
+
* `undefined` if there is an arc with sweep greater than 360 degrees.
|
|
189
|
+
*/
|
|
190
|
+
static updatePathForRelaxedValidation(filletedLineString, isClosed, parallelOptions) {
|
|
191
|
+
const newFilletedLineString = new Path_1.Path();
|
|
192
|
+
const numOfChildren = filletedLineString.children.length;
|
|
193
|
+
for (let i = 0; i < numOfChildren; i++) { // examine each child and its predecessor
|
|
194
|
+
const child = filletedLineString.children[i];
|
|
195
|
+
const arcSweep = child instanceof Arc3d_1.Arc3d ? Math.abs(child.sweep.sweepDegrees) : undefined;
|
|
196
|
+
const sweepTol = Geometry_1.Geometry.smallAngleDegrees;
|
|
197
|
+
if (arcSweep !== undefined && arcSweep > 360 + sweepTol)
|
|
198
|
+
return undefined;
|
|
199
|
+
if (!isClosed && i === 0) {
|
|
200
|
+
newFilletedLineString.tryAddChild(child);
|
|
201
|
+
continue; // skip first child for open path since it won't have a previous child
|
|
202
|
+
}
|
|
203
|
+
const prevChild = filletedLineString.cyclicCurvePrimitive(i - 1);
|
|
204
|
+
(0, core_bentley_1.assert)(prevChild !== undefined, "Cyclic neighbor is defined within loop extents");
|
|
205
|
+
const childStartTangent = child.fractionToPointAndDerivative(0).direction;
|
|
206
|
+
const prevChildEndTangent = prevChild.fractionToPointAndDerivative(1).direction;
|
|
207
|
+
const childrenAreParallel = childStartTangent.isParallelTo(prevChildEndTangent, false, true, parallelOptions);
|
|
208
|
+
const arcLineStringCorner = !childrenAreParallel &&
|
|
209
|
+
((child instanceof Arc3d_1.Arc3d && (prevChild instanceof LineSegment3d_1.LineSegment3d || prevChild instanceof LineString3d_1.LineString3d)) ||
|
|
210
|
+
((prevChild instanceof Arc3d_1.Arc3d && (child instanceof LineSegment3d_1.LineSegment3d || child instanceof LineString3d_1.LineString3d))));
|
|
211
|
+
const twoConnectedArcs = child instanceof Arc3d_1.Arc3d && prevChild instanceof Arc3d_1.Arc3d;
|
|
212
|
+
// apply relaxed validation rules
|
|
213
|
+
if (twoConnectedArcs || arcLineStringCorner) {
|
|
214
|
+
const linePoint = child.startPoint();
|
|
215
|
+
newFilletedLineString.tryAddChild(LineSegment3d_1.LineSegment3d.create(linePoint, linePoint));
|
|
216
|
+
}
|
|
217
|
+
if (arcSweep !== undefined && arcSweep > 180 - sweepTol && arcSweep <= 360 - sweepTol) {
|
|
218
|
+
CurveFactory.splitAndAppendArc(newFilletedLineString, child, [0, 0.5, 1]); // 2 pieces
|
|
219
|
+
}
|
|
220
|
+
else if (arcSweep !== undefined && arcSweep > 360 - sweepTol && arcSweep <= 360 + sweepTol) {
|
|
221
|
+
CurveFactory.splitAndAppendArc(newFilletedLineString, child, [0, 1 / 3, 2 / 3, 1]); // 3 pieces
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
newFilletedLineString.tryAddChild(child);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return newFilletedLineString;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Verify each neighboring curve to an arc is a line segment/string. Also verify arc tangents are parallel
|
|
231
|
+
* (but not anti-parallel) to neighboring line segment/string tangents.
|
|
232
|
+
*/
|
|
233
|
+
static validateArcNeighbors(validatedFilletedLineString, i, perpOptions) {
|
|
234
|
+
const child = validatedFilletedLineString.getChild(i);
|
|
235
|
+
if (!child || !(child instanceof Arc3d_1.Arc3d))
|
|
236
|
+
return false;
|
|
237
|
+
// previous child before arc must be line segment/string
|
|
238
|
+
const prevChild = validatedFilletedLineString.cyclicCurvePrimitive(i - 1); // ASSUME: i === 0 only if the path is closed
|
|
239
|
+
if (!prevChild || (!(prevChild instanceof LineSegment3d_1.LineSegment3d) && !(prevChild instanceof LineString3d_1.LineString3d)))
|
|
240
|
+
return false;
|
|
241
|
+
// arc start tangent must be parallel (but not anti-parallel) to previous line segment
|
|
242
|
+
const arcStartTangent = child.fractionToPointAndDerivative(0).direction;
|
|
243
|
+
const prevChildEndTangent = prevChild.fractionToPointAndDerivative(1).direction;
|
|
244
|
+
if (!arcStartTangent.isParallelTo(prevChildEndTangent, false, true, perpOptions))
|
|
245
|
+
return false;
|
|
246
|
+
// next child after arc must be line segment/string
|
|
247
|
+
const nextChild = validatedFilletedLineString.cyclicCurvePrimitive(i + 1); // ASSUME: i === numOfChildren-1 only if the path is closed
|
|
248
|
+
if (!nextChild || (!(nextChild instanceof LineSegment3d_1.LineSegment3d) && !(nextChild instanceof LineString3d_1.LineString3d)))
|
|
249
|
+
return false;
|
|
250
|
+
// arc end tangent must be parallel (and not anti-parallel) to next line segment
|
|
251
|
+
const arcEndTangent = child.fractionToPointAndDerivative(1).direction;
|
|
252
|
+
const nextChildStartTangent = nextChild.fractionToPointAndDerivative(0).direction;
|
|
253
|
+
if (!arcEndTangent.isParallelTo(nextChildStartTangent, false, true, perpOptions))
|
|
254
|
+
return false;
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
/** Validate a filleted line string. */
|
|
258
|
+
static validateFilletedLineString(filletedLineString, isClosed, options) {
|
|
259
|
+
if (filletedLineString.children.length === 0)
|
|
260
|
+
return undefined;
|
|
261
|
+
const relaxedValidation = options?.relaxedValidation ?? false;
|
|
262
|
+
let validatedFilletedLineString = filletedLineString;
|
|
263
|
+
if (!isClosed)
|
|
264
|
+
validatedFilletedLineString = this.validateOpenPathStartEnd(validatedFilletedLineString);
|
|
265
|
+
if (relaxedValidation)
|
|
266
|
+
validatedFilletedLineString = this.updatePathForRelaxedValidation(validatedFilletedLineString, isClosed, options?.parallelOptions);
|
|
267
|
+
if (validatedFilletedLineString === undefined)
|
|
268
|
+
return undefined;
|
|
269
|
+
const numOfChildren = validatedFilletedLineString.children.length;
|
|
270
|
+
// validate the children
|
|
271
|
+
for (let i = 0; i < numOfChildren; i++) {
|
|
272
|
+
const child = validatedFilletedLineString.children[i];
|
|
273
|
+
if (!(child instanceof Arc3d_1.Arc3d) && !(child instanceof LineSegment3d_1.LineSegment3d) && !(child instanceof LineString3d_1.LineString3d))
|
|
274
|
+
return undefined;
|
|
275
|
+
if (child instanceof Arc3d_1.Arc3d) {
|
|
276
|
+
if (child.circularRadius() === undefined || Math.abs(child.sweep.sweepDegrees) > 180 - Geometry_1.Geometry.smallAngleDegrees)
|
|
277
|
+
return undefined;
|
|
278
|
+
if (!this.validateArcNeighbors(validatedFilletedLineString, i, options?.parallelOptions))
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return validatedFilletedLineString;
|
|
283
|
+
}
|
|
284
|
+
/** If we have 2 connected arcs (with a zero-length line segment in between), add the joint with zero radius. */
|
|
285
|
+
static addJointBetweenConnectedArcs(validatedFilletedLineString, i, isClosed, result) {
|
|
286
|
+
if (!isClosed && i < 2) // for open path, skip the first 2 children
|
|
287
|
+
return;
|
|
288
|
+
const child = validatedFilletedLineString.getChild(i);
|
|
289
|
+
if (!child || !(child instanceof Arc3d_1.Arc3d))
|
|
290
|
+
return;
|
|
291
|
+
const prevChild = validatedFilletedLineString.cyclicCurvePrimitive(i - 1);
|
|
292
|
+
if (!prevChild || !(prevChild instanceof LineSegment3d_1.LineSegment3d) || prevChild.curveLength() > 0)
|
|
293
|
+
return;
|
|
294
|
+
const prevPrevChild = validatedFilletedLineString.cyclicCurvePrimitive(i - 2);
|
|
295
|
+
if (!prevPrevChild || !(prevPrevChild instanceof Arc3d_1.Arc3d))
|
|
296
|
+
return;
|
|
297
|
+
result.push([prevChild.startPoint(), 0]);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Extract points and radii from a valid filleted linestring.
|
|
301
|
+
* * A valid filleted linestring is a `CurveChain` that satisfies the following conditions:
|
|
302
|
+
* * Its children have type `Arc3d`, `LineSegment3d`, or `LineString3d`.
|
|
303
|
+
* * Each `Arc3d` is circular.
|
|
304
|
+
* * Each `Arc3d` sweep is less than 180 degrees.
|
|
305
|
+
* * Each `Arc3d` cannot be adjacent to another `Arc3d`.
|
|
306
|
+
* * Each `Arc3d` is G1 continuous with each of its neighbors, i.e., at their common point, the curves have the same
|
|
307
|
+
* tangent direction.
|
|
308
|
+
* * To treat more input chains as valid, pass `options.relaxedValidation = true`. Internally, this setting performs
|
|
309
|
+
* several transformations on the input to produce a valid filleted linestring:
|
|
310
|
+
* * Each `Arc3d` whose sweep is between 180 and 360 degrees is split into 2 arcs of equal sweep separated by a
|
|
311
|
+
* zero-length `LineSegment3d`. A 360-degree arc is split into 3 arcs of equal sweep separated by 2 zero-length
|
|
312
|
+
* `LineSegment3d`s. Arcs with sweep greater than 360 degrees are not allowed.
|
|
313
|
+
* * Adjacent `Arc3d`s are separated by a zero-length `LineSegment3d`.
|
|
314
|
+
* * An `Arc3d` that is not G1 continuous with its neighbor is separated from its neighbor by a zero-length
|
|
315
|
+
* `LineSegment3d`.
|
|
316
|
+
* @param filletedLineString A linestring with corner fillets, e.g., as created by {@link CurveFactory.createFilletsInLineString}.
|
|
317
|
+
* @param options optional validation settings.
|
|
318
|
+
* @returns Array of [point, radius] pairs extracted from input, or `undefined` if the input is not valid. A radius
|
|
319
|
+
* of zero means no fillet at the vertex.
|
|
320
|
+
*/
|
|
321
|
+
static fromFilletedLineString(filletedLineString, options) {
|
|
322
|
+
const path = filletedLineString instanceof Loop_1.Loop
|
|
323
|
+
? Path_1.Path.create(...filletedLineString.children)
|
|
324
|
+
: filletedLineString;
|
|
325
|
+
const isClosed = path.isPhysicallyClosedCurve(options?.distanceTol);
|
|
326
|
+
const validatedFilletedLineString = this.validateFilletedLineString(path, isClosed, options);
|
|
327
|
+
if (!validatedFilletedLineString)
|
|
328
|
+
return undefined;
|
|
329
|
+
// Algorithm:
|
|
330
|
+
// Each arc contributes a point with the arc's radius. If arc consumed the entire edge (2 points), we make sure to
|
|
331
|
+
// add both points (one with the arc's radius and one with zero radius).
|
|
332
|
+
// Each line segment contributes its start point with zero radius, except when it follows an arc, in which case
|
|
333
|
+
// it is ignored since the arc already contributes that point with the correct radius.
|
|
334
|
+
// For open validatedFilletedLineString (which is guaranteed to start and end with a line segment) we also add
|
|
335
|
+
// start and end points with zero radius.
|
|
336
|
+
const result = [];
|
|
337
|
+
const numOfChildren = validatedFilletedLineString.children.length;
|
|
338
|
+
const lastChild = validatedFilletedLineString.cyclicCurvePrimitive(-1);
|
|
339
|
+
let ignoreLineSegment = isClosed && lastChild && lastChild instanceof Arc3d_1.Arc3d;
|
|
340
|
+
for (let i = 0; i < numOfChildren; i++) {
|
|
341
|
+
const child = validatedFilletedLineString.children[i];
|
|
342
|
+
if (child instanceof Arc3d_1.Arc3d) {
|
|
343
|
+
this.addJointBetweenConnectedArcs(validatedFilletedLineString, i, isClosed, result);
|
|
344
|
+
ignoreLineSegment = true; // ignore next line segment that follows this arc
|
|
345
|
+
const tangIntersection = child.computeTangentIntersection();
|
|
346
|
+
const radius = child.circularRadius();
|
|
347
|
+
if (radius !== undefined && tangIntersection !== undefined)
|
|
348
|
+
result.push([tangIntersection, radius]);
|
|
349
|
+
else
|
|
350
|
+
return undefined;
|
|
351
|
+
}
|
|
352
|
+
else if (child instanceof LineSegment3d_1.LineSegment3d) {
|
|
353
|
+
if (ignoreLineSegment)
|
|
354
|
+
ignoreLineSegment = false;
|
|
355
|
+
else
|
|
356
|
+
result.push([child.startPoint(), 0]);
|
|
357
|
+
}
|
|
358
|
+
else if (child instanceof LineString3d_1.LineString3d) {
|
|
359
|
+
const j0 = ignoreLineSegment ? 1 : 0;
|
|
360
|
+
ignoreLineSegment = false;
|
|
361
|
+
for (let j = j0; j < child.numPoints() - 1; j++)
|
|
362
|
+
result.push([child.pointAtUnchecked(j), 0]);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
if (isClosed) {
|
|
366
|
+
if (result.length > 0 && !result[0][0].isAlmostEqual(result[result.length - 1][0], options?.distanceTol))
|
|
367
|
+
result.push(result[0]);
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const endPoint = validatedFilletedLineString.endPoint();
|
|
371
|
+
if (endPoint)
|
|
372
|
+
result.push([endPoint, 0]);
|
|
373
|
+
}
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
149
376
|
/**
|
|
150
377
|
* Create a `Loop` with given xy corners and fixed z.
|
|
151
378
|
* * The corners always proceed counter clockwise from lower left.
|