## BSplineCurve3dBase Class

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 degree.
• Within each span, the polynomial of that degree is controlled by order = degree + 1 contiguous 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 spanIndex:
• The order poles begin at index spanIndex.
• The 2*order knots 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 degree copies of the lowest knot value and degree copies of the highest knot value.

• For instance, the knot vector [0,0,0,1,2,3,3,3]

• can be evaluated from 0<=knot<=3
• has 3 spans: 0 to 1, 1 to 2, 2 to 3
• has 6 poles
• passes through its first and last poles.
• create methods 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 create methods 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.
• For BSplineCurve3d, the xyz value of pole calculations are "final" values for 3d evaluation
• For BSplineCurve3dH, various BSpline1dNd results 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

### Methods

Name Description
constructor(poleDimension: number, numPoles: number, order: number, knots: KnotVector): Protected
appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail[]): number Implement CurvePrimitive.appendPlaneIntersections
clone(): Abstract Return a deep clone.
clonePartialCurve(fractionA: number, fractionB: number): Return a curve primitive which is a portion of this curve.
cloneTransformed(transform: Transform): Return a transformed deep clone.
closestPoint(spacePoint: Point3d, _extend: boolean): undefined | CurveLocationDetail Search for the curve point that is closest to the spacePoint.
collectBezierSpans(prefer3dH: boolean): Return an array with this curve's bezier fragments.
constructOffsetXY(offsetDistanceOrOptions: number | OffsetOptions): undefined | CurvePrimitive | CurvePrimitive[] Construct an offset of the instance curve as viewed in the xy-plane (ignoring z).
copyKnots(includeExtraEndKnot: boolean): number[] return a simple array form of the knots.
endPoint(): Return the end point of the curve
evaluatePointAndDerivativeInSpan(spanIndex: number, spanFraction: number, result?: Ray3d): Abstract Evaluate at a position given by fractional position within a span.
evaluatePointInSpan(spanIndex: number, spanFraction: number, result?: Point3d): Abstract Evaluate at a position given by fractional position within a span.
fractionToPoint(fraction: number, result?: Point3d): Evaluate the curve point at fraction
fractionToPointAnd2Derivatives(fraction: number, result?: Plane3dByOriginAndVectors): Construct a plane with
fractionToPointAndDerivative(fraction: number, result?: Ray3d): Construct a ray with
getPolePoint3d(poleIndex: number, result?: Point3d): undefined | Point3d Abstract Return a specified pole as a Point3d
getPolePoint4d(poleIndex: number, result?: Point4d): undefined | Point4d Abstract Return a specified pole as a Point4d.
getSaturatedBezierSpan3dOr3dH(spanIndex: number, prefer3dH: boolean, result?: BezierCurveBase): undefined | BezierCurveBase Abstract Return a BezierCurveBase for this curve.
knotToPoint(knot: number, result?: Point3d): Abstract Evaluate xyz at a position given by knot.
knotToPointAnd2Derivatives(knot: number, result?: Plane3dByOriginAndVectors): Abstract Evaluate xyz and 2 derivatives at position given by a knot value.
knotToPointAndDerivative(knot: number, result?: Ray3d): Abstract Evaluate xyz and derivative at position given by a knot value.
poleIndexToDataIndex(poleIndex: number): undefined | number Given a pole index, return the starting index for the contiguous array.
projectedParameterRange(ray: Vector3d | Ray3d, lowHigh?: Range1d): undefined | Range1d Project instance geometry (via dispatch) onto the given ray, and return the extreme fractional parameters of projection.
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(): Return the start point of the curve.

### Inherited methods

Name Inherited from Description
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
collectCurvePrimitives(collectorArray?: CurvePrimitive[], smallestPossiblePrimitives: boolean = false, explodeLinestrings: boolean = false): CurvePrimitive Return an array containing only the curve primitives.
collectCurvePrimitivesGo(collectorArray: CurvePrimitive[], _smallestPossiblePrimitives: boolean, _explodeLinestrings: boolean = false): void CurvePrimitive Return an array containing only the curve primitives.
computeAndAttachRecursiveStrokeCounts(options?: StrokeOptions, parentMap?: StrokeCountMap): void CurvePrimitive Attach StrokeCountMap structure to this primitive (and recursively to any children)
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.
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
dispatchToGeometryHandler(handler: GeometryHandler): any Abstract CurvePrimitive * "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 (function updates dest`)
extendRange(rangeToExtend: Range3d, transform?: Transform): void Abstract CurvePrimitive Extend rangeToExtend by the range of this geometry multiplied by the transform
fractionAndDistanceToPointOnTangent(fraction: number, distance: number): CurvePrimitive Construct a point extrapolated along tangent at fraction.
fractionToCurvature(fraction: number): undefined | number CurvePrimitive Returns the (absolute) curvature magnitude.
fractionToFrenetFrame(fraction: number, result?: Transform): undefined | Transform CurvePrimitive Construct a frenet frame:
fractionToPointAndUnitTangent(fraction: number, result?: Ray3d): CurvePrimitive Returns a ray whose origin is the curve point and direction is the unit tangent.
fractionToSignedXYRadiusOfCurvature(fraction: number): number CurvePrimitive Construct signed distance from a point on the planar curve to its center of curvature (in xy only).
getFractionToDistanceScale(): undefined | number CurvePrimitive If the curve primitive has distance-along-curve strictly proportional to curve fraction, return the scale factor.
isAlmostEqual(other: GeometryQuery): boolean CurvePrimitive Test for exact structure and nearly identical geometry.
isInPlane(): boolean Abstract CurvePrimitive Ask if the curve is within tolerance of a plane.
isSameGeometryClass(other: GeometryQuery): boolean Abstract CurvePrimitive Test if (other instanceof this.Type).
moveSignedDistanceFromFraction(startFraction: number, signedDistance: number, allowExtension: boolean, result?: 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): Protected CurvePrimitive Generic algorithm to search for point at signed distance from a fractional startPoint.
quickLength(): number Abstract CurvePrimitive Compute a length for curve which may be a fast approximation to the true length.
range(transform?: Transform, result?: Range3d): CurvePrimitive Return the range of the entire GeometryQuery tree
rangeBetweenFractions(fraction0: number, fraction1: number, transform?: Transform): CurvePrimitive Returns a (high accuracy) range of the curve between fractional positions
rangeBetweenFractionsByClone(fraction0: number, fraction1: number, transform?: Transform): CurvePrimitive Returns a (high accuracy) range of the curve between fractional positions
rangeBetweenFractionsByCount(fraction0: number, fraction1: number, count: number, transform?: Transform, extrapolationFactor: number = 0.0): CurvePrimitive Returns an approximate range based on a fixed number of evaluations
tryTransformInPlace(transform: Transform): boolean Abstract CurvePrimitive Attempt to transform in place.
tryTranslateInPlace(dx: number, dy: number = 0.0, dz: number = 0.0): boolean CurvePrimitive Try to move the geometry by dx,dy,dz
areAlmostEqual(a: undefined | GeometryQuery, b: undefined | GeometryQuery): boolean Static CurvePrimitive Apply instance method CurvePrimitive.isAlmostEqual if both are defined.
installStrokeCountMap(curve: CurvePrimitive, curveMap: StrokeCountMap, parentMap?: StrokeCountMap): void Static CurvePrimitive Final install step to save curveMap in curve.

### Properties

Name Type Description
_bcurve Protected BSpline1dNd The underlying blocked-pole spline, with simple x,y,z poles
curvePrimitiveType Readonly "bsplineCurve" String name for schema properties
definitionData Accessor any
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

### Inherited properties

Name Type Inherited from Description
children Accessor ReadOnly undefined | GeometryQuery[] CurvePrimitive Return GeometryQuery children for recursive queries.
* leaf classes do not need to implement.
geometryCategory Readonly "curvePrimitive" CurvePrimitive String name for schema properties
isExtensibleFractionSpace Accessor ReadOnly boolean CurvePrimitive * Returns true if the curve can be easily extended past its start/end point (i.e., beyond the usual
fraction space [0,1]). Otherwise, returns false.
* Base class default implementation returns false.
* These classes (and perhaps others in the future) will return true:
* LineSegment3d
* LineString3d
* Arc3d
parent undefined | any CurvePrimitive Data attached by various algorithms (e.g.
strokeData undefined | StrokeCountMap CurvePrimitive Data attached during stroking for facets.

### Defined in

Last Updated: 04 October, 2023