Base class for BSplineCurve3d and BSplineCurve3dH.
- A bspline curve consists of a set of knots and a set of poles.
- The bspline curve is a function of the independent "knot axis" variable
- The curve "follows" the poles loosely.
- The is a set of polynomial spans.
- The polynomial spans all have same
- Within each span, the polynomial of that
degreeis controlled by
order = degree + 1contiguous points called poles.
- The is a strict relationship between knot and poles counts: `numPoles + order = numKnots + 2'
- The number of spans is
numSpan = numPoles - degree
- For a given
orderpoles begin at index
2*orderknots begin as span index
- The knot interval for this span is from
knot[degree+span-1] to knot[degree+span]
- The active part of the knot axis is
knot[degree-1] < knot < knot[degree-1 + numSpan]i.e. `knot[degree-1] < knot < knot[numPoles]
Nearly all bsplines are "clamped ".
- Clamping make the curve pass through its first and last poles, with tangents directed along the first and last edges of the control polygon.
- The knots for a clamped bspline have
degreecopies of the lowest knot value and
degreecopies of the highest knot value.
- For instance, the knot vector `[0,0,0,1,2,3,3,3]
- can be evaluated from
- has 3 spans: 0 to 1, 1 to 2, 2 to 3
- has 6 poles
- passes through its first and last poles.
- can be evaluated from
createmethods may allow classic convention that has an extra knot at the beginning and end of the knot vector.
- The extra knots (first and last) were never referenced by the bspline recurrence relations.
- When the
createmethods recognize the classic setup (
numPoles + order = numKnots), the extra knot is not saved with the BSplineCurve3dBase knots.
The weighted variant has the problem that CurvePrimitive 3d typing does not allow undefined result where Point4d has zero weight.
The convention for these is to return 000 in such places.
Note the class relationships:
- BSpline1dNd knows the bspline recurrence relations for control points (poles) with no physical meaning.
- BsplineCurve3dBase owns a protected BSpline1dNd
- BsplineCurve3dBase is derived from CurvePrimitive, which creates obligation to act as a 3D curve, such as
- evaluate fraction to point and derivatives wrt fraction
- compute intersection with plane
- BSplineCurve3d and BSplineCurve3dH have variant logic driven by whether or not there are "weights" on the poles.
BSplineCurve3d, the xyz value of pole calculations are "final" values for 3d evaluation
BSpline1dNdresults with xyzw have to be normalized back to xyz.
These classes do not support "periodic" variants.
- Periodic curves need to have certain leading knots and poles replicated at the end
|constructor(poleDimension: number, numPoles: number, order: number, knots: KnotVector): BSplineCurve3dBase Protected|
|appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail): number||Implement
|closestPoint(spacePoint: Point3d, _extend: boolean): CurveLocationDetail | undefined||Search for the curve point that is closest to the spacePoint.|
|collectBezierSpans(prefer3dH: boolean): BezierCurveBase||Return an array with this curve's bezier fragments.|
|copyKnots(includeExtraEndKnot: boolean): number||return a simple array form of the knots.|
|endPoint(): Point3d||Return the end point of the curve|
|evaluatePointAndDerivativeInSpan(spanIndex: number, spanFraction: number, result?: Ray3d): Ray3d Abstract||Evaluate at a position given by fractional position within a span.|
|evaluatePointInSpan(spanIndex: number, spanFraction: number, result?: Point3d): Point3d Abstract||Evaluate at a position given by fractional position within a span.|
|fractionToPoint(fraction: number, result?: Point3d): Point3d||Evaluate the curve point at
|fractionToPointAnd2Derivatives(fraction: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors||Construct a plane with
origin at the fractional position along the arc
x axis is the first derivative, i.e.
|fractionToPointAndDerivative(fraction: number, result?: Ray3d): Ray3d||Construct a ray with
origin at the fractional position along the arc
direction is the first derivative, i.e.
|getPolePoint3d(poleIndex: number, result?: Point3d): Point3d | undefined Abstract||Return a specified pole as a Point3d
BSplineCurve3d returns its simple xyz
BSplineCurve3dH attempts to normalize its (wx,wy,wz,w) back to (x,y,z), and returns undefined if weight is zero.
|getPolePoint4d(poleIndex: number, result?: Point4d): Point4d | undefined Abstract||Return a specified pole as a Point4d.|
|getSaturatedBezierSpan3dOr3dH(spanIndex: number, prefer3dH: boolean, result?: BezierCurveBase): BezierCurveBase | undefined Abstract||Return a BezierCurveBase for this curve.|
|knotToPoint(knot: number, result?: Point3d): Point3d Abstract||Evaluate xyz at a position given by knot.|
|knotToPointAnd2Derivatives(knot: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors Abstract||Evaluate xyz and 2 derivatives at position given by a knot value.|
|knotToPointAndDerivative(knot: number, result?: Ray3d): Ray3d Abstract||Evaluate xyz and derivative at position given by a knot value.|
|poleIndexToDataIndex(poleIndex: number): number | undefined||Given a pole index, return the starting index for the contiguous array.|
|reverseInPlace(): void||Reverse the curve in place.|
|setWrappable(value: BSplineWrapMode): void||Set the flag indicating the bspline might be suitable for having wrapped "closed" interpretation.|
|startPoint(): Point3d||Return the start point of the curve.|
|addMappedStrokesToLineString3D(map: StrokeCountMap, linestring: LineString3d): number||CurvePrimitive||* evaluate strokes at fractions indicated in a StrokeCountMap.|
|announceClipIntervals(_clipper: Clipper, _announce?: AnnounceNumberNumberCurvePrimitive): boolean||CurvePrimitive||Find intervals of this curvePrimitive that are interior to a clipper|
|clone(): GeometryQuery | undefined Abstract||GeometryQuery||return a clone|
|clonePartialCurve(_fractionA: number, _fractionB: number): CurvePrimitive | undefined||CurvePrimitive||Return (if possible) a curve primitive which is a portion of this curve.|
|cloneTransformed(transform: Transform): GeometryQuery | undefined Abstract||GeometryQuery||return a transformed clone.|
|computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentMap?: StrokeCountMap): void||CurvePrimitive||attach StrokeCountMap structure to this primitive (and recursively to any children)
* Base class implementation (here) gets the simple count from computeStrokeCountForOptions and attaches it.
|computeStrokeCountForOptions(options?: StrokeOptions): number Abstract||CurvePrimitive||return the stroke count required for given options.|
|curveLength(): number||CurvePrimitive||return the length of the curve.|
|curveLengthBetweenFractions(fraction0: number, fraction1: number): number||CurvePrimitive||Returns a (high accuracy) length of the curve between fractional positions
* Curve length is always positive.
|curveLengthWithFixedIntervalCountQuadrature(fraction0: number, fraction1: number, numInterval: number, numGauss: number = 5): number||CurvePrimitive|| Run an integration (with a default gaussian quadrature) with a fixed fractional step
This is typically called by specific curve type implementations of curveLengthBetweenFractions.
|dispatchToGeometryHandler(handler: GeometryHandler): any Abstract||GeometryQuery||* "double dispatch" call pattern.|
|emitStrokableParts(dest: IStrokeHandler, options?: StrokeOptions): void Abstract||CurvePrimitive||Ask the curve to announce points and simple subcurve fragments for stroking.|
|emitStrokes(dest: LineString3d, options?: StrokeOptions): void Abstract||CurvePrimitive||Add strokes to caller-supplied linestring|
|extendRange(rangeToExtend: Range3d, transform?: Transform): void Abstract||GeometryQuery||extend rangeToExtend by the range of this geometry multiplied by the transform|
|fractionAndDistanceToPointOnTangent(fraction: number, distance: number): Point3d||CurvePrimitive||Construct a point extrapolated along tangent at fraction.|
|fractionToFrenetFrame(fraction: number, result?: Transform): Transform | undefined||CurvePrimitive||Construct a frenet frame:
origin at the point on the curve
x axis is unit vector along the curve (tangent)
* y axis is perpendicular and in the plane of the osculating circle.
|fractionToPointAndUnitTangent(fraction: number, result?: Ray3d): Ray3d||CurvePrimitive||Returns a ray whose origin is the curve point and direction is the unit tangent.|
|getFractionToDistanceScale(): number | undefined||CurvePrimitive|| If the curve primitive has distance-along-curve strictly proportional to curve fraction, return true
If distance-along-the-curve is not proportional, return undefined.
|isAlmostEqual(other: GeometryQuery): boolean||GeometryQuery||test for exact structure and nearly identical geometry.|
|isInPlane(plane: Plane3dByOriginAndUnitNormal): boolean Abstract||CurvePrimitive||Ask if the curve is within tolerance of a plane.|
|isSameGeometryClass(other: GeometryQuery): boolean Abstract||GeometryQuery||test if (other instanceof this.Type).|
|moveSignedDistanceFromFraction(startFraction: number, signedDistance: number, allowExtension: boolean, result?: CurveLocationDetail): CurveLocationDetail||CurvePrimitive||* (Attempt to) find a position on the curve at a signed distance from start fraction.|
|moveSignedDistanceFromFractionGeneric(startFraction: number, signedDistance: number, allowExtension: boolean, result?: CurveLocationDetail): CurveLocationDetail Protected||CurvePrimitive||Generic algorithm to search for point at signed distance from a fractional startPoint.|
|quickLength(): number Abstract||CurvePrimitive||Compute a length which may be an fast approximation to the true length.|
|range(transform?: Transform, result?: Range3d): Range3d||GeometryQuery||return the range of the entire (tree) GeometryQuery|
|tryTransformInPlace(transform: Transform): boolean Abstract||GeometryQuery||Attempt to transform in place.|
|tryTranslateInPlace(dx: number, dy: number = 0, dz: number = 0): boolean||GeometryQuery||try to move the geometry by dx,dy,dz|
|installStrokeCountMap(curve: CurvePrimitive, curveMap: StrokeCountMap, parentMap?: StrokeCountMap): void Static||CurvePrimitive||final install step to save curveMap in curve.|
|_bcurve Protected||BSpline1dNd||The underlying blocked-pole spline, with simple x,y,z poles|
|curvePrimitiveType||"bsplineCurve" = "bsplineCurve"|
|degree Accessor ReadOnly||number||Return the degree (one less than the order) of the curve|
|numPoles Accessor ReadOnly||number||Return the number of poles|
|numSpan Accessor ReadOnly||number||Return the number of bezier spans in the curve.|
|order Accessor ReadOnly||number||Return the order (one more than degree) of the curve|
|children Accessor ReadOnly||GeometryQuery | undefined||GeometryQuery||return GeometryQuery children for recursive queries.
* leaf classes do not need to implement.
|geometryCategory||"curvePrimitive" = "curvePrimitive"||CurvePrimitive|
|isExtensibleFractionSpace Accessor ReadOnly||boolean||CurvePrimitive|| Returns true if the curve's fraction queries extend beyond 0..1.
Base class default implementation returns false.
These class (and perhaps others in the future) will return true:
|strokeData||undefined | StrokeCountMap||CurvePrimitive||data attached during stroking for facets.|
Last Updated: 10 September, 2019