import type { Helpers } from './helpers' ; see https author dmagunov + fork contributions from Alex Birch
 *  license export class CanvasDebugDraw { constructor ( private readonly box2D , private readonly helpers , private readonly context , private readonly canvasScaleFactor ) { } static drawAxes ( ctx ) { ctx . strokeStyle = 'rgb(192,0,0)' ; ctx . beginPath ( ) ; ctx . moveTo ( 0 , 0 ) ; ctx . lineTo ( 1 , 0 ) ; ctx . stroke ( ) ; ctx . strokeStyle = 'rgb(0,192,0)' ; ctx . beginPath ( ) ; ctx . moveTo ( 0 , 0 ) ; ctx . lineTo ( 0 , 1 ) ; ctx . stroke ( ) ; } setColorFromDebugDrawCallback = ( color_p ) : void => { const { wrapPointer , b2Color } = this . box2D ; const col = wrapPointer ( color_p , b2Color ) ; const red = ( col . get_r ( ) * 255 ) | 0 ; const green = ( col . get_g ( ) * 255 ) | 0 ; const blue = ( col . get_b ( ) * 255 ) | 0 ; const colStr = `${ red },${ green },${ blue }` ; this . context . fillStyle = `rgba(${ colStr },0.5)` ; this . context . strokeStyle = `rgb(${ colStr })` ; } ; drawPoint = ( vec_p , sizeMetres , color_p ) : void => { const { wrapPointer , b2Vec2 } = this . box2D ; const vert = wrapPointer ( vec_p , b2Vec2 ) ; this . setColorFromDebugDrawCallback ( color_p ) ; const sizePixels = sizeMetres / this . canvasScaleFactor ; this . context . fillRect ( vert . get_x ( ) - sizePixels / 2 , vert . get_y ( ) - sizePixels / 2 , sizePixels , sizePixels ) ; } ; drawSegment = ( vert1_p , vert2_p ) : void => { const { wrapPointer , b2Vec2 } = this . box2D ; const vert1V = wrapPointer ( vert1_p , b2Vec2 ) ; const vert2V = wrapPointer ( vert2_p , b2Vec2 ) ; this . context . beginPath ( ) ; this . context . moveTo ( vert1V . get_x ( ) , vert1V . get_y ( ) ) ; this . context . lineTo ( vert2V . get_x ( ) , vert2V . get_y ( ) ) ; this . context . stroke ( ) ; } ; drawPolygon = ( vertices , vertexCount , fill ) : void => { const { wrapPointer , b2Vec2 } = this . box2D ; this . context . beginPath ( ) ; for ( let tmpI = 0 ; tmpI < vertexCount ; tmpI ++ ) { const vert = wrapPointer ( vertices + ( tmpI * 8 ) , b2Vec2 ) ; if ( tmpI === 0 ) { this . context . moveTo ( vert . get_x ( ) , vert . get_y ( ) ) ; } else { this . context . lineTo ( vert . get_x ( ) , vert . get_y ( ) ) ; } } this . context . closePath ( ) ; if ( fill ) { this . context . fill ( ) ; } this . context . stroke ( ) ; } ; drawCircle = ( center_p , radius , axis_p , fill ) : void => { const { wrapPointer , b2Vec2 } = this . box2D ; const { copyVec2 , scaledVec2 } = this . helpers ; const centerV = wrapPointer ( center_p , b2Vec2 ) ; const axisV = wrapPointer ( axis_p , b2Vec2 ) ; this . context . beginPath ( ) ; this . context . arc ( centerV . get_x ( ) , centerV . get_y ( ) , radius , 0 , 2 * Math . PI , false ) ; if ( fill ) { this . context . fill ( ) ; } this . context . stroke ( ) ; if ( fill ) { const vert2V = copyVec2 ( centerV ) ; vert2V . op_add ( scaledVec2 ( axisV , radius ) ) ; this . context . beginPath ( ) ; this . context . moveTo ( centerV . get_x ( ) , centerV . get_y ( ) ) ; this . context . lineTo ( vert2V . get_x ( ) , vert2V . get_y ( ) ) ; this . context . stroke ( ) ; } } ; drawTransform = ( transform_p ) : void => { const { wrapPointer , b2Transform } = this . box2D ; const trans = wrapPointer ( transform_p , b2Transform ) ; const pos = trans . get_p ( ) ; const rot = trans . get_q ( ) ; this . context . save ( ) ; this . context . translate ( pos . get_x ( ) , pos . get_y ( ) ) ; this . context . scale ( 0.5 , 0.5 ) ; this . context . rotate ( rot . GetAngle ( ) ) ; this . context . lineWidth *= 2 ; CanvasDebugDraw . drawAxes ( this . context ) ; this . context . restore ( ) ; } ; constructJSDraw = ( ) : Box2D . JSDraw => { const { JSDraw , b2Vec2 , getPointer } = this . box2D ; const debugDraw = Object . assign ( new JSDraw ( ) , { DrawSegment : ( vert1_p , vert2_p , color_p ) : void => { this . setColorFromDebugDrawCallback ( color_p ) ; this . drawSegment ( vert1_p , vert2_p ) ; } , DrawPolygon : ( vertices , vertexCount , color_p ) : void => { this . setColorFromDebugDrawCallback ( color_p ) ; this . drawPolygon ( vertices , vertexCount , false ) ; } , DrawSolidPolygon : ( vertices , vertexCount , color_p ) : void => { this . setColorFromDebugDrawCallback ( color_p ) ; this . drawPolygon ( vertices , vertexCount , true ) ; } , DrawCircle : ( center_p , radius , color_p ) : void => { this . setColorFromDebugDrawCallback ( color_p ) ; const dummyAxis = new b2Vec2 ( 0 , 0 ) ; const dummyAxis_p = getPointer ( dummyAxis ) ; this . drawCircle ( center_p , radius , dummyAxis_p , false ) ; } , DrawSolidCircle : ( center_p , radius , axis_p , color_p ) : void => { this . setColorFromDebugDrawCallback ( color_p ) ; this . drawCircle ( center_p , radius , axis_p , true ) ; } , DrawTransform : ( transform_p ) : void => { this . drawTransform ( transform_p ) ; } , DrawPoint : ( vec_p , size , color_p ) : void => { this . drawPoint ( vec_p , size , color_p ) ; } } ) ; return debugDraw ; } ; }