Skip to content

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

import { Segment } from 'scenerystack/kite';

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

import type { ClosestToPointResult } from 'scenerystack/kite';
  • segment: Segment
  • t: number
  • closestPoint: Vector2
  • distanceSquared: number

Type DashValues

import type { DashValues } from 'scenerystack/kite';
  • 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

import type { PiecewiseLinearOptions } from 'scenerystack/kite';

Type SerializedSegment

import type { SerializedSegment } from 'scenerystack/kite';

SerializedArc | SerializedCubic | SerializedEllipticalArc | SerializedLine | SerializedQuadratic

Source Code

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