Segment¶
Overview¶
A segment represents a specific curve with a start and end.
Each segment is treated parametrically, where t=0 is the start of the segment, and t=1 is the end. Values of t between those represent points along the segment.
@author Jonathan Olson <jonathan.olson@colorado.edu> /* global paper */
Class Segment¶
Constructor¶
new Segment()¶
Instance Methods¶
positionAt( t : number ) : Vector2¶
Returns the position parametrically, with 0 <= t <= 1. NOTE that this function doesn't keep a constant magnitude tangent.
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.
curvatureAt( t : number ) : number¶
Returns the signed curvature (positive for visual clockwise - mathematical counterclockwise)
subdivided( t : number ) : Segment[]¶
Returns an array with up to 2 sub-segments, split at the parametric t value. The segments together should make the same shape as the original segment.
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 ) : Segment[]¶
Returns an array of segments that will draw an offset curve on the logical left side
strokeRight( lineWidth : number ) : Segment[]¶
Returns an array of segments that will draw an offset curve on the logical right side
windingIntersection( ray : Ray2 ) : number¶
Returns the winding number for intersection with a ray
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
intersection( ray : Ray2 ) : RayIntersection[]¶
Returns a list of intersections between the segment and the ray.
getBounds() : Bounds2¶
Returns a {Bounds2} representing the bounding box for the segment.
getSignedAreaFragment() : number¶
Returns signed area contribution for this segment using Green's Theorem
getNondegenerateSegments() : Segment[]¶
Returns a list of non-degenerate segments that are equivalent to this segment. Generally gets rid (or simplifies) invalid or repeated segments.
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 ) : Segment¶
Returns a new segment that represents this segment after transformation by the matrix
invalidate()¶
serialize() : SerializedSegment¶
areStrokedBoundsDilated() : boolean¶
Will return true if the start/end tangents are purely vertical or horizontal. If all of the segments of a shape have this property, then the only line joins will be a multiple of pi/2 (90 degrees), and so all of the types of line joins will have the same bounds. This means that the stroked bounds will just be a pure dilation of the regular bounds, by lineWidth / 2.
getBoundsWithTransform( matrix : Matrix3 ) : Bounds2¶
TODO: override everywhere so this isn't necessary (it's not particularly efficient!) https://github.com/phetsims/kite/issues/76
slice( t0 : number, t1 : number ) : Segment¶
Extracts a slice of a segment, based on the parametric value.
Given that this segment is represented by the interval [0,1]
subdivisions( tList : number[] ) : Segment[]¶
@param tList - list of sorted t values from 0 <= t <= 1
subdividedIntoMonotone() : Segment[]¶
Return an array of segments from breaking this segment into monotone pieces
isSufficientlyFlat( distanceEpsilon : number, curveEpsilon : number ) : boolean¶
Determines if the segment is sufficiently flat (given certain epsilon values)
@param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change between segments
getArcLength( distanceEpsilon? : number, curveEpsilon? : number, maxLevels? : number ) : number¶
Returns the (sometimes approximate) arc length of the segment.
getDashValues( lineDash : number[], lineDashOffset : number, distanceEpsilon : number, curveEpsilon : number ) : DashValues¶
Returns information about the line dash parametric offsets for a given segment.
As always, this is fairly approximate depending on the type of segment.
@param lineDash @param lineDashOffset @param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change between segments
toPiecewiseLinearSegments( options : PiecewiseLinearOptions, minLevels? : number, maxLevels? : number, segments? : Line[], start? : Vector2, end? : Vector2 ) : Line[]¶
@param [options] @param [minLevels] - how many levels to force subdivisions @param [maxLevels] - prevent subdivision past this level @param [segments] @param [start] @param [end]
toPiecewiseLinearOrArcSegments( providedOptions : PiecewiseLinearOrArcOptions ) : Segment[]¶
Returns a list of Line and/or Arc segments that approximates this segment.
toShape() : Shape¶
Returns a Shape containing just this one segment.
getClosestPoints( point : Vector2 ) : ClosestToPointResult[]¶
Instance Properties¶
invalidationEmitter : TEmitter¶
Static Methods¶
closestToPoint( segments : Segment[], point : Vector2, threshold : number ) : ClosestToPointResult[]¶
List of results (since there can be duplicates), threshold is used for subdivision, where it will exit if all of the segments are shorter than the threshold
TODO: solve segments to determine this analytically! https://github.com/phetsims/kite/issues/76
polynomialGetOverlapCubic( p0s : number, p1s : number, p2s : number, p3s : number, q0s : number, q1s : number, q2s : number, q3s : number ) : PossibleSimpleOverlap¶
Given the cubic-premultiplied values for two cubic bezier curves, determines (if available) a specified (a,b) pair such that p( t ) === q( a * t + b ).
Given a 1-dimensional cubic bezier determined by the control points p0, p1, p2 and p3, compute:
[ p0s ] [ 1 0 0 0 ] [ p0 ] [ p1s ] == [ -3 3 0 0 ] * [ p1 ] [ p2s ] == [ 3 -6 3 0 ] * [ p2 ] [ p3s ] [ -1 3 -3 1 ] [ p3 ]
see Cubic.getOverlaps for more information.
polynomialGetOverlapQuadratic( p0s : number, p1s : number, p2s : number, q0s : number, q1s : number, q2s : number ) : PossibleSimpleOverlap¶
Given the quadratic-premultiplied values for two quadratic bezier curves, determines (if available) a specified (a,b) pair such that p( t ) === q( a * t + b ).
Given a 1-dimensional quadratic bezier determined by the control points p0, p1, p2, compute:
[ p0s ] [ 1 0 0 ] [ p0 ] [ p1s ] == [ -2 2 0 ] * [ p1 ] [ p2s ] [ 2 -2 3 ] * [ p2 ]
see Quadratic.getOverlaps for more information.
polynomialGetOverlapLinear( p0s : number, p1s : number, q0s : number, q1s : number ) : PossibleSimpleOverlap¶
Given the linear-premultiplied values for two lines, determines (if available) a specified (a,b) pair such that p( t ) === q( a * t + b ).
Given a line determined by the control points p0, p1, compute:
[ p0s ] == [ 1 0 ] * [ p0 ] [ p1s ] == [ -1 1 ] * [ p1 ]
see Quadratic/Cubic.getOverlaps for more information.
intersect( a : Segment, b : Segment ) : SegmentIntersection[]¶
Returns all the distinct (non-endpoint, non-finite) intersections between the two segments.
deserialize( obj : SerializedSegment ) : Segment¶
Returns a Segment from the serialized representation.
isSufficientlyFlat( distanceEpsilon : number, curveEpsilon : number, start : Vector2, middle : Vector2, end : Vector2 ) : boolean¶
Determines if the start/middle/end points are representative of a sufficiently flat segment (given certain epsilon values)
@param start @param middle @param end @param distanceEpsilon - controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve @param curveEpsilon - controls level of subdivision by attempting to ensure a maximum curvature change between segments
filterClosestToPointResult( results : ClosestToPointResult[] ) : ClosestToPointResult[]¶
Type ClosestToPointResult¶
Type DashValues¶
- values: number[]
Parametric (t) values for where dash boundaries exist - arcLength: number
Total arc length for this segment - initiallyInside: boolean
Whether the start of the segment is inside a dash (instead of a gap)
Type PiecewiseLinearOptions¶
- minLevels?: number
how many levels to force subdivisions - maxLevels?: number
prevent subdivision past this level - distanceEpsilon?: number | null
controls level of subdivision by attempting to ensure a maximum (squared) deviation from the curve - curveEpsilon?: number | null
controls level of subdivision by attempting to ensure a maximum curvature change between segments - pointMap?: ( v: Vector2 ) => Vector2
represents a (usually non-linear) transformation applied - methodName?: KeysMatching<Segment, ( options: PiecewiseLinearOptions ) => Segment[]> | KeysMatching<Arc, ( options: PiecewiseLinearOptions ) => Segment[]> | KeysMatching<Cubic, ( options: PiecewiseLinearOptions ) => Segment[]> | KeysMatching<EllipticalArc, ( options: PiecewiseLinearOptions ) => Segment[]> | KeysMatching<Line, ( options: PiecewiseLinearOptions ) => Segment[]> | KeysMatching<Quadratic, ( options: PiecewiseLinearOptions ) => Segment[]>
if the method name is found on the segment, it is called with the expected signature function( options ) : Array[Segment] instead of using our brute-force logic
Type SerializedSegment¶
SerializedArc | SerializedCubic | SerializedEllipticalArc | SerializedLine | SerializedQuadratic
Source Code¶
See the source for Segment.ts in the kite repository.