Skip to content

Cubic

Overview

Cubic Bezier segment.

See http://www.cis.usouthal.edu/~hain/general/Publications/Bezier/BezierFlattening.pdf for info

Good reference: http://cagd.cs.byu.edu/~557/text/ch2.pdf

@author Jonathan Olson <jonathan.olson@colorado.edu>

Class Cubic

import { Cubic } from 'scenerystack/kite';

Constructor

new Cubic( start : Vector2, control1 : Vector2, control2 : Vector2, end : Vector2 )

Instance Methods

setStart( start : Vector2 ) : this

Sets the start point of the Cubic.

getStart() : Vector2

Returns the start of this Cubic.

setControl1( control1 : Vector2 ) : this

Sets the first control point of the Cubic.

getControl1() : Vector2

Returns the first control point of this Cubic.

setControl2( control2 : Vector2 ) : this

Sets the second control point of the Cubic.

getControl2() : Vector2

Returns the second control point of this Cubic.

setEnd( end : Vector2 ) : this

Sets the end point of the Cubic.

getEnd() : Vector2

Returns the end of this Cubic.

positionAt( t : number ) : Vector2

Returns the position parametrically, with 0 <= t <= 1.

NOTE: positionAt( 0 ) will return the start of the segment, and positionAt( 1 ) will return the end of the segment.

This method is part of the Segment API. See Segment.js's constructor for more API documentation.

tangentAt( t : number ) : Vector2

Returns the non-normalized tangent (dx/dt, dy/dt) of this segment at the parametric value of t, with 0 <= t <= 1.

NOTE: tangentAt( 0 ) will return the tangent at the start of the segment, and tangentAt( 1 ) will return the tangent at the end of the segment.

This method is part of the Segment API. See Segment.js's constructor for more API documentation.

curvatureAt( t : number ) : number

Returns the signed curvature of the segment at the parametric value t, where 0 <= t <= 1.

The curvature will be positive for visual clockwise / mathematical counterclockwise curves, negative for opposite curvature, and 0 for no curvature.

NOTE: curvatureAt( 0 ) will return the curvature at the start of the segment, and curvatureAt( 1 ) will return the curvature at the end of the segment.

This method is part of the Segment API. See Segment.js's constructor for more API documentation.

subdivided( t : number ) : Cubic[]

Returns an array with up to 2 sub-segments, split at the parametric t value. Together (in order) they should make up the same shape as the current segment.

This method is part of the Segment API. See Segment.js's constructor for more API documentation.

invalidate()

Clears cached information, should be called when any of the 'constructor arguments' are mutated.

getStartTangent() : Vector2

Gets the start position of this cubic polynomial.

getEndTangent() : Vector2

Gets the end position of this cubic polynomial.

getR() : Vector2

TODO: documentation https://github.com/phetsims/kite/issues/76

getS() : Vector2

TODO: documentation https://github.com/phetsims/kite/issues/76

getTCusp() : number

Returns the parametric t value for the possible cusp location. A cusp may or may not exist at that point.

getTDeterminant() : number

Returns the determinant value for the cusp, which indicates the presence (or lack of presence) of a cusp.

getTInflection1() : number

Returns the parametric t value for the potential location of the first possible inflection point.

getTInflection2() : number

Returns the parametric t value for the potential location of the second possible inflection point.

getQuadratics() : Quadratic[] | null

If there is a cusp, this cubic will consist of one or two quadratic segments, typically "start => cusp" and "cusp => end".

getXExtremaT() : number[]

Returns a list of parametric t values where x-extrema exist, i.e. where dx/dt==0. These are candidate locations on the cubic for "maximum X" and "minimum X", and are needed for bounds computations.

getYExtremaT() : number[]

Returns a list of parametric t values where y-extrema exist, i.e. where dy/dt==0. These are candidate locations on the cubic for "maximum Y" and "minimum Y", and are needed for bounds computations.

getBounds() : Bounds2

Returns the bounds of this segment.

getNondegenerateSegments() : Segment[]

Returns a list of non-degenerate segments that are equivalent to this segment. Generally gets rid (or simplifies) invalid or repeated segments.

hasCusp() : boolean

Returns whether this cubic has a cusp.

toRS( point : Vector2 ) : Vector2

offsetTo( r : number, reverse : boolean ) : Line[]

getSVGPathFragment() : string

Returns a string containing the SVG path. assumes that the start point is already provided, so anything that calls this needs to put the M calls first

strokeLeft( lineWidth : number ) : Line[]

Returns an array of lines that will draw an offset curve on the logical left side

strokeRight( lineWidth : number ) : Line[]

Returns an array of lines that will draw an offset curve on the logical right side

getInteriorExtremaTs() : number[]

Returns a list of t values where dx/dt or dy/dt is 0 where 0 < t < 1. subdividing on these will result in monotonic segments The list does not include t=0 and t=1

intersection( ray : Ray2 ) : RayIntersection[]

Hit-tests this segment with the ray. An array of all intersections of the ray with this segment will be returned. For details, see the documentation in Segment.js

windingIntersection( ray : Ray2 ) : number

Returns the winding number for intersection with a ray

writeToContext( context : CanvasRenderingContext2D )

Draws the segment to the 2D Canvas context, assuming the context's current location is already at the start point

transformed( matrix : Matrix3 ) : Cubic

Returns a new cubic that represents this cubic after transformation by the matrix

degreeReduced( epsilon : number ) : Quadratic | null

Returns a degree-reduced quadratic Bezier if possible, otherwise it returns null

getSignedAreaFragment() : number

Returns the contribution to the signed area computed using Green's Theorem, with P=-y/2 and Q=x/2.

NOTE: This is this segment's contribution to the line integral (-y/2 dx + x/2 dy).

reversed() : Cubic

Returns a reversed copy of this segment (mapping the parametrization from [0,1] => [1,0]).

getSelfIntersection() : SegmentIntersection | null

If it exists, returns the point where the cubic curve self-intersects.

@returns - Null if there is no intersection

serialize() : SerializedCubic

Returns an object form that can be turned back into a segment with the corresponding deserialize method.

getOverlaps( segment : Segment, epsilon ) : Overlap[] | null

Determine whether two lines overlap over a continuous section, and if so finds the a,b pair such that p( t ) === q( a * t + b ).

@param segment @param [epsilon] - Will return overlaps only if no two corresponding points differ by this amount or more in one component. @returns - The solution, if there is one (and only one)

Instance Properties

degree : number

Degree of this polynomial (cubic)

Static Methods

deserialize( obj : SerializedCubic ) : Cubic

Returns a Cubic from the serialized representation.

extremaT( v0 : number, v1 : number, v2 : number, v3 : number ) : number[]

Finds what t values the cubic extrema are at (if any). This is just the 1-dimensional case, used for multiple purposes

getOverlaps( cubic1 : Cubic, cubic2 : Cubic, epsilon ) : Overlap[]

Determine whether two Cubics overlap over a continuous section, and if so finds the a,b pair such that p( t ) === q( a * t + b ).

NOTE: for this particular function, we assume we're not degenerate. Things may work if we can be degree-reduced to a quadratic, but generally that shouldn't be done.

@param cubic1 @param cubic2 @param [epsilon] - Will return overlaps only if no two corresponding points differ by this amount or more in one component. @returns - The solution, if there is one (and only one)

Type SerializedCubic

import type { SerializedCubic } from 'scenerystack/kite';
  • type: "Cubic"
  • startX: number
  • startY: number
  • control1X: number
  • control1Y: number
  • control2X: number
  • control2Y: number
  • endX: number
  • endY: number

Source Code

See the source for Cubic.ts in the kite repository.