import { Line2 } from "./Line2" ; import { ReadonlyVector2 , Vector2 } from "./Vector2" ; /**
 * A polygon with any number of vertices.
 */ export class Polygon2 { public readonly vertices : Vector2 [ ] ; public readonly edges : Line2 [ ] = [ ] ; private readonly normals : Vector2 [ ] = [ ] ; param vertices public constructor ( ... vertices ) { this . vertices = vertices ; for ( let i = 0 , max = vertices . length ; i < max ; ++ i ) { this . edges . push ( new Line2 ( vertices [ i ] , vertices [ i + 1 ] ?? vertices [ 0 ] ) ) ; } } return public hasVertices ( ) { return this . vertices . length > 0 ; } param vertex param index public addVertex ( vertex , index = this . vertices . length ) { const edge = new Line2 ( vertex , vertex ) ; this . vertices . splice ( index , 0 , vertex ) ; const previousEdge = this . edges [ index - 1 ] ; this . edges . splice ( index , 0 , edge ) ; if ( previousEdge != null ) { edge . end = previousEdge . end ; previousEdge . end = vertex ; } else { edge . end = this . vertices [ 0 ] ; } return this ; } param index public removeVertex ( index ) { const edges = this . edges ; const edge = edges [ index ] ; if ( edge != null ) { const previousEdge = edges [ index - 1 ] ?? edges [ edges . length - 1 ] ; const nextEdge = edges [ index + 1 ] ?? edges [ 0 ] ; if ( previousEdge !== edge && nextEdge !== edge ) { nextEdge . start = edge . end ; previousEdge . end = edge . end ; } this . vertices . splice ( index , 1 ) ; this . edges . splice ( index , 1 ) ; } return this ; } /**
     * Removes all vertices from the polygon.
     */ public clear ( ) { this . vertices . length = 0 ; this . edges . length = 0 ; this . normals . length = 0 ; return this ; } param index return public getVertexNormal ( index ) { const normal = this . normals [ index ] ?. reset ( ) ?? ( this . normals [ index ] = new Vector2 ( ) ) ; const edges = this . edges ; const edge = edges [ index ] ; if ( edge != null ) { normal . add ( edge . getNormal ( ) ) ; const previousEdge = edges [ index - 1 ] ?? edges [ edges . length - 1 ] ; if ( previousEdge != null ) { normal . add ( previousEdge . getNormal ( ) ) ; } } return normal . normalize ( ) ; } param ctx public draw ( ctx ) { const vertices = this . vertices ; if ( vertices . length > 0 ) { const first = vertices [ 0 ] ; ctx . moveTo ( first . x , first . y ) ; for ( let i = 1 , max = vertices . length ; i < max ; ++ i ) { const next = vertices [ i ] ; ctx . lineTo ( next . x , next . y ) ; } } ctx . closePath ( ) ; return this ; } param ctx param len public drawNormals ( ctx , len ? ) { for ( const edge of this . edges ) { edge . drawNormal ( ctx , len ) ; } return this ; } param ctx param len public drawVertexNormals ( ctx , len = 25 ) { this . vertices . forEach ( ( vertex , index ) => { ctx . moveTo ( vertex . x , vertex . y ) ; const normal = this . getVertexNormal ( index ) ; ctx . lineTo ( vertex . x + normal . x * len , vertex . y + normal . y * len ) ; } ) ; return this ; } }