pts 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/Canvas.ts","../src/Space.ts","../src/Pt.ts","../src/Util.ts","../src/Num.ts","../src/Op.ts","../src/LinearAlgebra.ts","../src/uheprng.ts","../src/UI.ts","../src/Form.ts","../src/Typography.ts","../src/Image.ts","../src/Create.ts","../src/Color.ts","../src/Dom.ts","../src/Svg.ts","../src/Physics.ts","../src/Play.ts","../src/_script.ts"],"sourcesContent":["/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport {MultiTouchSpace} from './Space';\r\nimport {VisualForm, Font} from \"./Form\";\r\nimport {Pt, Group, Bound} from \"./Pt\";\r\nimport {Const, Util} from \"./Util\";\r\nimport {Typography as Typo} from \"./Typography\";\r\nimport { Rectangle } from './Op';\r\nimport {Img} from './Image';\r\nimport {PtLike, GroupLike, PtsCanvasRenderingContext2D, DefaultFormStyle, PtLikeIterable, PtIterable, CanvasSpaceOptions} from \"./Types\";\r\n\r\n\r\n\r\n\r\n/**\r\n* CanvasSpace is an implementation of the abstract class [`Space`](#link). It represents a space for HTML Canvas.\r\n* Learn more about the concept of Space in [this guide](../guide/Space-0500.html).\r\n*/\r\nexport class CanvasSpace extends MultiTouchSpace {\r\n \r\n protected _canvas:HTMLCanvasElement;\r\n protected _container:Element;\r\n\r\n protected _pixelScale = 1;\r\n protected _autoResize = true;\r\n protected _bgcolor = \"#e1e9f0\";\r\n protected _ctx:PtsCanvasRenderingContext2D;\r\n \r\n protected _offscreen = false;\r\n protected _offCanvas:HTMLCanvasElement;\r\n protected _offCtx:PtsCanvasRenderingContext2D;\r\n\r\n protected _initialResize = false;\r\n \r\n\r\n \r\n /**\r\n * Create a CanvasSpace which represents a HTML Canvas Space\r\n * @param elem Specify an element by its \"id\" attribute as string, or by the element object itself. An element can be an existing `<canvas>`, or a `<div>` container in which a new `<canvas>` will be created. If left empty, a `<div id=\"pt_container\"><canvas id=\"pt\" /></div>` will be added to DOM. Use css to customize its appearance if needed.\r\n * @param callback an optional callback `function(boundingBox, spaceElement)` to be called when canvas is appended and ready. Alternatively, a \"ready\" event will also be fired from the `<canvas>` element when it's appended, which can be traced with `spaceInstance.canvas.addEventListener(\"ready\")`\r\n * @example `new CanvasSpace( \"#myElementID\" )`\r\n */\r\n constructor( elem:string | Element, callback?:Function ) {\r\n super();\r\n \r\n let _selector:Element = null;\r\n let _existed = false;\r\n this.id = \"pt\";\r\n \r\n // check element or element id string\r\n if ( elem instanceof Element ) {\r\n _selector = elem;\r\n this.id = \"pts_existing_space\";\r\n } else {\r\n let id = <string>elem;\r\n id = ( elem[0] === \"#\" || elem[0] === \".\" ) ? elem : \"#\" + elem;\r\n _selector = document.querySelector( id );\r\n _existed = true;\r\n this.id = id.substr( 1 );\r\n }\r\n \r\n // if selector is not defined, create a canvas\r\n if ( !_selector ) { \r\n this._container = this._createElement( \"div\", this.id + \"_container\" );\r\n this._canvas = this._createElement( \"canvas\", this.id ) as HTMLCanvasElement;\r\n this._container.appendChild( this._canvas );\r\n document.body.appendChild( this._container );\r\n _existed = false;\r\n \r\n // if selector is element but not canvas, create a canvas inside it\r\n } else if ( _selector.nodeName.toLowerCase() != \"canvas\" ) { \r\n this._container = _selector;\r\n this._canvas = this._createElement( \"canvas\", this.id + \"_canvas\" ) as HTMLCanvasElement;\r\n this._container.appendChild( this._canvas );\r\n this._initialResize = true;\r\n \r\n // if selector is an existing canvas\r\n } else {\r\n this._canvas = _selector as HTMLCanvasElement;\r\n this._container = _selector.parentElement;\r\n this._autoResize = false;\r\n }\r\n \r\n // if size is known then set it immediately\r\n // if (_existed) {\r\n // let b = this._container.getBoundingClientRect();\r\n // this.resize( Bound.fromBoundingRect(b) );\r\n // }\r\n \r\n // no mutation observer, so we set a timeout for ready event\r\n setTimeout( this._ready.bind( this, callback ), 100 );\r\n \r\n // store canvas 2d rendering context\r\n this._ctx = this._canvas.getContext( '2d' );\r\n \r\n }\r\n \r\n \r\n /**\r\n * Helper function to create a DOM element\r\n * @param elem element tag name\r\n * @param id element id attribute\r\n */\r\n protected _createElement( elem = \"div\", id ) {\r\n const d = document.createElement( elem );\r\n d.setAttribute( \"id\", id );\r\n return d;\r\n }\r\n \r\n \r\n /**\r\n * Handle callbacks after element is mounted in DOM\r\n * @param callback \r\n */\r\n private _ready( callback:Function ) {\r\n if ( !this._container ) throw new Error( `Cannot initiate #${this.id} element` );\r\n \r\n this._isReady = true;\r\n \r\n this._resizeHandler( null );\r\n\r\n this.clear( this._bgcolor );\r\n this._canvas.dispatchEvent( new Event( \"ready\" ) );\r\n \r\n for ( const k in this.players ) {\r\n if ( this.players.hasOwnProperty( k ) ) {\r\n if ( this.players[k].start ) this.players[k].start( this.bound.clone(), this );\r\n }\r\n }\r\n \r\n this._pointer = this.center;\r\n this._initialResize = false; // unset\r\n \r\n if ( callback ) callback( this.bound, this._canvas );\r\n }\r\n \r\n \r\n /**\r\n * Set up various options for CanvasSpace. The `opt` parameter is an object with the following fields. This is usually set during instantiation, eg `new CanvasSpace(...).setup( { opt } )`\r\n * @param opt a [`CanvasSpaceOptions`](#link) object with optional settings, ie `{ bgcolor:string, resize:boolean, retina:boolean, offscreen:boolean, pixelDensity:number }`. \r\n * @example `space.setup({ bgcolor: \"#f00\", retina: true, resize: true })`\r\n */\r\n setup( opt:CanvasSpaceOptions ):this {\r\n this._bgcolor = opt.bgcolor ? opt.bgcolor : \"transparent\";\r\n \r\n this.autoResize = ( opt.resize != undefined ) ? opt.resize : false;\r\n \r\n if ( opt.retina !== false ) {\r\n const r1 = window ? window.devicePixelRatio || 1 : 1;\r\n const r2 = this._ctx.webkitBackingStorePixelRatio || this._ctx.mozBackingStorePixelRatio || this._ctx.msBackingStorePixelRatio || this._ctx.oBackingStorePixelRatio || this._ctx.backingStorePixelRatio || 1; \r\n this._pixelScale = Math.max( 1, r1 / r2 );\r\n }\r\n \r\n if ( opt.offscreen ) {\r\n this._offscreen = true;\r\n this._offCanvas = this._createElement( \"canvas\", this.id + \"_offscreen\" ) as HTMLCanvasElement;\r\n this._offCtx = this._offCanvas.getContext( '2d' );\r\n } else {\r\n this._offscreen = false;\r\n }\r\n\r\n if ( opt.pixelDensity ) {\r\n this._pixelScale = opt.pixelDensity;\r\n }\r\n \r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set whether the canvas element should resize when its container is resized. \r\n * @param auto a boolean value indicating if auto size is set\r\n */\r\n set autoResize( auto ) {\r\n if ( !window ) return;\r\n this._autoResize = auto;\r\n if ( auto ) {\r\n window.addEventListener( 'resize', this._resizeHandler.bind( this ) );\r\n } else {\r\n window.removeEventListener( 'resize', this._resizeHandler.bind( this ) );\r\n }\r\n }\r\n get autoResize(): boolean { return this._autoResize; }\r\n \r\n \r\n /**\r\n * This overrides Space's `resize` function. It's used as a callback function for window's resize event and not usually called directly. You can keep track of resize events with `resize: (bound ,evt)` callback in your player objects. \r\n * @param b a Bound object to resize to\r\n * @param evt Optionally pass a resize event\r\n * @see Space.add\r\n */\r\n resize( b:Bound, evt?:Event ):this {\r\n \r\n this.bound = b;\r\n\r\n this._canvas.width = Math.ceil( this.bound.size.x ) * this._pixelScale;\r\n this._canvas.height = Math.ceil( this.bound.size.y ) * this._pixelScale;\r\n this._canvas.style.width = Math.ceil( this.bound.size.x ) + \"px\";\r\n this._canvas.style.height = Math.ceil( this.bound.size.y ) + \"px\";\r\n \r\n if ( this._offscreen ) {\r\n this._offCanvas.width = Math.ceil( this.bound.size.x ) * this._pixelScale;\r\n this._offCanvas.height = Math.ceil( this.bound.size.y ) * this._pixelScale;\r\n // this._offCanvas.style.width = Math.floor(this.bound.size.x) + \"px\";\r\n // this._offCanvas.style.height = Math.floor(this.bound.size.y) + \"px\";\r\n }\r\n \r\n if ( this._pixelScale != 1 ) {\r\n this._ctx.scale( this._pixelScale, this._pixelScale );\r\n \r\n if ( this._offscreen ) {\r\n this._offCtx.scale( this._pixelScale, this._pixelScale );\r\n }\r\n }\r\n \r\n for ( const k in this.players ) {\r\n if ( this.players.hasOwnProperty( k ) ) {\r\n const p = this.players[k];\r\n if ( p.resize ) p.resize( this.bound, evt );\r\n }\r\n }\r\n \r\n this.render( this._ctx );\r\n\r\n // if it's a valid resize event and space is not playing, repaint the canvas once\r\n if ( evt && !this.isPlaying ) this.playOnce( 0 ); \r\n \r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Window resize handling\r\n * @param evt \r\n */\r\n protected _resizeHandler( evt:Event ) {\r\n if ( !window ) return;\r\n const b = ( this._autoResize || this._initialResize ) ? this._container.getBoundingClientRect() : this._canvas.getBoundingClientRect();\r\n\r\n if ( b ) {\r\n const box = Bound.fromBoundingRect( b );\r\n \r\n // Need to compute offset from window scroll. See outerBound calculation in Space's _mouseAction \r\n box.center = box.center.add( window.pageXOffset, window.pageYOffset ); \r\n this.resize( box, evt );\r\n }\r\n }\r\n \r\n\r\n /**\r\n * Set a background color for this canvas. Alternatively, you may use `clear()` function.\r\n @param bg background color as hex or rgba string\r\n */\r\n set background( bg:string ) { this._bgcolor = bg; }\r\n get background():string { return this._bgcolor; }\r\n\r\n \r\n /**\r\n * `pixelScale` property returns a number that let you determine if the screen is \"retina\" (when value >= 2)\r\n */\r\n public get pixelScale():number {\r\n return this._pixelScale;\r\n }\r\n \r\n \r\n /**\r\n * Check if an offscreen canvas is created\r\n */\r\n public get hasOffscreen():boolean {\r\n return this._offscreen;\r\n }\r\n \r\n \r\n /**\r\n * Get the rendering context of offscreen canvas (if created via `setup()`)\r\n */\r\n public get offscreenCtx():PtsCanvasRenderingContext2D { return this._offCtx; }\r\n \r\n \r\n /**\r\n * Get the offscreen canvas element\r\n */\r\n public get offscreenCanvas():HTMLCanvasElement { return this._offCanvas; }\r\n \r\n \r\n\r\n \r\n /**\r\n * Get a new `CanvasForm` for drawing\r\n * @see `CanvasForm`\r\n */\r\n public getForm():CanvasForm { return new CanvasForm( this ); }\r\n \r\n \r\n /**\r\n * Get the html canvas element\r\n */\r\n get element():HTMLCanvasElement {\r\n return this._canvas;\r\n }\r\n \r\n \r\n /**\r\n * Get the parent element that contains the canvas element\r\n */\r\n get parent():Element {\r\n return this._container;\r\n }\r\n\r\n\r\n /**\r\n * A property to indicate if the Space is ready\r\n */\r\n get ready():boolean { \r\n return this._isReady; \r\n }\r\n \r\n \r\n /**\r\n * Get the rendering context of canvas\r\n * @example `form.ctx.clip()`\r\n */\r\n public get ctx():PtsCanvasRenderingContext2D { return this._ctx; }\r\n \r\n \r\n \r\n /**\r\n * Clear the canvas with its background color. Overrides Space's `clear` function.\r\n * @param bg Optionally specify a custom background color in hex or rgba string, or \"transparent\". If not defined, it will use its `bgcolor` property as background color to clear the canvas.\r\n */\r\n clear( bg?:string ):this {\r\n \r\n if ( bg ) this._bgcolor = bg;\r\n const lastColor = this._ctx.fillStyle;\r\n const px = Math.ceil( this.pixelScale );\r\n \r\n if ( !this._bgcolor || this._bgcolor === \"transparent\" ) {\r\n this._ctx.clearRect( -px, -px, this._canvas.width + px, this._canvas.height + px );\r\n } else { \r\n // semi-transparent bg needs to be cleared first\r\n if ( this._bgcolor.indexOf( \"rgba\" ) === 0 || ( this._bgcolor.length === 9 && this._bgcolor.indexOf( \"#\" ) === 0 ) ) { \r\n this._ctx.clearRect( -px, -px, this._canvas.width + px, this._canvas.height + px );\r\n }\r\n this._ctx.fillStyle = this._bgcolor;\r\n this._ctx.fillRect( -px, -px, this._canvas.width + px, this._canvas.height + px );\r\n }\r\n \r\n this._ctx.fillStyle = lastColor;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Similiar to `clear()` but clear the offscreen canvas instead\r\n * @param bg Optionally specify a custom background color in hex or rgba string, or \"transparent\". If not defined, it will use its `bgcolor` property as background color to clear the canvas.\r\n */\r\n clearOffscreen( bg?:string ):this {\r\n if ( this._offscreen ) {\r\n const px = Math.ceil( this.pixelScale );\r\n if ( bg ) {\r\n this._offCtx.fillStyle = bg;\r\n this._offCtx.fillRect( -px, -px, this._canvas.width + px, this._canvas.height + px );\r\n } else {\r\n this._offCtx.clearRect( -px, -px, this._offCanvas.width + px, this._offCanvas.height + px );\r\n }\r\n }\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Main animation function.\r\n * @param time current time\r\n */\r\n protected playItems( time: number ) {\r\n if ( this._isReady ) {\r\n this._ctx.save();\r\n if ( this._offscreen ) this._offCtx.save();\r\n super.playItems( time );\r\n this._ctx.restore();\r\n if ( this._offscreen ) this._offCtx.restore();\r\n this.render( this._ctx );\r\n }\r\n }\r\n \r\n \r\n /**\r\n * Dispose of browser resources held by this space and remove all players. Call this before unmounting the canvas.\r\n */\r\n dispose():this {\r\n if ( !window ) return;\r\n // remove event listeners\r\n window.removeEventListener( 'resize', this._resizeHandler.bind( this ) );\r\n // stop animation loop\r\n this.stop();\r\n // remove players from space\r\n this.removeAll();\r\n\r\n return this;\r\n }\r\n \r\n\r\n /**\r\n * Get a [`MediaRecorder`](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) to record the current CanvasSpace. You can then call its `start()` function to start recording, and `stop()` to either download the video file or handle the blob data in the callback function you provided.\r\n * @param downloadOrCallback Either `true` to download the video, or provide a callback function to handle the Blob data, when recording is completed.\r\n * @param filetype video format. Default is \"webm\".\r\n * @param bitrate bitrate per second\r\n * @example `let rec = space.recorder(true); rec.start(); setTimeout( () => rec.stop(), 5000); // record 5s of video and download the file`\r\n */\r\n recorder( downloadOrCallback: boolean | ( ( blobURL:string ) => {} ), filetype:string = \"webm\", bitrate:number = 15000000 ): MediaRecorder {\r\n const stream = this._canvas.captureStream();\r\n const recorder = new MediaRecorder( stream, { mimeType: `video/${filetype}`, bitsPerSecond: bitrate } );\r\n \r\n recorder.ondataavailable = function( d ) {\r\n const url = URL.createObjectURL( new Blob( [d.data], { type: `video/${filetype}` } ) );\r\n\r\n if ( typeof downloadOrCallback === \"function\" ) {\r\n downloadOrCallback( url );\r\n\r\n } else if ( downloadOrCallback ) {\r\n const a = document.createElement( \"a\" );\r\n a.href = url;\r\n a.download = `canvas_video.${filetype}`;\r\n a.click();\r\n a.remove();\r\n }\r\n };\r\n\r\n return recorder;\r\n }\r\n\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n* CanvasForm is an implementation of abstract class [`VisualForm`](#link). It provide methods to express Pts on [`CanvasSpace`](#link). \r\n* You may extend CanvasForm to implement your own expressions for CanvasSpace.\r\n*/\r\nexport class CanvasForm extends VisualForm {\r\n \r\n protected _space:CanvasSpace;\r\n protected _ctx:CanvasRenderingContext2D; \r\n protected _estimateTextWidth:( string ) => number;\r\n\r\n /** \r\n * store common styles so that they can be restored to canvas context when using multiple forms. See `reset()`.\r\n */\r\n protected _style:DefaultFormStyle = {\r\n fillStyle: \"#f03\", strokeStyle:\"#fff\", \r\n lineWidth: 1, lineJoin: \"bevel\", lineCap: \"butt\",\r\n globalAlpha: 1\r\n };\r\n \r\n \r\n /**\r\n * Create a new CanvasForm. You may also use [`CanvasSpace.getForm()`](#link) to get the default form.\r\n * @param space an instance of CanvasSpace\r\n */\r\n constructor( space?:CanvasSpace | CanvasRenderingContext2D ) {\r\n super();\r\n\r\n // allow for undefined context to support custom contexts via subclassing. \r\n if ( !space ) return this; \r\n \r\n const _setup = ( ctx ) => {\r\n this._ctx = ctx;\r\n this._ctx.fillStyle = this._style.fillStyle;\r\n this._ctx.strokeStyle = this._style.strokeStyle; \r\n this._ctx.lineJoin = \"bevel\";\r\n this._ctx.font = this._font.value;\r\n this._ready = true;\r\n };\r\n\r\n if ( space instanceof CanvasRenderingContext2D ) {\r\n _setup( space );\r\n } else {\r\n this._space = space;\r\n this._space.add( { start: () => {\r\n _setup( this._space.ctx );\r\n }} );\r\n }\r\n }\r\n \r\n \r\n /**\r\n * get the CanvasSpace instance that this form is associated with\r\n */\r\n get space():CanvasSpace { return this._space; }\r\n \r\n\r\n /**\r\n * Get the rendering context of canvas to perform other canvas functions.\r\n * @example `form.ctx.clip()`\r\n */\r\n get ctx():PtsCanvasRenderingContext2D { return this._ctx; }\r\n\r\n\r\n /**\r\n * Toggle whether to draw on offscreen canvas (if offscreen is set in CanvasSpace)\r\n * @param off if `true`, draw on offscreen canvas instead of the visible canvas. Default is `true`\r\n * @param clear optionally provide a valid color string to fill a bg color. see CanvasSpace's `clearOffscreen` function.\r\n */\r\n useOffscreen( off:boolean = true, clear:boolean | string = false ) {\r\n if ( clear ) this._space.clearOffscreen( ( typeof clear == \"string\" ) ? clear : null );\r\n this._ctx = ( this._space.hasOffscreen && off ) ? this._space.offscreenCtx : this._space.ctx;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Render the offscreen canvas's content on the visible canvas\r\n * @param offset Optional offset on the top-left position when drawing on the visible canvas\r\n */\r\n renderOffscreen( offset:PtLike = [0,0] ) {\r\n if ( this._space.hasOffscreen ) {\r\n this._space.ctx.drawImage( \r\n this._space.offscreenCanvas, offset[0], offset[1], this._space.width, this._space.height );\r\n }\r\n }\r\n \r\n \r\n /**\r\n * Set current alpha value.\r\n * @example `form.alpha(0.6)`\r\n * @param a alpha value between 0 and 1\r\n */\r\n alpha( a:number ):this {\r\n this._ctx.globalAlpha = a;\r\n this._style.globalAlpha = a;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set current fill style. Provide a valid color string such as `\"#FFF\"` or `\"rgba(255,0,100,0.5)\"` or `false` to specify no fill color.\r\n * @example `form.fill(\"#F90\")`, `form.fill(\"rgba(0,0,0,.5\")`, `form.fill(false)`\r\n * @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))\r\n */\r\n fill( c:string | boolean | CanvasGradient | CanvasPattern ):this {\r\n if ( typeof c == \"boolean\" ) {\r\n this.filled = c;\r\n } else {\r\n this.filled = true;\r\n this._style.fillStyle = c;\r\n this._ctx.fillStyle = c;\r\n }\r\n return this;\r\n }\r\n \r\n /**\r\n * Set current fill style and remove stroke style.\r\n * @param c fill color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle))\r\n */\r\n fillOnly( c:string | boolean | CanvasGradient | CanvasPattern ):this {\r\n this.stroke( false );\r\n return this.fill( c );\r\n }\r\n \r\n \r\n /**\r\n * Set current stroke style. Provide a valid color string or `false` to specify no stroke color.\r\n * @example `form.stroke(\"#F90\")`, `form.stroke(\"rgba(0,0,0,.5\")`, `form.stroke(false)`, `form.stroke(\"#000\", 0.5, 'round', 'square')`\r\n * @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))\r\n * @param width Optional value (can be floating point) to set line width\r\n * @param linejoin Optional string to set line joint style. Can be \"miter\", \"bevel\", or \"round\".\r\n * @param linecap Optional string to set line cap style. Can be \"butt\", \"round\", or \"square\".\r\n */\r\n stroke( c:string | boolean | CanvasGradient | CanvasPattern, width?:number, linejoin?:CanvasLineJoin, linecap?:CanvasLineCap ):this {\r\n if ( typeof c == \"boolean\" ) {\r\n this.stroked = c;\r\n } else {\r\n this.stroked = true;\r\n this._style.strokeStyle = c;\r\n this._ctx.strokeStyle = c;\r\n if ( width ) {\r\n this._ctx.lineWidth = width;\r\n this._style.lineWidth = width;\r\n }\r\n if ( linejoin ) {\r\n this._ctx.lineJoin = linejoin;\r\n this._style.lineJoin = linejoin;\r\n }\r\n if ( linecap ) {\r\n this._ctx.lineCap = linecap;\r\n this._style.lineCap = linecap;\r\n }\r\n }\r\n return this;\r\n }\r\n\r\n /**\r\n * Set stroke style and remove fill style.\r\n * @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))\r\n * @param width Optional value (can be floating point) to set line width\r\n * @param linejoin Optional string to set line joint style. Can be \"miter\", \"bevel\", or \"round\".\r\n * @param linecap Optional string to set line cap style. Can be \"butt\", \"round\", or \"square\".\r\n */\r\n strokeOnly( c:string | boolean | CanvasGradient | CanvasPattern, width?:number, linejoin?:CanvasLineJoin, linecap?:CanvasLineCap ):this {\r\n this.fill( false );\r\n return this.stroke( c, width, linejoin, linecap );\r\n }\r\n\r\n /**\r\n * A convenient function to apply fill and/or stroke after custom drawings using canvas context (eg, `form.ctx.ellipse(...)`). \r\n * You don't need to call this function if you're using Pts' drawing functions like `form.point` or `form.rect`\r\n * @param filled apply fill when set to `true`\r\n * @param stroked apply stroke when set to `true`\r\n * @param strokeWidth optionally set a stroke width\r\n * @example `form.ctx.beginPath(); form.ctx.ellipse(...); form.applyFillStroke();`\r\n */\r\n applyFillStroke( filled:boolean | string = true, stroked:boolean | string = true, strokeWidth:number = 1 ) {\r\n if ( filled ) {\r\n if ( typeof filled === 'string' ) this.fill( filled );\r\n this._ctx.fill();\r\n }\r\n\r\n if ( stroked ) {\r\n if ( typeof stroked === 'string' ) this.stroke( stroked, strokeWidth );\r\n this._ctx.stroke();\r\n }\r\n\r\n return this;\r\n }\r\n \r\n\r\n /**\r\n * This function takes an array of gradient colors, and returns a function to define the areas of the gradient fill. See demo code in [CanvasForm.gradient](https://ptsjs.org/demo/?name=canvasform.textBox).\r\n * @param stops an array of gradient stops. This can be an array of colors `[\"#f00\", \"#0f0\", ...]` for evenly distributed gradient, or an array of [stop, color] like `[[0.1, \"#f00\"], [0.7, \"#0f0\"]]`\r\n * @returns a function that takes 1 or 2 `Group` as parameters. Use a single `Group` to specify a rectangular area for linear gradient, or use 2 `Groups` to specify 2 `Circles` for radial gradient.\r\n * @example `c1 = Circle.fromCenter(...); grad = form.gradient([\"#f00\", \"#00f\"]); form.fill( grad( c1, c2 ) ).circle( c1 )`\r\n */\r\n gradient( stops:[number, string][] | string[] ):( ( area1:GroupLike, area2?:GroupLike ) => CanvasGradient ) {\r\n const vals:[number, string][] = [];\r\n if ( stops.length < 2 ) ( stops as [number, string][] ).push( [0.99, \"#000\"], [1,\"#000\"] );\r\n\r\n for ( let i = 0, len = stops.length; i < len; i++ ) {\r\n const t:number = typeof stops[i] === 'string' ? i * ( 1 / ( stops.length - 1 ) ) : stops[i][0] as number;\r\n const v: string = typeof stops[i] === 'string' ? stops[i] as string : stops[i][1] as string;\r\n vals.push( [t, v] );\r\n }\r\n\r\n return ( area1:GroupLike, area2?:GroupLike ) => {\r\n const grad = area2 \r\n ? this._ctx.createRadialGradient( area1[0][0], area1[0][1], Math.abs( area1[1][0] ), area2[0][0], area2[0][1], Math.abs( area2[1][0] ) )\r\n : this._ctx.createLinearGradient( area1[0][0], area1[0][1], area1[1][0], area1[1][1] );\r\n\r\n for ( let i = 0, len = vals.length; i < len; i++ ) {\r\n grad.addColorStop( vals[i][0], vals[i][1] );\r\n }\r\n\r\n return grad;\r\n };\r\n }\r\n\r\n\r\n /**\r\n * Set composite operation (also known as blend mode). You can also call this function without parameters to get back to default 'source-over' mode. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation) for the full list of operations you can use.\r\n * @param mode a composite operation such as 'lighten', 'multiply', 'overlay', and 'color-burn'.\r\n */\r\n composite( mode:GlobalCompositeOperation = 'source-over' ):this {\r\n this._ctx.globalCompositeOperation = mode;\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Create a clipping mask from the current path. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip) for details.\r\n */\r\n clip():this {\r\n this._ctx.clip();\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Activate dashed stroke and set dash style. You can customize the segments and offset.\r\n * @example `form.dash()`, `form.dash([5, 10])`, `form.dash([5, 5], 5)`, `form.dash(false)`\r\n * @param segments Dash segments. Defaults to `true` which corresponds to `[5, 5]`. Pass `false` to deactivate dashes. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash))\r\n * @param offset Dash offset. Defaults to 0. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset)\r\n */\r\n dash( segments:PtLike | boolean = true, offset:number = 0 ):this {\r\n if ( !segments ) {\r\n // false or [], deactivate dashed strokes\r\n this._ctx.setLineDash( [] );\r\n this._ctx.lineDashOffset = 0;\r\n } else {\r\n if ( segments === true ) {\r\n segments = [5, 5];\r\n }\r\n this._ctx.setLineDash( [segments[0], segments[1]] );\r\n this._ctx.lineDashOffset = offset;\r\n }\r\n return this;\r\n }\r\n \r\n \r\n \r\n /**\r\n * Set the current font.\r\n * @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties\r\n * @param weight Optional font-weight string such as \"bold\"\r\n * @param style Optional font-style string such as \"italic\"\r\n * @param lineHeight Optional line-height number suchas 1.5\r\n * @param family Optional font-family such as \"Helvetica, sans-serif\"\r\n * @example `form.font( myFont )`, `form.font(14, \"bold\")`\r\n */\r\n font( sizeOrFont:number | Font, weight?:string, style?:string, lineHeight?:number, family?:string ):this {\r\n if ( typeof sizeOrFont == \"number\" ) {\r\n \r\n this._font.size = sizeOrFont;\r\n if ( family ) this._font.face = family;\r\n if ( weight ) this._font.weight = weight;\r\n if ( style ) this._font.style = style;\r\n if ( lineHeight ) this._font.lineHeight = lineHeight;\r\n \r\n } else {\r\n this._font = sizeOrFont;\r\n }\r\n\r\n this._ctx.font = this._font.value;\r\n\r\n // If using estimate, reapply it when font changes.\r\n if ( this._estimateTextWidth ) this.fontWidthEstimate( true );\r\n\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Set whether to use html canvas' [`measureText`](#link) function, or a faster but less accurate heuristic function.\r\n * @param estimate `true` to use heuristic function, or `false` to use ctx.measureText\r\n */\r\n fontWidthEstimate( estimate:boolean = true ):this {\r\n this._estimateTextWidth = ( estimate ) ? Typo.textWidthEstimator( ( ( c:string ) => this._ctx.measureText( c ).width ) ) : undefined;\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get the width of this text. It will return an actual measurement or an estimate based on [`fontWidthEstimate`](#link) setting. Default is an actual measurement using canvas context's measureText.\r\n * @param c a string of text contents\r\n */\r\n getTextWidth( c:string ):number {\r\n return ( !this._estimateTextWidth ) ? this._ctx.measureText( c + \" .\" ).width : this._estimateTextWidth( c );\r\n }\r\n\r\n\r\n /**\r\n * Truncate text to fit width.\r\n * @param str text to truncate\r\n * @param width width to fit\r\n * @param tail text to indicate overflow such as \"...\". Default is empty \"\".\r\n */\r\n protected _textTruncate( str:string, width:number, tail:string = \"\" ):[string, number] {\r\n return Typo.truncate( this.getTextWidth.bind( this ), str, width, tail );\r\n }\r\n\r\n\r\n /**\r\n * Align text within a rectangle box.\r\n * @param box a Group or an Iterable<PtLike> that defines a rectangular box\r\n * @param vertical a string that specifies the vertical alignment in the box: \"top\", \"bottom\", \"middle\", \"start\", \"end\"\r\n * @param offset Optional offset from the edge (like padding)\r\n * @param center Optional center position \r\n */\r\n protected _textAlign( box:PtLikeIterable, vertical:string, offset?:PtLike, center?:Pt ):Pt {\r\n const _box = Util.iterToArray( box );\r\n if ( !Util.arrayCheck( _box ) ) return;\r\n\r\n if ( !center ) center = Rectangle.center( _box );\r\n\r\n let px = _box[0][0];\r\n if ( this._ctx.textAlign == \"end\" || this._ctx.textAlign == \"right\" ) {\r\n px = _box[1][0];\r\n // @ts-ignore\r\n } else if ( this._ctx.textAlign == \"center\" || this._ctx.textAlign == \"middle\" ) {\r\n px = center[0];\r\n }\r\n\r\n let py = center[1];\r\n if ( vertical == \"top\" || vertical == \"start\" ) {\r\n py = _box[0][1];\r\n } else if ( vertical == \"end\" || vertical == \"bottom\" ) {\r\n py = _box[1][1];\r\n }\r\n\r\n return ( offset ) ? new Pt( px + offset[0], py + offset[1] ) : new Pt( px, py );\r\n }\r\n \r\n \r\n /**\r\n * Reset the rendering context's common styles to this form's styles. This supports using multiple forms on the same canvas context.\r\n */\r\n reset():this {\r\n for ( const k in this._style ) {\r\n if ( this._style.hasOwnProperty( k ) ) {\r\n this._ctx[k] = this._style[k];\r\n }\r\n }\r\n this._font = new Font();\r\n this._ctx.font = this._font.value;\r\n return this;\r\n }\r\n \r\n \r\n protected _paint() {\r\n if ( this._filled ) this._ctx.fill();\r\n if ( this._stroked ) this._ctx.stroke();\r\n }\r\n \r\n\r\n /**\r\n * A static function to draw a point.\r\n * @param ctx canvas rendering context\r\n * @param p a Pt object\r\n * @param radius radius of the point. Default is 5.\r\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\r\n * @example `form.point( p )`, `form.point( p, 10, \"circle\" )`\r\n */\r\n static point( ctx:CanvasRenderingContext2D, p:PtLike, radius:number = 5, shape:string = \"square\" ) {\r\n if ( !p ) return;\r\n if ( !CanvasForm[shape] ) throw new Error( `${shape} is not a static function of CanvasForm` );\r\n CanvasForm[shape]( ctx, p, radius );\r\n }\r\n \r\n\r\n /**\r\n * Draws a point.\r\n * @param p a Pt object\r\n * @param radius radius of the point. Default is 5.\r\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\r\n * @example `form.point( p )`, `form.point( p, 10, \"circle\" )`\r\n */\r\n point( p:PtLike, radius:number = 5, shape:string = \"square\" ):this {\r\n CanvasForm.point( this._ctx, p, radius, shape );\r\n this._paint();\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A static function to draw a circle.\r\n * @param ctx canvas rendering context\r\n * @param pt center position of the circle\r\n * @param radius radius of the circle\r\n */\r\n static circle( ctx:CanvasRenderingContext2D, pt:PtLike, radius:number = 10 ) {\r\n if ( !pt ) return;\r\n ctx.beginPath();\r\n ctx.arc( pt[0], pt[1], radius, 0, Const.two_pi, false );\r\n ctx.closePath();\r\n }\r\n \r\n \r\n /**\r\n * Draw a circle. See also [`Circle.fromCenter`](#link)\r\n * @param pts usually a Group or an Iterable<PtLike> with 2 Pt, but it can also take an array of two numeric arrays [ [position], [size] ]\r\n */\r\n circle( pts:PtLikeIterable ):this {\r\n const p = Util.iterToArray( pts );\r\n CanvasForm.circle( this._ctx, p[0], p[1][0] );\r\n this._paint();\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A static function to draw an ellipse.\r\n * @param ctx canvas rendering context\r\n * @param pt center position \r\n * @param radius radius [x, y] of the ellipse\r\n * @param rotation rotation of the ellipse in radian. Default is 0.\r\n * @param startAngle start angle of the ellipse. Default is 0.\r\n * @param endAngle end angle of the ellipse. Default is 2 PI.\r\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\r\n */\r\n static ellipse( ctx:CanvasRenderingContext2D, pt:PtLike, radius:PtLike, rotation:number = 0, startAngle:number = 0, endAngle:number = Const.two_pi, cc:boolean = false ) {\r\n if ( !pt || !radius ) return;\r\n ctx.beginPath();\r\n ctx.ellipse( pt[0], pt[1], radius[0], radius[1], rotation, startAngle, endAngle, cc );\r\n }\r\n\r\n\r\n /**\r\n * Draw an ellipse.\r\n * @param pt center position \r\n * @param radius radius [x, y] of the ellipse\r\n * @param rotation rotation of the ellipse in radian. Default is 0.\r\n * @param startAngle start angle of the ellipse. Default is 0.\r\n * @param endAngle end angle of the ellipse. Default is 2 PI.\r\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\r\n */\r\n ellipse( pt:PtLike, radius:PtLike, rotation:number = 0, startAngle:number = 0, endAngle:number = Const.two_pi, cc:boolean = false ) {\r\n CanvasForm.ellipse( this._ctx, pt, radius, rotation, startAngle, endAngle, cc );\r\n this._paint();\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * A static function to draw an arc.\r\n * @param ctx canvas rendering context\r\n * @param pt center position \r\n * @param radius radius of the arc circle\r\n * @param startAngle start angle of the arc\r\n * @param endAngle end angle of the arc\r\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\r\n */\r\n static arc( ctx:CanvasRenderingContext2D, pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ) {\r\n if ( !pt ) return;\r\n ctx.beginPath();\r\n ctx.arc( pt[0], pt[1], radius, startAngle, endAngle, cc );\r\n }\r\n\r\n\r\n /**\r\n * Draw an arc.\r\n * @param pt center position\r\n * @param radius radius of the arc circle\r\n * @param startAngle start angle of the arc\r\n * @param endAngle end angle of the arc\r\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\r\n */\r\n arc( pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ):this {\r\n CanvasForm.arc( this._ctx, pt, radius, startAngle, endAngle, cc );\r\n this._paint();\r\n return this;\r\n }\r\n\r\n \r\n /**\r\n * A static function to draw a square.\r\n * @param ctx canvas rendering context\r\n * @param pt center position of the square\r\n * @param halfsize half size of the square\r\n */\r\n static square( ctx:CanvasRenderingContext2D, pt:PtLike, halfsize:number ) {\r\n if ( !pt ) return;\r\n const x1 = pt[0] - halfsize;\r\n const y1 = pt[1] - halfsize;\r\n const x2 = pt[0] + halfsize;\r\n const y2 = pt[1] + halfsize;\r\n \r\n // faster than using `rect`\r\n ctx.beginPath();\r\n ctx.moveTo( x1, y1 );\r\n ctx.lineTo( x1, y2 );\r\n ctx.lineTo( x2, y2 );\r\n ctx.lineTo( x2, y1 );\r\n ctx.closePath();\r\n }\r\n \r\n \r\n /**\r\n * Draw a square, given a center and its half-size.\r\n * @param pt center Pt\r\n * @param halfsize half-size\r\n */\r\n square( pt:PtLike, halfsize:number ) {\r\n CanvasForm.square( this._ctx, pt, halfsize );\r\n this._paint();\r\n return this;\r\n }\r\n\r\n \r\n /**\r\n * A static function to draw a line or polyline.\r\n * @param ctx canvas rendering context\r\n * @param pts a Group or an Iterable<PtLike> representing a line\r\n */\r\n static line( ctx:CanvasRenderingContext2D, pts:PtLikeIterable ) {\r\n if ( !Util.arrayCheck( pts ) ) return;\r\n let i = 0;\r\n ctx.beginPath();\r\n for ( const it of pts ) {\r\n if ( it ) {\r\n if ( i++ > 0 ) {\r\n ctx.lineTo( it[0], it[1] );\r\n } else {\r\n ctx.moveTo( it[0], it[1] );\r\n }\r\n }\r\n }\r\n }\r\n \r\n \r\n /**\r\n * Draw a line or polyline.\r\n * @param pts a Group or an Iterable<PtLike> representing a line\r\n */\r\n line( pts:PtLikeIterable ):this {\r\n CanvasForm.line( this._ctx, pts );\r\n this._paint();\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A static function to draw a polygon.\r\n * @param ctx canvas rendering context\r\n * @param pts a Group or an Iterable<PtLike> representing a polygon\r\n */\r\n static polygon( ctx:CanvasRenderingContext2D, pts:PtLikeIterable ) {\r\n if ( !Util.arrayCheck( pts ) ) return;\r\n CanvasForm.line( ctx, pts );\r\n ctx.closePath();\r\n }\r\n \r\n \r\n /**\r\n * Draw a polygon.\r\n * @param pts a Group or an Iterable<PtLike> representingg a polygon\r\n */\r\n polygon( pts:PtLikeIterable ):this {\r\n CanvasForm.polygon( this._ctx, pts );\r\n this._paint();\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A static function to draw a rectangle.\r\n * @param ctx canvas rendering context\r\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.\r\n */\r\n static rect( ctx:CanvasRenderingContext2D, pts:PtLikeIterable ) {\r\n const p = Util.iterToArray( pts );\r\n if ( !Util.arrayCheck( p ) ) return;\r\n ctx.beginPath();\r\n ctx.moveTo( p[0][0], p[0][1] );\r\n ctx.lineTo( p[0][0], p[1][1] );\r\n ctx.lineTo( p[1][0], p[1][1] );\r\n ctx.lineTo( p[1][0], p[0][1] );\r\n ctx.closePath();\r\n \r\n }\r\n \r\n \r\n /**\r\n * Draw a rectangle.\r\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.\r\n */\r\n rect( pts:PtLikeIterable ):this {\r\n CanvasForm.rect( this._ctx, pts );\r\n this._paint();\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * A static function to draw an image.\r\n * @param ctx canvas rendering context\r\n * @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)\r\n * @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.\r\n * @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a cropping box in the original target. \r\n */\r\n static image( ctx:CanvasRenderingContext2D, ptOrRect:PtLike | PtLikeIterable, img:CanvasImageSource | Img, orig?:PtLikeIterable ) {\r\n const t = Util.iterToArray( ptOrRect );\r\n let pos:number[];\r\n\r\n if ( typeof t[0] === \"number\" ) { // no crop\r\n pos = t as number[];\r\n\r\n } else {\r\n if ( orig ) { // crop\r\n const o = Util.iterToArray( orig );\r\n pos = [o[0][0], o[0][1], o[1][0] - o[0][0], o[1][1] - o[0][1], \r\n t[0][0], t[0][1], t[1][0] - t[0][0], t[1][1] - t[0][1]];\r\n\r\n } else { // bounding box resize\r\n pos = [t[0][0], t[0][1], t[1][0] - t[0][0], t[1][1] - t[0][1]];\r\n } \r\n }\r\n\r\n if ( img instanceof Img ) {\r\n if ( img.loaded ) {\r\n // @ts-ignore\r\n ctx.drawImage( img.image, ...pos );\r\n }\r\n } else {\r\n // @ts-ignore\r\n ctx.drawImage( img, ...pos );\r\n }\r\n }\r\n \r\n \r\n /**\r\n * Draw an image.\r\n * @param img either an [Img](#link) instance or an [`CanvasImageSource`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasImageSource) instance (eg the image from `<img>`, `<video>` or `<canvas>`)\r\n * @param ptOrRect a target area to place the image. Either a PtLike specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a bounding box. Default is (0,0) at top-left.\r\n * @param orig optionally a Group or an Iterable<PtLike> with 2 Pt (top-left position, bottom-right position) that specifies a cropping box in the original target. \r\n */\r\n image( ptOrRect:PtLike | PtLikeIterable, img:CanvasImageSource | Img, orig?:PtLikeIterable ) {\r\n if ( img instanceof Img ) {\r\n if ( img.loaded ) {\r\n CanvasForm.image( this._ctx, ptOrRect, img.image, orig );\r\n }\r\n } else {\r\n CanvasForm.image( this._ctx, ptOrRect, img, orig );\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * A static function to draw ImageData on canvas\r\n * @param ctx canvas rendering context\r\n * @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.\r\n * @param img an ImageData object\r\n */\r\n static imageData( ctx:CanvasRenderingContext2D, ptOrRect:PtLike | PtLikeIterable, img:ImageData ) {\r\n const t = Util.iterToArray( ptOrRect );\r\n if ( typeof t[0] === \"number\" ) { // Pt\r\n ctx.putImageData( img, t[0], t[1] );\r\n } else { // rect\r\n ctx.putImageData( img, t[0][0], t[0][1], t[0][0], t[0][1], t[1][0], t[1][1] );\r\n }\r\n }\r\n\r\n\r\n /**\r\n * Draw ImageData on canvas using ImageData\r\n * @param ptOrRect a target area to place the image. Either a Pt or numeric array specifying a position, or a Group or an Iterable<PtLike> with 2 Pt (top-left, bottom-right) that specifies a bounding box for resizing. Default is (0,0) at top-left.\r\n * @param img an ImageData object\r\n */\r\n imageData( ptOrRect:PtLike | PtLikeIterable, img:ImageData ) {\r\n CanvasForm.imageData( this._ctx, ptOrRect, img );\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A static function to draw text.\r\n * @param ctx canvas rendering context\r\n * @param `pt` a Point object to specify the anchor point\r\n * @param `txt` a string of text to draw\r\n * @param `maxWidth` specify a maximum width per line\r\n */\r\n static text( ctx:CanvasRenderingContext2D, pt:PtLike, txt:string, maxWidth?:number ) {\r\n if ( !pt ) return;\r\n ctx.fillText( txt, pt[0], pt[1], maxWidth );\r\n }\r\n \r\n \r\n /**\r\n * Draw text on canvas.\r\n * @param `pt` a Pt or numeric array to specify the anchor point\r\n * @param `txt` text\r\n * @param `maxWidth` specify a maximum width per line\r\n */\r\n text( pt:PtLike, txt:string, maxWidth?:number ): this {\r\n CanvasForm.text( this._ctx, pt, txt, maxWidth );\r\n return this;\r\n }\r\n \r\n\r\n /**\r\n * Fit a single-line text in a rectangular box.\r\n * @param box a rectangle box defined by a Group or an Iterable<Pt>\r\n * @param txt string of text\r\n * @param tail text to indicate overflow such as \"...\". Default is empty \"\".\r\n * @param verticalAlign \"top\", \"middle\", or \"bottom\" to specify vertical alignment inside the box\r\n * @param overrideBaseline If `true`, use the corresponding baseline as verticalAlign. If `false`, use the current canvas context's textBaseline setting. Default is `true`.\r\n */\r\n textBox( box:PtIterable, txt:string, verticalAlign:string = \"middle\", tail:string = \"\", overrideBaseline:boolean = true ): this {\r\n // @ts-ignore\r\n if ( overrideBaseline ) this._ctx.textBaseline = verticalAlign;\r\n const size = Rectangle.size( box );\r\n const t = this._textTruncate( txt, size[0], tail );\r\n this.text( this._textAlign( box, verticalAlign ), t[0] );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Fit multi-line text in a rectangular box. Note that this will also set canvas context's textBaseline to \"top\".\r\n * @param box a Group or an Iterable<PtLike> with 2 Pt that represents a bounding box\r\n * @param txt string of text\r\n * @param lineHeight line height as a ratio of font size. Default is 1.2.\r\n * @param verticalAlign \"top\", \"middle\", or \"bottom\" to specify vertical alignment inside the box\r\n * @param crop a boolean to specify whether to crop text when overflowing\r\n */\r\n paragraphBox( box:PtLikeIterable, txt:string, lineHeight:number = 1.2, verticalAlign:string = \"top\", crop:boolean = true ):this {\r\n const b = Util.iterToArray( box );\r\n const size = Rectangle.size( b );\r\n this._ctx.textBaseline = \"top\"; // override textBaseline\r\n \r\n const lstep = this._font.size * lineHeight;\r\n\r\n // find next lines recursively\r\n const nextLine = ( sub:string, buffer:string[] = [], cc:number = 0 ) => {\r\n if ( !sub ) return buffer;\r\n if ( crop && cc * lstep > size[1] - lstep * 2 ) return buffer;\r\n if ( cc > 10000 ) throw new Error( \"max recursion reached (10000)\" );\r\n\r\n const t = this._textTruncate( sub, size[0], \"\" );\r\n\r\n // new line\r\n const newln = t[0].indexOf( \"\\n\" );\r\n if ( newln >= 0 ) {\r\n buffer.push( t[0].substr( 0, newln ) );\r\n return nextLine( sub.substr( newln + 1 ), buffer, cc + 1 ); \r\n }\r\n\r\n // word wrap\r\n let dt = t[0].lastIndexOf( \" \" ) + 1;\r\n if ( dt <= 0 || t[1] === sub.length ) dt = undefined;\r\n const line = t[0].substr( 0, dt );\r\n buffer.push( line );\r\n\r\n return ( t[1] <= 0 || t[1] === sub.length ) ? buffer : nextLine( sub.substr( ( dt || t[1] ) ), buffer, cc + 1 );\r\n };\r\n\r\n const lines = nextLine( txt ); // go through all lines\r\n const lsize = lines.length * lstep; // total height\r\n let lbox = b;\r\n \r\n\r\n if ( verticalAlign == \"middle\" || verticalAlign == \"center\" ) {\r\n let lpad = ( size[1] - lsize ) / 2; \r\n if ( crop ) lpad = Math.max( 0, lpad ); \r\n lbox = new Group( b[0].$add( 0, lpad ), b[1].$subtract( 0, lpad ) );\r\n } else if ( verticalAlign == \"bottom\" ) {\r\n lbox = new Group( b[0].$add( 0, size[1] - lsize ), b[1] );\r\n } else {\r\n lbox = new Group( b[0], b[0].$add( size[0], lsize ) );\r\n }\r\n\r\n const center = Rectangle.center( lbox );\r\n for ( let i = 0, len = lines.length; i < len; i++ ) {\r\n this.text( this._textAlign( lbox, \"top\", [0, i * lstep], center ), lines[i] );\r\n }\r\n\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Set text alignment and baseline (eg, vertical-align).\r\n * @param alignment HTML canvas' textAlign option: \"left\", \"right\", \"center\", \"start\", or \"end\"\r\n * @param baseline HTML canvas' textBaseline option: \"top\", \"hanging\", \"middle\", \"alphabetic\", \"ideographic\", \"bottom\". For convenience, you can also use \"center\" (same as \"middle\"), and \"baseline\" (same as \"alphabetic\")\r\n */\r\n alignText( alignment:CanvasTextAlign = \"left\", baseline:CanvasTextBaseline = \"alphabetic\" ) {\r\n // @ts-ignore\r\n if ( baseline == \"center\" ) baseline = \"middle\";\r\n // @ts-ignore\r\n if ( baseline == \"baseline\" ) baseline = \"alphabetic\";\r\n this._ctx.textAlign = alignment;\r\n this._ctx.textBaseline = baseline;\r\n return this;\r\n }\r\n\r\n \r\n /**\r\n * A convenient way to draw some text on canvas for logging or debugging. It'll be draw on the top-left of the canvas as an overlay.\r\n * @param txt text\r\n */\r\n log( txt ):this {\r\n const w = this._ctx.measureText( txt ).width + 20;\r\n this.stroke( false ).fill( \"rgba(0,0,0,.4)\" ).rect( [[0,0], [w, 20]] );\r\n this.fill( \"#fff\" ).text( [10,14], txt ); \r\n return this;\r\n }\r\n \r\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport {Pt, Bound} from \"./Pt\";\r\nimport {Form} from \"./Form\";\r\nimport {UIPointerActions as UIA} from \"./UI\";\r\nimport {ITimer, ISpacePlayers, IPlayer, AnimateCallbackFn, TouchPointsKey} from \"./Types\";\r\n\r\n\r\n/**\r\n* Space is an abstract class that represents a general context for expressing Pts. It's extended through subclasses such as [`CanvasSpace`](#link) and [`SVGSpace`](#link). You can also create your own extension of Space.\r\n* See [Space guide](../guide/Space-0500.html) for details.\r\n*/\r\nexport abstract class Space {\r\n \r\n id: string = \"space\";\r\n protected bound: Bound = new Bound();\r\n \r\n protected _time: ITimer = { prev: 0, diff: 0, end: -1, min: 0 };\r\n protected players:ISpacePlayers = {};\r\n protected playerCount = 0;\r\n protected _ctx:any;\r\n \r\n private _animID:number = -1;\r\n \r\n private _pause:boolean = false;\r\n private _refresh:boolean = undefined;\r\n private _renderFunc: ( context:any, self:Space ) => null;\r\n \r\n protected _pointer:Pt = new Pt();\r\n\r\n protected _isReady = false;\r\n protected _playing = false;\r\n\r\n protected _keyDownBind: ( evt:KeyboardEvent ) => boolean;\r\n protected _keyUpBind: ( evt:KeyboardEvent ) => boolean;\r\n \r\n \r\n /**\r\n * Set whether the rendering should be repainted on each frame.\r\n * @param b a boolean value to set whether to repaint each frame\r\n */\r\n refresh( b:boolean ):this {\r\n this._refresh = b;\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Set a minimum frame time\r\n * @param ms at least this amount of miniseconds must have elapsed before frame advances\r\n */\r\n minFrameTime( ms:number = 0 ) {\r\n this._time.min = ms;\r\n }\r\n \r\n \r\n /**\r\n * Add an [`IPlayer`](#link) object or a [`AnimateCallbackFn`](#link) callback function to handle events in this Space. An IPlayer is an object with the following callback functions: \r\n * - required: `animate: fn( time, ftime, space )` \r\n * - optional: `start: fn(bound, space)` \r\n * - optional: `resize: fn( size, event )`\r\n * - optional: `action: fn( type, x, y, event )` \r\n * Subclasses of Space may define other callback functions.\r\n * @param player an [`IPlayer`](#link) object with animate function, or a callback function `fn(time, ftime)`. \r\n */\r\n add( p:IPlayer | AnimateCallbackFn ):this {\r\n const player:IPlayer = ( typeof p == \"function\" ) ? { animate: p } : p;\r\n \r\n const k = this.playerCount++;\r\n const pid = player.animateID || ( this.id + k );\r\n \r\n this.players[pid] = player;\r\n player.animateID = pid;\r\n if ( player.resize && this.bound.inited ) player.resize( this.bound ); \r\n \r\n // if _refresh is not set, set it to true\r\n if ( this._refresh === undefined ) this._refresh = true;\r\n \r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Remove a player from this Space.\r\n * @param player an IPlayer that has an `animateID` property\r\n */\r\n remove( player:IPlayer ):this {\r\n delete this.players[ player.animateID ];\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Remove all players from this Space.\r\n */\r\n removeAll():this {\r\n this.players = {};\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Main play loop. This implements `window.requestAnimationFrame` and calls it recursively. \r\n * You may override this `play()` function to implement your own animation loop.\r\n * @param time current time\r\n */\r\n play( time = 0 ):this {\r\n // make sure only one play loop is active \r\n if ( time === 0 && this._animID !== -1 ) {\r\n return;\r\n }\r\n this._animID = requestAnimationFrame( this.play.bind( this ) );\r\n if ( this._pause ) return this;\r\n \r\n this._time.diff = time - this._time.prev;\r\n if ( this._time.diff < this._time.min ) return this;\r\n this._time.prev = time;\r\n \r\n try {\r\n this.playItems( time );\r\n } catch ( err ) {\r\n cancelAnimationFrame( this._animID );\r\n this._animID = -1;\r\n this._playing = false;\r\n throw err;\r\n }\r\n \r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Replay the animation after [`Space.stop`](#link). This resets the end-time counter. \r\n * You may also use [`Space.pause`](#link) and [`resume`](#link) for temporary pause.\r\n */\r\n replay() {\r\n this._time.end = -1;\r\n this.play();\r\n }\r\n \r\n \r\n /**\r\n * Main animate function. This calls all the items to perform.\r\n * @param time current time\r\n */\r\n protected playItems( time: number ) {\r\n\r\n this._playing = true;\r\n \r\n // clear before draw if refresh is true\r\n if ( this._refresh ) this.clear();\r\n \r\n // animate all players\r\n if ( this._isReady ) {\r\n for ( const k in this.players ) {\r\n if ( this.players[k].animate ) this.players[k].animate( time, this._time.diff, this );\r\n }\r\n }\r\n \r\n // stop if time ended\r\n if ( this._time.end >= 0 && time > this._time.end ) {\r\n cancelAnimationFrame( this._animID );\r\n this._animID = -1;\r\n this._playing = false;\r\n }\r\n }\r\n \r\n \r\n /**\r\n * Pause the animation.\r\n * @param toggle a boolean value to set if this function call should be a toggle (between pause and resume)\r\n */\r\n pause( toggle = false ):this {\r\n this._pause = ( toggle ) ? !this._pause : true;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Resume the pause animation.\r\n */\r\n resume():this {\r\n this._pause = false;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Specify when the animation should stop: immediately, after a time period, or never stops.\r\n * @param t a value in millisecond to specify a time period to play before stopping, or `-1` to play forever, or `0` to end immediately. Default is 0 which will stop the animation immediately.\r\n */\r\n stop( t = 0 ):this {\r\n this._time.end = t;\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Play animation loop once. Optionally set a `duration` time to play for that specific duration.\r\n * @param duration a value in millisecond to specify a time period to play before stopping, or `-1` to play forever\r\n */\r\n playOnce( duration = 0 ):this {\r\n this.play();\r\n this.stop( duration );\r\n return this;\r\n }\r\n \r\n /**\r\n * Custom rendering.\r\n * @param context rendering context\r\n */\r\n protected render( context:any ):this {\r\n if ( this._renderFunc ) this._renderFunc( context, this );\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set a custom rendering function `fn(graphics_context, canvas_space)` if needed.\r\n */\r\n set customRendering( f:( context:any, self:Space ) => null ) { this._renderFunc = f; }\r\n get customRendering():( context:any, self:Space ) => null { return this._renderFunc; }\r\n \r\n\r\n /**\r\n * Indicate whether the animation is playing.\r\n */\r\n get isPlaying():boolean { return this._playing; }\r\n\r\n\r\n /**\r\n * The outer bounding box which includes its positions.\r\n */\r\n get outerBound():Bound { return this.bound.clone(); }\r\n \r\n \r\n /**\r\n * The inner bounding box of the space, excluding its positions.\r\n */\r\n public get innerBound():Bound { return new Bound( Pt.make( this.size.length, 0 ), this.size.clone() ); }\r\n \r\n \r\n /**\r\n * The size of this space's bounding box.\r\n */\r\n get size():Pt { return this.bound.size.clone(); }\r\n \r\n \r\n /**\r\n * The center of this space's bounding box.\r\n */\r\n get center():Pt { return this.size.divide( 2 ); }\r\n \r\n \r\n /**\r\n * The width of this space's bounding box.\r\n */\r\n get width():number { return this.bound.width; }\r\n \r\n \r\n /**\r\n * The height of this space's bounding box.\r\n */\r\n get height():number { return this.bound.height; }\r\n \r\n \r\n /**\r\n * Resize the space. To be implemented in subclasses.\r\n * @param b a Bound representing the position and size of the space\r\n * @param evt event\r\n */\r\n abstract resize( b:Bound, evt?:Event ):this;\r\n \r\n \r\n /**\r\n * clear all contents in the space. To be implemented in subclasses.\r\n */\r\n abstract clear():this;\r\n \r\n \r\n /**\r\n * Get a default form for drawing in this space. To be implemented in subclasses.\r\n */\r\n abstract getForm():Form;\r\n \r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * MultiTouchSpace is an abstract class that extends [`Space`](#link) to support user interactions via touch events. \r\n * It's extended through subclasses such as [`CanvasSpace`](#link) and [`SVGSpace`](#link). \r\n */\r\nexport abstract class MultiTouchSpace extends Space {\r\n \r\n // track mouse dragging\r\n protected _pressed = false;\r\n protected _dragged = false;\r\n \r\n protected _hasMouse = false;\r\n protected _hasTouch = false;\r\n protected _hasKeyboard = false;\r\n \r\n // accept subclasses that implements addEventListener, removeEventListener, dispatchEvent\r\n protected _canvas:EventTarget;\r\n \r\n /**\r\n * Get the mouse or touch pointer that stores the last action.\r\n */\r\n public get pointer():Pt {\r\n const p = this._pointer.clone();\r\n p.id = this._pointer.id;\r\n return p;\r\n }\r\n \r\n /**\r\n * Bind event listener in canvas element. You can also use [`MultiTouchSpace.bindMouse`](#link) or [`MultiTouchSpace.bindTouch`](#link) to bind mouse or touch events conveniently.\r\n * @param evt an event string such as \"mousedown\"\r\n * @param callback callback function for this event\r\n * @param options options for [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).\r\n * @param customTarget If needed, this is an optional parameter to set another event target that's not the canvas element itself. See [Technical Notes guide](/guide/Technical-notes-9000.html) for use cases.\r\n */\r\n bindCanvas( evt:string, callback:EventListener, options:any = {}, customTarget?:Element ) {\r\n const target = customTarget ? customTarget : this._canvas;\r\n target.addEventListener( evt, callback, options );\r\n }\r\n \r\n \r\n /**\r\n * Unbind a callback from the event listener.\r\n * @param evt an event string such as \"mousedown\"\r\n * @param callback callback function to unbind\r\n * @param options options for [removeEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener). This should match the options set in bindCanvas.\r\n * @param customTarget If customTarget is set in bindCanvas, you'll need to pass the same instance here to unbind\r\n */\r\n unbindCanvas( evt:string, callback:EventListener, options:any = {}, customTarget?:Element ) {\r\n const target = customTarget ? customTarget : this._canvas;\r\n target.removeEventListener( evt, callback, options );\r\n }\r\n \r\n\r\n bindDoc( evt:string, callback:EventListener, options:any = {} ) {\r\n if ( document ) {\r\n document.addEventListener( evt, callback, options );\r\n }\r\n }\r\n\r\n unbindDoc( evt:string, callback:EventListener, options:any = {} ) {\r\n if ( document ) {\r\n document.removeEventListener( evt, callback, options );\r\n }\r\n }\r\n \r\n\r\n /**\r\n * A convenient method to bind (or unbind) all mouse events in canvas element. \r\n * All [`IPlayer`](#link) objects added to this space that implement an `action` callback property will receive mouse event callbacks. \r\n * The types of mouse actions are defined by [`UIPointerActions`](#link) constants: \"up\", \"down\", \"move\", \"drag\", \"drop\", \"over\", and \"out\". \r\n * @param bind a boolean value to bind mouse events if set to `true`. If `false`, all mouse events will be unbound. Default is true.\r\n * @param customTarget If needed, this is an optional parameter to set another event target that's not the canvas element itself. See [Technical Notes guide](/guide/Technical-notes-9000.html) for use cases.\r\n * @see [`Space.add`](#link) \r\n */\r\n bindMouse( bind:boolean = true, customTarget?:Element ):this {\r\n if ( bind ) {\r\n this._mouseDown = this._mouseDown.bind( this );\r\n this._mouseUp = this._mouseUp.bind( this );\r\n this._mouseOver = this._mouseOver.bind( this );\r\n this._mouseOut = this._mouseOut.bind( this );\r\n this._mouseMove = this._mouseMove.bind( this );\r\n this._mouseClick = this._mouseClick.bind( this );\r\n this._contextMenu = this._contextMenu.bind( this );\r\n\r\n this.bindCanvas( \"pointerdown\", this._mouseDown, {}, customTarget );\r\n this.bindCanvas( \"pointerup\", this._mouseUp, {}, customTarget );\r\n this.bindCanvas( \"pointerover\", this._mouseOver, {}, customTarget );\r\n this.bindCanvas( \"pointerout\", this._mouseOut, {}, customTarget );\r\n this.bindCanvas( \"pointermove\", this._mouseMove, {}, customTarget );\r\n this.bindCanvas( \"click\", this._mouseClick, {}, customTarget );\r\n this.bindCanvas( \"contextmenu\", this._contextMenu, {}, customTarget );\r\n this._hasMouse = true;\r\n } else {\r\n this.unbindCanvas( \"pointerdown\", this._mouseDown, {}, customTarget );\r\n this.unbindCanvas( \"pointerup\", this._mouseUp, {}, customTarget );\r\n this.unbindCanvas( \"pointerover\", this._mouseOver, {}, customTarget );\r\n this.unbindCanvas( \"pointerout\", this._mouseOut, {}, customTarget );\r\n this.unbindCanvas( \"pointermove\", this._mouseMove, {}, customTarget );\r\n this.unbindCanvas( \"click\", this._mouseClick, {}, customTarget );\r\n this.unbindCanvas( \"contextmenu\", this._contextMenu, {}, customTarget );\r\n this._hasMouse = false;\r\n }\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * A convenient method to bind (or unbind) all touch events in canvas element. \r\n * All [`IPlayer`](#link) objects added to this space that implement an `action` callback property will receive touch event callbacks. \r\n * The types of mouse actions are defined by [`UIPointerActions`](#link) constants: \"up\", \"down\", \"move\", \"drag\", \"drop\", \"over\", and \"out\". \r\n * @param bind a boolean value to bind touch events if set to `true`. If `false`, all mouse events will be unbound. Default is true.\r\n * @param passive a boolean value to set passive mode, ie, it won't block scrolling. Default is false.\r\n * @param customTarget If needed, this is an optional parameter to set another event target that's not the canvas element itself. See [Technical Notes guide](/guide/Technical-notes-9000.html) for use cases.\r\n * @see [`Space.add`](#link)\r\n */\r\n bindTouch( bind:boolean = true, passive:boolean = false, customTarget?:Element ):this {\r\n if ( bind ) {\r\n this.bindCanvas( \"touchstart\", this._touchStart.bind( this ), {passive: passive}, customTarget );\r\n this.bindCanvas( \"touchend\", this._mouseUp.bind( this ), {}, customTarget );\r\n this.bindCanvas( \"touchmove\", this._touchMove.bind( this ), {passive: passive}, customTarget );\r\n this.bindCanvas( \"touchcancel\", this._mouseOut.bind( this ), {}, customTarget );\r\n this._hasTouch = true;\r\n } else {\r\n this.unbindCanvas( \"touchstart\", this._touchStart.bind( this ), {passive: passive}, customTarget );\r\n this.unbindCanvas( \"touchend\", this._mouseUp.bind( this ), {}, customTarget );\r\n this.unbindCanvas( \"touchmove\", this._touchMove.bind( this ), {passive: passive}, customTarget );\r\n this.unbindCanvas( \"touchcancel\", this._mouseOut.bind( this ), {}, customTarget );\r\n this._hasTouch = false;\r\n }\r\n return this;\r\n }\r\n \r\n\r\n bindKeyboard( bind:boolean = true ):this {\r\n if ( bind ) {\r\n this._keyDownBind = this._keyDown.bind( this );\r\n this._keyUpBind = this._keyUp.bind( this );\r\n this.bindDoc( \"keydown\", this._keyDownBind, {} );\r\n this.bindDoc( \"keyup\", this._keyUpBind, {} );\r\n this._hasKeyboard = true;\r\n } else {\r\n this.unbindDoc( \"keydown\", this._keyDownBind, {} );\r\n this.unbindDoc( \"keyup\", this._keyUpBind, {} );\r\n this._hasKeyboard = false;\r\n }\r\n return this;\r\n }\r\n \r\n \r\n \r\n /**\r\n * A convenient method to convert the touch points in a touch event to an array of Pts.\r\n * @param evt a touch event which contains touches, changedTouches, and targetTouches list\r\n * @param which a string to select a touches list: \"touches\", \"changedTouches\", or \"targetTouches\". Default is \"touches\"\r\n * @return an array of Pt, whose origin position (0,0) is offset to the top-left of this space\r\n */\r\n touchesToPoints( evt:TouchEvent, which:TouchPointsKey = \"touches\" ): Pt[] {\r\n if ( !evt || !evt[which] ) return [];\r\n const ts = [];\r\n for ( let i = 0; i < evt[which].length; i++ ) {\r\n const t = evt[which].item( i );\r\n ts.push( new Pt( t.pageX - this.bound.topLeft.x, t.pageY - this.bound.topLeft.y ) );\r\n }\r\n return ts;\r\n }\r\n \r\n \r\n /**\r\n * Go through all the added [`IPlayer`](#link) objects and call its `action` callback function.\r\n * @param type an UIPointerActions constant or string: \"up\", \"down\", \"move\", \"drag\", \"drop\", \"over\", and \"out\"\r\n * @param evt mouse or touch event\r\n * @see [`Space.add`](#link)\r\n */\r\n protected _mouseAction( type:string, evt:MouseEvent | TouchEvent | PointerEvent ) {\r\n if ( !this.isPlaying ) return;\r\n\r\n let px = 0, py = 0;\r\n \r\n if ( evt instanceof MouseEvent ) {\r\n for ( const k in this.players ) {\r\n if ( this.players.hasOwnProperty( k ) ) {\r\n const v = this.players[k];\r\n px = evt.pageX - this.outerBound.x;\r\n py = evt.pageY - this.outerBound.y;\r\n if ( v.action ) v.action( type, px, py, evt );\r\n }\r\n }\r\n } else {\r\n for ( const k in this.players ) {\r\n if ( this.players.hasOwnProperty( k ) ) {\r\n const v = this.players[k];\r\n const c = evt.changedTouches && evt.changedTouches.length > 0;\r\n const touch = evt.changedTouches.item( 0 );\r\n px = ( c ) ? touch.pageX - this.outerBound.x : 0;\r\n py = ( c ) ? touch.pageY - this.outerBound.y : 0;\r\n if ( v.action ) v.action( type, px, py, evt );\r\n }\r\n }\r\n }\r\n if ( type ) {\r\n this._pointer.to( px, py );\r\n this._pointer.id = type;\r\n }\r\n }\r\n \r\n \r\n /**\r\n * MouseDown handler.\r\n * @param evt \r\n */\r\n protected _mouseDown( evt:PointerEvent ) {\r\n this._mouseAction( UIA.down, evt );\r\n this._mouseAction( UIA.pointerdown, evt );\r\n this._pressed = true;\r\n if ( evt.target instanceof Element ) {\r\n evt.target.setPointerCapture( evt.pointerId );\r\n }\r\n return false;\r\n }\r\n\r\n \r\n /**\r\n * MouseUp handler.\r\n * @param evt \r\n */\r\n protected _mouseUp( evt:PointerEvent ) {\r\n this._mouseAction( UIA.pointerup, evt );\r\n if ( this._dragged ) {\r\n this._mouseAction( UIA.drop, evt );\r\n } else {\r\n this._mouseAction( UIA.up, evt );\r\n }\r\n this._pressed = false;\r\n this._dragged = false;\r\n if ( evt.target instanceof Element ) {\r\n evt.target.releasePointerCapture( evt.pointerId );\r\n }\r\n return false;\r\n }\r\n\r\n \r\n /**\r\n * MouseMove handler.\r\n * @param evt \r\n */\r\n protected _mouseMove( evt:PointerEvent ) {\r\n if ( this._pressed ) {\r\n this._dragged = true;\r\n this._mouseAction( UIA.drag, evt );\r\n } else {\r\n this._mouseAction( UIA.move, evt );\r\n }\r\n return false;\r\n }\r\n \r\n \r\n /**\r\n * MouseOver handler.\r\n * @param evt \r\n */\r\n protected _mouseOver( evt:PointerEvent ) {\r\n this._mouseAction( UIA.over, evt );\r\n return false;\r\n }\r\n \r\n \r\n /**\r\n * MouseOut handler.\r\n * @param evt \r\n */\r\n protected _mouseOut( evt:PointerEvent ) {\r\n this._mouseAction( UIA.out, evt );\r\n if ( this._dragged ) this._mouseAction( UIA.drop, evt );\r\n this._dragged = false;\r\n return false;\r\n }\r\n\r\n\r\n /**\r\n * MouseClick handler.\r\n * @param evt \r\n */\r\n protected _mouseClick( evt:MouseEvent | TouchEvent ) {\r\n this._mouseAction( UIA.click, evt );\r\n this._pressed = false;\r\n this._dragged = false;\r\n return false;\r\n }\r\n \r\n \r\n /**\r\n * ContextMenu handler.\r\n * @param evt \r\n */\r\n protected _contextMenu( evt:MouseEvent ) {\r\n this._mouseAction( UIA.contextmenu, evt );\r\n return false;\r\n }\r\n \r\n \r\n /**\r\n * TouchMove handler.\r\n * @param evt \r\n */\r\n protected _touchMove( evt:TouchEvent ) {\r\n this._mouseAction( UIA.move, evt );\r\n if ( this._pressed ) {\r\n this._dragged = true;\r\n this._mouseAction( UIA.drag, evt );\r\n }\r\n evt.preventDefault();\r\n return false;\r\n }\r\n\r\n /**\r\n * TouchStart handler.\r\n * @param evt \r\n */\r\n protected _touchStart( evt:TouchEvent ) {\r\n this._mouseAction( UIA.down, evt );\r\n this._pressed = true;\r\n return false;\r\n evt.preventDefault();\r\n return false;\r\n }\r\n\r\n\r\n protected _keyDown( evt:KeyboardEvent ) {\r\n this._keyboardAction( UIA.keydown, evt );\r\n return false;\r\n }\r\n\r\n protected _keyUp( evt:KeyboardEvent ) {\r\n this._keyboardAction( UIA.keyup, evt );\r\n return false;\r\n }\r\n\r\n protected _keyboardAction( type:string, evt:KeyboardEvent ) {\r\n if ( !this.isPlaying ) return;\r\n for ( const k in this.players ) {\r\n if ( this.players.hasOwnProperty( k ) ) {\r\n const v = this.players[k];\r\n if ( v.action ) v.action( type, evt.shiftKey ? 1 : 0, evt.altKey ? 1 : 0, evt );\r\n }\r\n }\r\n }\r\n \r\n}\r\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport {Util, Const} from \"./Util\";\r\nimport {Geom, Num} from \"./Num\";\r\nimport {Vec, Mat} from \"./LinearAlgebra\";\r\nimport {IPt, GroupLike, PtLike, PtIterable, PtLikeIterable} from \"./Types\";\r\n\r\n/**\r\n * Pt is a subclass of standard [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array) with additional properties and functions to support vector and geometric calculations.\r\n * See [Pt guide](../guide/Pt-0200.html) for details.\r\n */\r\nexport class Pt extends Float32Array implements IPt, Iterable<number> {\r\n\r\n protected _id:string;\r\n \r\n /**\r\n * Create a Pt. If no parameter is provided, this will instantiate a Pt with 2 dimensions [0, 0]. \r\n * Note that `new Pt(3)` will only instantiate Pt with length of 3 (ie, same as `new Float32Array(3)` ). If you need a Pt with 1 dimension of value 3, use `new Pt([3])`.\r\n * @example `new Pt()`, `new Pt(1,2,3,4,5)`, `new Pt([1,2])`, `new Pt({x:0, y:1})`, `new Pt(pt)`\r\n * @param args a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\r\n */\r\n constructor( ...args: Array<number | number[] | IPt | Float32Array> ) {\r\n let params;\r\n if ( args.length === 1 && typeof args[0] == \"number\" ) {\r\n params = args[0]; // init with the TypedArray's length. Needed this in order to make \".map\", \".slice\" etc work.\r\n } else {\r\n params = ( args.length > 0 ) ? Util.getArgs( args ) : [0,0];\r\n } \r\n super( params );\r\n }\r\n\r\n\r\n /**\r\n * Create an n-dimensional Pt with either default value or random values.\r\n * @param dimensions number of dimensions\r\n * @param defaultValue optional default value to fill the dimensions\r\n * @param randomize if `true`, randomize the value between 0 to default value\r\n */\r\n static make( dimensions:number, defaultValue:number = 0, randomize:boolean = false ):Pt {\r\n const p = new Float32Array( dimensions );\r\n if ( defaultValue ) p.fill( defaultValue );\r\n if ( randomize ) {\r\n for ( let i = 0, len = p.length; i < len; i++ ) {\r\n p[i] = p[i] * Num.random();\r\n }\r\n }\r\n return new Pt( p );\r\n }\r\n\r\n /**\r\n * ID string of this Pt\r\n */\r\n get id():string { return this._id; }\r\n set id( s:string ) { this._id = s; }\r\n\r\n /**\r\n * Value in the first dimensional of this Pt\r\n */\r\n get x():number { return this[0]; }\r\n set x( n:number ) { this[0] = n; }\r\n\r\n /**\r\n * Value in the second dimension of this Pt\r\n */\r\n get y():number { return this[1]; }\r\n set y( n:number ) { this[1] = n; }\r\n\r\n /**\r\n * Value in the third dimension of this Pt\r\n */\r\n get z():number { return this[2]; }\r\n set z( n:number ) { this[2] = n; }\r\n\r\n /**\r\n * Value in the forth dimension of this Pt\r\n */\r\n get w():number { return this[3]; } \r\n set w( n:number ) { this[3] = n; }\r\n \r\n\r\n /**\r\n * Clone this Pt and return it as a new Pt.\r\n */\r\n clone():Pt {\r\n return new Pt( this );\r\n }\r\n\r\n\r\n /**\r\n * Check if another Pt is equal to this Pt, within a threshold.\r\n * @param p another Pt to compare with\r\n * @param threshold a threshold value within which the two Pts are considered equal. Default is 0.000001.\r\n */\r\n equals( p:PtLike, threshold = 0.000001 ):boolean {\r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n if ( Math.abs( this[i] - p[i] ) > threshold ) return false;\r\n }\r\n return true;\r\n }\r\n\r\n\r\n /**\r\n * Update the values of this Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n to( ...args ):this {\r\n const p = Util.getArgs( args );\r\n for ( let i = 0, len = Math.min( this.length, p.length ); i < len; i++ ) {\r\n this[i] = p[i];\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Like [`Pt.to`](#link) but returns a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $to( ...args ):Pt {\r\n return this.clone().to( ...args );\r\n }\r\n\r\n\r\n /**\r\n * Update the values of this Pt to point at a specific angle.\r\n * @param radian target angle in radian\r\n * @param magnitude Optional magnitude if known. If not provided, it'll calculate and use this Pt's magnitude.\r\n * @param anchorFromPt If `true`, add it from this Pt's current position. Default is `false` which update the position from origin (0,0). See also [`Geom.rotate2D`](#link) for rotating a point from another anchor point.\r\n */\r\n toAngle( radian:number, magnitude?:number, anchorFromPt:boolean = false ):this {\r\n const m = ( magnitude != undefined ) ? magnitude : this.magnitude();\r\n const change = [Math.cos( radian ) * m, Math.sin( radian ) * m];\r\n return ( anchorFromPt ) ? this.add( change ) : this.to( change );\r\n }\r\n\r\n\r\n /**\r\n * Create an operation using this Pt, passing this Pt into a custom function's first parameter. See the [Op guide](../guide/Op-0400.html) for details.\r\n * @param fn any function that takes a Pt as its first parameter\r\n * @example `let myOp = pt.op( fn ); let result = myOp( [1,2,3] );`\r\n * @returns a resulting function that takes other parameters required in `fn`\r\n */\r\n op( fn:( p1:PtLike, ...rest:any[] ) => any ): ( ...rest:any[] ) => any {\r\n const self = this;\r\n return ( ...params:any[] ) => {\r\n return fn( self, ...params );\r\n };\r\n }\r\n\r\n\r\n /**\r\n * This combines a series of operations into an array. See the [Op guide](../guide/Op-0400.html) for details.\r\n * @param fns an array of functions for `op`\r\n * @example `let myOps = pt.ops([fn1, fn2, fn3]); let results = myOps.map( (op) => op([1,2,3]) );`\r\n * @returns an array of resulting functions\r\n */\r\n ops( fns:( ( p1:PtLike, ...rest:any[] ) => any )[] ): ( ( ...rest:any[] ) => any )[] {\r\n const _ops = [];\r\n for ( let i = 0, len = fns.length; i < len; i++ ) {\r\n _ops.push( this.op( fns[i] ) );\r\n }\r\n return _ops;\r\n }\r\n\r\n\r\n /**\r\n * Take specific dimensional values from this Pt and create a new Pt.\r\n * @param axis a string such as \"xy\" (use Const.xy) or an array to specify indices\r\n */\r\n $take( axis:string | number[] ):Pt {\r\n const p = [];\r\n for ( let i = 0, len = axis.length; i < len; i++ ) {\r\n p.push( this[axis[i]] || 0 );\r\n }\r\n return new Pt( p );\r\n }\r\n\r\n\r\n /**\r\n * Concatenate this Pt with addition dimensional values and return as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $concat( ...args ):Pt {\r\n return new Pt( this.toArray().concat( Util.getArgs( args ) ) );\r\n }\r\n\r\n\r\n /**\r\n * Add scalar or vector values to this Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n add( ...args ): this { \r\n ( args.length === 1 && typeof args[0] == \"number\" ) ? Vec.add( this, args[0] ) : Vec.add( this, Util.getArgs( args ) );\r\n return this; \r\n }\r\n\r\n\r\n /**\r\n * Like [`Pt.add`](#link), but returns result as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $add( ...args ): Pt { return this.clone().add( ...args ); }\r\n\r\n\r\n /**\r\n * Subtract scalar or vector values from this Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n subtract( ...args ): this { \r\n ( args.length === 1 && typeof args[0] == \"number\" ) ? Vec.subtract( this, args[0] ) : Vec.subtract( this, Util.getArgs( args ) );\r\n return this; \r\n }\r\n\r\n\r\n /**\r\n * Like [`Pt.subtract`](#link), but returns result as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $subtract( ...args ): Pt { return this.clone().subtract( ...args ); }\r\n\r\n\r\n /**\r\n * Multiply scalar or vector values (as element-wise) with this Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n multiply( ...args ): this { \r\n ( args.length === 1 && typeof args[0] == \"number\" ) ? Vec.multiply( this, args[0] ) : Vec.multiply( this, Util.getArgs( args ) );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Like [`Pt.multiply`](#link), but returns result as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $multiply( ...args ): Pt { return this.clone().multiply( ...args ); }\r\n\r\n\r\n /**\r\n * Divide this Pt over scalar or vector values (as element-wise).\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n divide( ...args ): this { \r\n ( args.length === 1 && typeof args[0] == \"number\" ) ? Vec.divide( this, args[0] ) : Vec.divide( this, Util.getArgs( args ) );\r\n return this; \r\n }\r\n\r\n\r\n /**\r\n * Like [`Pt.divide`](#link), but returns result as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $divide( ...args ): Pt { return this.clone().divide( ...args ); }\r\n\r\n\r\n /**\r\n * Get the squared distance (magnitude) of this Pt from origin.\r\n */\r\n magnitudeSq():number { return Vec.dot( this, this ); }\r\n\r\n\r\n /**\r\n * Get the distance (magnitude) of this Pt from origin.\r\n */\r\n magnitude():number { return Vec.magnitude( this ); }\r\n\r\n\r\n /**\r\n * Convert to a unit vector, which is a normalized vector whose magnitude equals to 1.\r\n * @param magnitude Optional: if the magnitude is known, pass it as a parameter to avoid duplicate calculation.\r\n */\r\n unit( magnitude:number = undefined ):Pt {\r\n Vec.unit( this, magnitude );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get a new unit vector from this Pt.\r\n */\r\n $unit( magnitude:number = undefined ):Pt { return this.clone().unit( magnitude ); }\r\n\r\n\r\n /**\r\n * Dot product of this Pt and another Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n dot( ...args ):number { return Vec.dot( this, Util.getArgs( args ) ); }\r\n\r\n\r\n /**\r\n * 2D Cross product of this Pt and another Pt. Return results as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $cross2D( ...args ):number { return Vec.cross2D( this, Util.getArgs( args ) ); }\r\n\r\n \r\n /**\r\n * 3D Cross product of this Pt and another Pt. Return results as a new Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $cross( ...args ): Pt { return Vec.cross( this, Util.getArgs( args ) ); }\r\n\r\n\r\n /**\r\n * Calculate vector projection of this Pt on another Pt. \r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n * @returns the projection vector as a Pt\r\n */\r\n $project( ...args ):Pt {\r\n return this.$multiply( this.dot( ...args ) / this.magnitudeSq() );\r\n }\r\n\r\n\r\n /**\r\n * Calculate scalar projection.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n projectScalar( ...args ):number {\r\n return this.dot( ...args ) / this.magnitude();\r\n }\r\n\r\n\r\n /**\r\n * Absolute values for all values in this pt.\r\n */\r\n abs():Pt {\r\n Vec.abs( this );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt with absolute values of this Pt.\r\n */\r\n $abs():Pt {\r\n return this.clone().abs();\r\n }\r\n\r\n\r\n /**\r\n * Floor values for all values in this Pt.\r\n */\r\n floor():Pt {\r\n Vec.floor( this );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt with floor values of this Pt.\r\n */\r\n $floor():Pt {\r\n return this.clone().floor();\r\n }\r\n\r\n\r\n /**\r\n * Ceiling values for all values in this Pt.\r\n */\r\n ceil():Pt {\r\n Vec.ceil( this );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt with ceiling values of this Pt.\r\n */\r\n $ceil():Pt {\r\n return this.clone().ceil();\r\n }\r\n\r\n\r\n /**\r\n * Rounded values for all values in this Pt.\r\n */\r\n round():Pt {\r\n Vec.round( this );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt with rounded values of this Pt.\r\n */\r\n $round():Pt {\r\n return this.clone().round();\r\n }\r\n\r\n\r\n /**\r\n * Find the minimum value across all dimensions in this Pt.\r\n * @returns an object with `value` and `index` which returns the minimum value and its dimensional index\r\n */\r\n minValue():{value:number, index:number} {\r\n return Vec.min( this );\r\n }\r\n\r\n\r\n /**\r\n * Find the maximum value across all dimensions in this Pt.\r\n * @returns an object with `value` and `index` which returns the maximum value and its dimensional index\r\n */\r\n maxValue():{value:number, index:number} {\r\n return Vec.max( this );\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt that has the minimum dimensional values of this Pt and another Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $min( ...args ):Pt {\r\n const p = Util.getArgs( args );\r\n const m = this.clone();\r\n for ( let i = 0, len = Math.min( this.length, p.length ); i < len; i++ ) {\r\n m[i] = Math.min( this[i], p[i] );\r\n }\r\n return m;\r\n }\r\n\r\n\r\n /**\r\n * Get a new Pt that has the maximum dimensional values of this Pt and another Pt.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n $max( ...args ):Pt {\r\n const p = Util.getArgs( args );\r\n const m = this.clone();\r\n for ( let i = 0, len = Math.min( this.length, p.length ); i < len; i++ ) {\r\n m[i] = Math.max( this[i], p[i] );\r\n }\r\n return m;\r\n }\r\n \r\n\r\n /**\r\n * Get angle of this Pt from origin.\r\n * @param axis a string such as \"xy\" (use Const.xy) or an array to specify index for two dimensions\r\n */\r\n angle( axis:string | number[] = Const.xy ):number {\r\n return Math.atan2( this[axis[1]], this[axis[0]] );\r\n }\r\n\r\n\r\n /**\r\n * Get the angle between this and another Pt.\r\n * @param p the other Pt\r\n * @param axis a string such as \"xy\" (use Const.xy) or an array to specify index for two dimensions\r\n */\r\n angleBetween( p:Pt, axis:string | number[] = Const.xy ):number {\r\n return Geom.boundRadian( this.angle( axis ) ) - Geom.boundRadian( p.angle( axis ) );\r\n }\r\n\r\n\r\n /**\r\n * Scale this Pt from origin or from an anchor point.\r\n * @param scale scale ratio\r\n * @param anchor optional anchor point to scale from\r\n */\r\n scale( scale:number | number[] | PtLike, anchor?:PtLike ) { \r\n Geom.scale( this, scale, anchor || Pt.make( this.length, 0 ) );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Rotate this Pt from origin or from an anchor point in 2D.\r\n * @param angle rotate angle\r\n * @param anchor optional anchor point to scale from\r\n * @param axis optional string such as \"yz\" to specify a 2D plane\r\n */\r\n rotate2D( angle:number, anchor?:PtLike, axis?:string ) { \r\n Geom.rotate2D( this, angle, anchor || Pt.make( this.length, 0 ), axis );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Shear this Pt from origin or from an anchor point in 2D.\r\n * @param shear shearing value which can be a number or an array of 2 numbers\r\n * @param anchor optional anchor point to scale from\r\n * @param axis optional string such as \"yz\" to specify a 2D plane\r\n */\r\n shear2D( scale:number | number[] | PtLike, anchor?:PtLike, axis?:string ) {\r\n Geom.shear2D( this, scale, anchor || Pt.make( this.length, 0 ), axis );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Reflect this Pt along a 2D line.\r\n * @param line a Group of 2 Pts that defines a line for reflection\r\n * @param axis optional axis such as \"yz\" to define a 2D plane of reflection\r\n */\r\n reflect2D( line:GroupLike, axis?:string ):this {\r\n Geom.reflect2D( this, line, axis );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * A string representation of this Pt. Eg, \"Pt(1, 2, 3)\".\r\n */\r\n toString():string {\r\n return `Pt(${ this.join( \", \" )})`;\r\n }\r\n\r\n\r\n /**\r\n * Convert this Pt to a javascript Array.\r\n */\r\n toArray():number[] {\r\n return [].slice.call( this );\r\n }\r\n\r\n\r\n /**\r\n * Convert this Pt to a Group as new Group([0,...], pt)\r\n */\r\n toGroup():Group {\r\n return new Group( Pt.make( this.length ), this.clone() );\r\n }\r\n\r\n\r\n /**\r\n * Convert this Pt to a Bound as new Group([0,...], pt)\r\n */\r\n toBound():Bound {\r\n return new Bound( Pt.make( this.length ), this.clone() );\r\n }\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n * A Group is a subclass of standard javascript [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). It should only contain Pt instances. You can think of it as an array of Float32Arrays.\r\n * See [Group guide](../guide/Group-0300.html) for details.\r\n */\r\nexport class Group extends Array<Pt> {\r\n\r\n protected _id:string;\r\n \r\n /**\r\n * Create a Group by passing an array of [`Pt`](#link). You may also create a Group using [`Group.fromArray`](#link) or [`Group.fromPtArray`](#link).\r\n * @param args an array of Pts\r\n */\r\n constructor( ...args:Pt[] ) {\r\n super( ...args );\r\n }\r\n\r\n /**\r\n * ID string of this Group\r\n */\r\n get id():string { return this._id; }\r\n set id( s:string ) { this._id = s; }\r\n\r\n /** \r\n * The first Pt in this Group \r\n */\r\n get p1():Pt { return this[0]; }\r\n\r\n /** \r\n * The second Pt in this Group \r\n */\r\n get p2():Pt { return this[1]; }\r\n\r\n /** \r\n * The third Pt in this Group \r\n */\r\n get p3():Pt { return this[2]; }\r\n\r\n /** \r\n * The forth Pt in this Group \r\n */\r\n get p4():Pt { return this[3]; }\r\n\r\n /** \r\n * The last Pt in this Group \r\n */\r\n get q1():Pt { return this[this.length - 1]; }\r\n\r\n /** \r\n * The second-last Pt in this Group \r\n */\r\n get q2():Pt { return this[this.length - 2]; }\r\n\r\n /** \r\n * The third-last Pt in this Group \r\n */\r\n get q3():Pt { return this[this.length - 3]; }\r\n\r\n /** \r\n * The forth-last Pt in this Group \r\n */\r\n get q4():Pt { return this[this.length - 4]; }\r\n\r\n \r\n\r\n /**\r\n * Depp clone this group and its Pts.\r\n */\r\n clone():Group {\r\n const group = new Group(); \r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n group.push( this[i].clone() );\r\n }\r\n return group;\r\n }\r\n\r\n\r\n /**\r\n * Convert an array of numeric arrays into a Group.\r\n * @param list an Iterable<PtLike> such as an array or a generator (of PtLike numeric arrays)\r\n * @example `Group.fromArray( [[1,2], [3,4], [5,6]] )`\r\n */\r\n static fromArray( list:PtLikeIterable ):Group {\r\n const g = new Group();\r\n for ( const li of list ) {\r\n const p = ( li instanceof Pt ) ? li as Pt : new Pt( li );\r\n g.push( p );\r\n }\r\n return g;\r\n }\r\n\r\n\r\n /**\r\n * Convert an Array/Iterable of Pt into a Group.\r\n * @param list an Iterable<Pt>\r\n */\r\n static fromPtArray( list:PtIterable ):Group {\r\n return Group.from( list ) as Group;\r\n }\r\n\r\n\r\n /**\r\n * Split this Group into an array of sub-groups.\r\n * @param chunkSize number of items per sub-group\r\n * @param stride forward-steps after each sub-group\r\n * @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed\r\n */\r\n split( chunkSize:number, stride?:number, loopBack:boolean = false ):Group[] {\r\n const sp = Util.split( this, chunkSize, stride, loopBack );\r\n return sp as Group[];\r\n }\r\n\r\n\r\n /**\r\n * Insert more Pt into this group.\r\n * @param pts a Group or an Iterable<Pt>\r\n * @param index the index position to insert into\r\n */\r\n insert( pts:PtIterable, index = 0 ):this {\r\n Group.prototype.splice.apply( this, [index, 0, ...pts] );\r\n return this;\r\n }\r\n \r\n\r\n /**\r\n * Like Array's splice function, with support for negative index and a friendlier name.\r\n * @param index start index, which can be negative (where -1 is at index 0, -2 at index 1, etc)\r\n * @param count number of items to remove\r\n * @returns The items that are removed. \r\n */\r\n remove( index = 0, count:number = 1 ):Group {\r\n const param = ( index < 0 ) ? [index * -1 - 1, count] : [index, count];\r\n return Group.prototype.splice.apply( this, param );\r\n }\r\n\r\n\r\n /**\r\n * Split this group into an array of sub-group segments.\r\n * @param pts_per_segment number of Pts in each segment\r\n * @param stride forward-step to take\r\n * @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed\r\n */\r\n segments( pts_per_segment:number = 2, stride:number = 1, loopBack:boolean = false ):Group[] { \r\n return this.split( pts_per_segment, stride, loopBack ); \r\n }\r\n\r\n\r\n /**\r\n * Get all the line segments (ie, edges in a graph) of this group.\r\n */\r\n lines():Group[] { return this.segments( 2, 1 ); }\r\n\r\n\r\n /**\r\n * Find the centroid of this group's Pts, which is the average middle point.\r\n */\r\n centroid(): Pt {\r\n return Geom.centroid( this );\r\n }\r\n\r\n \r\n /**\r\n * Find the rectangular bounding box of this group's Pts.\r\n * @returns a Group of 2 Pts representing the top-left and bottom-right of the rectangle\r\n */\r\n boundingBox():Group {\r\n return Geom.boundingBox( this );\r\n }\r\n\r\n\r\n /**\r\n * Anchor all the Pts in this Group using a target Pt as origin. (ie, subtract all Pt with the target anchor to get a relative position). All the Pts' values will be updated.\r\n * @param ptOrIndex a Pt, or a numeric index to target a specific Pt in this Group\r\n */\r\n anchorTo( ptOrIndex:PtLike | number = 0 ) { Geom.anchor( this, ptOrIndex, \"to\" ); }\r\n\r\n\r\n /**\r\n * Anchor all the Pts in this Group by its absolute position from a target Pt. (ie, add all Pt with the target anchor to get an absolute position). All the Pts' values will be updated.\r\n * @param ptOrIndex a Pt, or a numeric index to target a specific Pt in this Group\r\n */\r\n anchorFrom( ptOrIndex:PtLike | number = 0 ) { Geom.anchor( this, ptOrIndex, \"from\" ); }\r\n\r\n\r\n /**\r\n * Create an operation using this Group, passing this Group into a custom function's first parameter. See the [Op guide](../guide/Op-0400.html) for details.\r\n * @param fn any function that takes a Group as its first parameter\r\n * @example `let myOp = group.op( fn ); let result = myOp( [1,2,3] );`\r\n * @returns a resulting function that takes other parameters required in `fn`\r\n */\r\n op( fn:( g1:PtIterable, ...rest:any[] ) => any ): ( ...rest:any[] ) => any {\r\n const self = this;\r\n return ( ...params:any[] ) => {\r\n return fn( self, ...params );\r\n };\r\n }\r\n\r\n\r\n /**\r\n * This combines a series of operations into an array. See the [Op guide](../guide/Op-0400.html) for details.\r\n * @param fns an array of functions for `op`\r\n * @example `let myOps = pt.ops([fn1, fn2, fn3]); let results = myOps.map( (op) => op([1,2,3]) );`\r\n * @returns an array of resulting functions\r\n */\r\n ops( fns:( ( g1:PtIterable, ...rest:any[] ) => any )[] ): ( ( ...rest:any[] ) => any )[] {\r\n const _ops = [];\r\n for ( let i = 0, len = fns.length; i < len; i++ ) {\r\n _ops.push( this.op( fns[i] ) );\r\n }\r\n return _ops;\r\n }\r\n\r\n\r\n /**\r\n * Get an interpolated point on the line segments defined by this Group.\r\n * @param t a value between 0 to 1 usually\r\n */\r\n interpolate( t:number ):Pt {\r\n t = Num.clamp( t, 0, 1 );\r\n const chunk = this.length - 1;\r\n const tc = 1 / ( this.length - 1 );\r\n const idx = Math.floor( t / tc );\r\n return Geom.interpolate( this[idx], this[ Math.min( this.length - 1, idx + 1 )], ( t - idx * tc ) * chunk );\r\n }\r\n\r\n\r\n /**\r\n * Move every Pt's position by a specific amount. Same as [`Group.add`](#link).\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n moveBy( ...args ):this {\r\n return this.add( ...args );\r\n }\r\n\r\n\r\n /**\r\n * Move the first Pt in this group to a specific position, and move all the other Pts correspondingly.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n moveTo( ...args ):this {\r\n const d = new Pt( Util.getArgs( args ) ).subtract( this[0] );\r\n this.moveBy( d );\r\n return this; \r\n }\r\n\r\n\r\n /**\r\n * Scale this group's Pts from an anchor point. Default anchor point is the first Pt in this group.\r\n * @param scale scale ratio\r\n * @param anchor optional anchor point to scale from\r\n */\r\n scale( scale:number | number[] | PtLike, anchor?:PtLike ):this { \r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n Geom.scale( this[i], scale, anchor || this[0] );\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Rotate this group's Pt from an anchor point in 2D. Default anchor point is the first Pt in this group.\r\n * @param angle rotate angle\r\n * @param anchor optional anchor point to scale from\r\n * @param axis optional string such as \"yz\" to specify a 2D plane\r\n */\r\n rotate2D( angle:number, anchor?:PtLike, axis?:string ):this { \r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n Geom.rotate2D( this[i], angle, anchor || this[0], axis );\r\n } \r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Shear this group's Pt from an anchor point in 2D. Default anchor point is the first Pt in this group.\r\n * @param shear shearing value which can be a number or an array of 2 numbers\r\n * @param anchor optional anchor point to scale from\r\n * @param axis optional string such as \"yz\" to specify a 2D plane\r\n */\r\n shear2D( scale:number | number[] | PtLike, anchor?:PtLike, axis?:string ):this {\r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n Geom.shear2D( this[i], scale, anchor || this[0], axis );\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Reflect this group's Pts along a 2D line. Default anchor point is the first Pt in this group.\r\n * @param line a Group or an Iterable<PtLike> with 2 Pt that defines a line for reflection\r\n * @param axis optional axis such as \"yz\" to define a 2D plane of reflection\r\n */\r\n reflect2D( line:PtLikeIterable, axis?:string ):this {\r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n Geom.reflect2D( this[i], line, axis );\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Sort this group's Pts by values in a specific dimension.\r\n * @param dim dimensional index\r\n * @param desc if true, sort descending. Default is false (ascending)\r\n */\r\n sortByDimension( dim:number, desc:boolean = false ):this {\r\n return this.sort( ( a, b ) => ( desc ) ? b[dim] - a[dim] : a[dim] - b[dim] );\r\n }\r\n\r\n\r\n /**\r\n * Update each Pt in this Group with an existing Pt function.\r\n * @param ptFn string name of an existing Pt function. Note that the function must return Pt.\r\n * @param args arguments for the function specified in ptFn\r\n */\r\n forEachPt( ptFn:string, ...args ):this {\r\n if ( !this[0][ptFn] ) {\r\n Util.warn( `${ptFn} is not a function of Pt` );\r\n return this;\r\n }\r\n for ( let i = 0, len = this.length; i < len; i++ ) {\r\n this[i] = this[i][ptFn]( ...args );\r\n }\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Add scalar or vector values to this group's Pts.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n add( ...args ):this {\r\n return this.forEachPt( \"add\", ...args );\r\n }\r\n\r\n\r\n /**\r\n * Subtract scalar or vector values from this group's Pts.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n subtract( ...args ):this {\r\n return this.forEachPt( \"subtract\", ...args );\r\n }\r\n\r\n\r\n /**\r\n * Multiply scalar or vector values (as element-wise) with this group's Pts.\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n multiply( ...args ):this {\r\n return this.forEachPt( \"multiply\", ...args );\r\n }\r\n \r\n\r\n /**\r\n * Divide this group's Pts over scalar or vector values (as element-wise).\r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n divide( ...args ):this {\r\n return this.forEachPt( \"divide\", ...args );\r\n }\r\n\r\n\r\n /**\r\n * Apply this group as a matrix and calculate matrix addition.\r\n * @param g a scalar number, an array of numeric arrays, or a group of Pt\r\n * @returns a new Group\r\n */\r\n $matrixAdd( g:GroupLike | number[][] | number ):Group {\r\n return Mat.add( this, g );\r\n }\r\n\r\n\r\n /**\r\n * Apply this group as a matrix and calculate matrix multiplication.\r\n * @param g a scalar number, an array of numeric arrays, or a Group of K Pts, each with N dimensions (K-rows, N-columns) -- or if transposed is true, then N Pts with K dimensions\r\n * @param transposed (Only applicable if it's not elementwise multiplication) If true, then a and b's columns should match (ie, each Pt should have the same dimensions). Default is `false`.\r\n * @param elementwise if true, then the multiplication is done element-wise. Default is `false`.\r\n * @returns If not elementwise, this will return a new Group with M Pt, each with N dimensions (M-rows, N-columns).\r\n */\r\n $matrixMultiply( g:GroupLike | number, transposed:boolean = false, elementwise:boolean = false ):Group {\r\n return Mat.multiply( this, g, transposed , elementwise );\r\n }\r\n\r\n\r\n /**\r\n * Zip one slice of an array of Pt. Imagine the Pts are organized in rows, then this function will take the values in a specific column.\r\n * @param idx index to zip at\r\n * @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.\r\n */\r\n zipSlice( index:number, defaultValue:number | boolean = false ):Pt {\r\n return Mat.zipSlice( this, index, defaultValue );\r\n }\r\n\r\n\r\n /**\r\n * Zip a group of Pt. eg, [[1,2],[3,4],[5,6]] => [[1,3,5],[2,4,6]].\r\n * @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.\r\n * @param useLongest If true, find the longest list of values in a Pt and use its length for zipping. Default is false, which uses the first item's length for zipping.\r\n */\r\n $zip( defaultValue:number | boolean = undefined, useLongest = false ):Group {\r\n return Mat.zip( this, defaultValue, useLongest );\r\n }\r\n\r\n\r\n /**\r\n * Get a Bound instance of this group\r\n */\r\n toBound():Group {\r\n return Bound.fromGroup( this );\r\n }\r\n\r\n\r\n /**\r\n * Get a string representation of this group.\r\n */\r\n toString():string {\r\n return \"Group[ \" + this.reduce( ( p, c ) => p + c.toString() + \" \", \"\" ) + \" ]\";\r\n }\r\n\r\n\r\n}\r\n\r\n\r\n\r\n/**\r\n * Bound is a subclass of [`Group`](#link) that represents a rectangular boundary. \r\n * It includes some convenient accessors (eg, bottomRight, center) for bounding box calculations. \r\n */\r\nexport class Bound extends Group implements IPt {\r\n\r\n protected _center:Pt = new Pt();\r\n protected _size:Pt = new Pt();\r\n protected _topLeft:Pt = new Pt();\r\n protected _bottomRight:Pt = new Pt();\r\n protected _inited = false;\r\n\r\n \r\n /**\r\n * Create a Bound. This is similar to the Group constructor. You can also create a Bound via the static function [`Bound.fromGroup`](#link), or alternatively via the [Group.toBound](#link) function.\r\n * @param args a list of Pt as parameters\r\n * @see Bound.fromGroup\r\n */\r\n constructor( ...args:Pt[] ) {\r\n super( ...args );\r\n this.init();\r\n }\r\n\r\n\r\n /**\r\n * Create a Bound from a [`ClientRect`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) object.\r\n * @param rect an object that has {top, left, bottom, right, width, height} properties\r\n * @returns a Bound object\r\n */\r\n static fromBoundingRect( rect:ClientRect ):Bound {\r\n const b = new Bound( new Pt( rect.left||0, rect.top||0 ), new Pt( rect.right||0, rect.bottom||0 ) );\r\n if ( rect.width && rect.height ) b.size = new Pt( rect.width, rect.height );\r\n return b;\r\n }\r\n\r\n\r\n /**\r\n * Create a Bound from a Group or an array of Pts\r\n * @param g a Group or an Iterable<PtLike>\r\n */\r\n static fromGroup( g:PtLikeIterable ):Bound {\r\n const _g = Util.iterToArray( g );\r\n if ( _g.length < 2 ) throw new Error( \"Cannot create a Bound from a group that has less than 2 Pt\" );\r\n return new Bound( _g[0], _g[_g.length - 1] );\r\n }\r\n\r\n\r\n /**\r\n * Initiate the bound's properties.\r\n */\r\n protected init() {\r\n if ( this.p1 ) {\r\n this._size = this.p1.clone();\r\n this._inited = true;\r\n } \r\n if ( this.p1 && this.p2 ) {\r\n const a = this.p1;\r\n const b = this.p2;\r\n this.topLeft = a.$min( b );\r\n this._bottomRight = a.$max( b );\r\n this._updateSize();\r\n this._inited = true;\r\n }\r\n }\r\n\r\n\r\n /**\r\n * Clone this bound and return a new one.\r\n */\r\n clone():Bound {\r\n return new Bound( this._topLeft.clone(), this._bottomRight.clone() );\r\n }\r\n\r\n \r\n /**\r\n * Recalculte size and center.\r\n */\r\n protected _updateSize() {\r\n this._size = this._bottomRight.$subtract( this._topLeft ).abs();\r\n this._updateCenter();\r\n }\r\n\r\n\r\n /**\r\n * Recalculate center.\r\n */\r\n protected _updateCenter() {\r\n this._center = this._size.$multiply( 0.5 ).add( this._topLeft );\r\n }\r\n\r\n\r\n /**\r\n * Recalculate based on top-left position and size.\r\n */\r\n protected _updatePosFromTop() {\r\n this._bottomRight = this._topLeft.$add( this._size );\r\n this._updateCenter();\r\n }\r\n\r\n\r\n /**\r\n * Recalculate based on bottom-right position and size.\r\n */\r\n protected _updatePosFromBottom() {\r\n this._topLeft = this._bottomRight.$subtract( this._size );\r\n this._updateCenter();\r\n }\r\n\r\n\r\n /**\r\n * Recalculate based on center position and size.\r\n */\r\n protected _updatePosFromCenter() {\r\n const half = this._size.$multiply( 0.5 );\r\n this._topLeft = this._center.$subtract( half );\r\n this._bottomRight = this._center.$add( half );\r\n }\r\n\r\n\r\n /**\r\n * Size of this Bound\r\n */\r\n get size():Pt { return new Pt( this._size ); }\r\n set size( p: Pt ) { \r\n this._size = new Pt( p ); \r\n this._updatePosFromTop();\r\n }\r\n \r\n\r\n /**\r\n * Center position of this Bound\r\n */\r\n get center():Pt { return new Pt( this._center ); }\r\n set center( p:Pt ) {\r\n this._center = new Pt( p );\r\n this._updatePosFromCenter();\r\n }\r\n\r\n\r\n /**\r\n * Top-left position of this Bound\r\n */\r\n get topLeft():Pt { return new Pt( this._topLeft ); }\r\n set topLeft( p:Pt ) {\r\n this._topLeft = new Pt( p );\r\n this[0] = this._topLeft;\r\n this._updateSize();\r\n }\r\n\r\n\r\n /**\r\n * Bottom-right position of this Bound\r\n */\r\n get bottomRight():Pt { return new Pt( this._bottomRight ); }\r\n set bottomRight( p:Pt ) {\r\n this._bottomRight = new Pt( p );\r\n this[1] = this._bottomRight;\r\n this._updateSize();\r\n }\r\n\r\n\r\n /**\r\n * Width of this Bound\r\n */\r\n get width():number { return ( this._size.length > 0 ) ? this._size.x : 0; }\r\n set width( w:number ) {\r\n this._size.x = w;\r\n this._updatePosFromTop();\r\n }\r\n\r\n\r\n /**\r\n * Height of this Bound\r\n */\r\n get height():number { return ( this._size.length > 1 ) ? this._size.y : 0; }\r\n set height( h:number ) {\r\n this._size.y = h;\r\n this._updatePosFromTop();\r\n }\r\n\r\n\r\n /**\r\n * Depth of this Bound\r\n */\r\n get depth():number { return ( this._size.length > 2 ) ? this._size.z : 0; }\r\n set depth( d:number ) {\r\n this._size.z = d;\r\n this._updatePosFromTop();\r\n }\r\n \r\n\r\n /**\r\n * First value of the Bound's top-left position\r\n */\r\n get x():number { return this.topLeft.x; }\r\n\r\n\r\n /**\r\n * Second value of the Bound's top-left position\r\n */\r\n get y():number { return this.topLeft.y; }\r\n\r\n\r\n /**\r\n * Third value of the Bound's top-left position\r\n */\r\n get z():number { return this.topLeft.z; }\r\n\r\n\r\n /**\r\n * Whether this Bound has been initiated\r\n */\r\n get inited():boolean { return this._inited; }\r\n\r\n\r\n\r\n /**\r\n * If the Bound's Pts are changed, call this function to update the Bound's properties.\r\n * It's simpler and preferable to change the Bound's properties (eg, topLeft, bottomRight) instead of updating the Bound's Pts.\r\n */\r\n update() {\r\n this._topLeft = this[0];\r\n this._bottomRight = this[1];\r\n this._updateSize();\r\n return this;\r\n }\r\n\r\n\r\n}\r\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport { CanvasSpace } from \"./Canvas\";\r\nimport { Num } from \"./Num\";\r\nimport {Group, Pt} from \"./Pt\";\r\nimport {WarningType, PtLikeIterable} from \"./Types\";\r\n\r\n\r\n/**\r\n * Various constant values for enumerations and calculations.\r\n */\r\nexport const Const = {\r\n\r\n /** A string to indicate xy plane. */\r\n xy: \"xy\",\r\n\r\n /** A string to indicate yz plane. */\r\n yz: \"yz\",\r\n\r\n /** A string to indicate xz plane. */\r\n xz: \"xz\",\r\n\r\n /** A string to indicate xyz space. */\r\n xyz: \"xyz\",\r\n\r\n /** Represents horizontal direction. */\r\n horizontal: 0,\r\n\r\n /** Represents vertical direction. */\r\n vertical: 1,\r\n\r\n /** Represents identical point or value */\r\n identical: 0,\r\n\r\n /** Represents right position or direction */\r\n right: 4,\r\n\r\n /** Represents bottom right position or direction */\r\n bottom_right: 5,\r\n\r\n /** Represents bottom position or direction */\r\n bottom: 6,\r\n\r\n /** Represents bottom left position or direction */\r\n bottom_left: 7,\r\n\r\n /** Represents left position or direction */\r\n left: 8,\r\n\r\n /** Represents top left position or direction */\r\n top_left: 1,\r\n\r\n /** Represents top position or direction */\r\n top: 2,\r\n\r\n /** Represents top right position or direction */\r\n top_right: 3,\r\n\r\n /** Represents an arbitrary very small number. It is set as 0.0001 here. */\r\n epsilon : 0.0001,\r\n\r\n /** Represents Number.MAX_VALUE */\r\n max: Number.MAX_VALUE,\r\n\r\n /** Represents Number.MIN_VALUE */\r\n min: Number.MIN_VALUE,\r\n\r\n /** π radian (180 deg) */\r\n pi: Math.PI,\r\n\r\n /** Two π radian (360deg) */\r\n two_pi : 6.283185307179586,\r\n\r\n /** Half π radian (90deg) */\r\n half_pi : 1.5707963267948966,\r\n\r\n /** π/4 radian (45deg) */\r\n quarter_pi : 0.7853981633974483,\r\n\r\n /** π/180 or 1 degree in radian */\r\n one_degree: 0.017453292519943295,\r\n\r\n /** Multiply this constant with a radian to get a degree */\r\n rad_to_deg: 57.29577951308232,\r\n\r\n /** Multiply this constant with a degree to get a radian */\r\n deg_to_rad: 0.017453292519943295,\r\n\r\n /** Gravity acceleration (unit: m/s^2) and gravity force (unit: Newton) on 1kg of mass. */\r\n gravity: 9.81,\r\n\r\n /** 1 Newton: 0.10197 Kilogram-force */\r\n newton: 0.10197,\r\n\r\n /** Gaussian constant (1 / Math.sqrt(2 * Math.PI)) */\r\n gaussian: 0.3989422804014327\r\n\r\n};\r\n\r\n\r\n\r\n/**\r\n * Util class provides static helper functions.\r\n */\r\nexport class Util {\r\n\r\n \r\n static _warnLevel:WarningType = \"mute\";\r\n\r\n /**\r\n * Set a global warning level setting. If no parameter is passed, this will return the current warn-level. See [`Util.warn`](#link).\r\n * @param lv a [`WarningType`](#link) option, where \"error\" will throw an error, \"warn\" will log in console, and \"mute\" will ignore the error. \r\n */\r\n static warnLevel( lv?:WarningType ):WarningType {\r\n if ( lv ) {\r\n Util._warnLevel = lv;\r\n }\r\n return Util._warnLevel;\r\n }\r\n\r\n\r\n /**\r\n * Convert different kinds of parameters (arguments, array, object) into an array of numbers. \r\n * @param args can be either a list of numbers, an array, a Pt, or an object with {x,y,z,w} properties\r\n */\r\n static getArgs( args:any[] ):Array<number> {\r\n if ( args.length < 1 ) return [];\r\n\r\n let pos = [];\r\n \r\n let isArray = Array.isArray( args[0] ) || ArrayBuffer.isView( args[0] );\r\n \r\n // positional arguments: x,y,z,w,...\r\n if ( typeof args[0] === 'number' ) {\r\n pos = Array.prototype.slice.call( args );\r\n\r\n // as an object of {x, y?, z?, w?}\r\n } else if ( typeof args[0] === 'object' && !isArray ) {\r\n let a = [\"x\", \"y\", \"z\", \"w\"];\r\n let p = args[0];\r\n for ( let i = 0; i < a.length; i++ ) {\r\n if ( ( p.length && i >= p.length ) || !( a[i] in p ) ) break; // check for length and key exist\r\n pos.push( p[ a[i] ] );\r\n }\r\n\r\n // as an array of values\r\n } else if ( isArray ) {\r\n pos = [].slice.call( args[0] );\r\n }\r\n \r\n return pos;\r\n }\r\n\r\n\r\n /**\r\n * Send a warning message based on [`Util.warnLevel`](#link) global setting. This allows you to dynamically set whether minor errors should be thrown or printed in console or muted.\r\n * @param message any error or warning message\r\n * @param defaultReturn optional return value\r\n */\r\n static warn( message:string = \"error\", defaultReturn:any = undefined ):any {\r\n if ( Util.warnLevel() == \"error\" ) {\r\n throw new Error( message );\r\n } else if ( Util.warnLevel() == \"warn\" ) {\r\n console.warn( message );\r\n }\r\n return defaultReturn;\r\n \r\n }\r\n\r\n\r\n /**\r\n * Get a random integer. This can be useful for selecting a random index in an array.\r\n * @param range value range\r\n * @param start Optional starting value\r\n */\r\n static randomInt( range:number, start:number = 0 ) {\r\n Util.warn( \"Util.randomInt is deprecated. Please use `Num.randomRange`\" );\r\n return Math.floor( Num.random() * range ) + start;\r\n }\r\n\r\n\r\n /**\r\n * Split an array into chunks of sub-array.\r\n * @param pts an array \r\n * @param size chunk size, ie, number of items in a chunk\r\n * @param stride optional parameter to \"walk through\" the array in steps\r\n * @param loopBack if `true`, always go through the array till the end and loop back to the beginning to complete the segments if needed.\r\n * @param matchSize if `true`, all chunks's length must match `size`.\r\n */\r\n static split( pts: any[], size: number, stride?: number, loopBack: boolean = false, matchSize = true ): any[][] {\r\n let chunks: any[] = [];\r\n let part: any[] = [];\r\n let st: number = stride || size;\r\n let index: number = 0;\r\n if ( pts.length <= 0 || st <= 0 ) return [];\r\n \r\n while ( index < pts.length ) {\r\n part = [];\r\n for ( let k = 0; k < size; k++ ) {\r\n if ( loopBack ) {\r\n part.push( pts[( index + k ) % pts.length] );\r\n } else {\r\n if ( index + k >= pts.length ) break;\r\n part.push( pts[index + k] );\r\n }\r\n }\r\n index += st;\r\n if ( !matchSize || ( matchSize && part.length === size ) ) chunks.push( part );\r\n }\r\n\r\n return chunks;\r\n }\r\n \r\n\r\n /**\r\n * Flatten an array of arrays such as Group[] to a flat Array or Group.\r\n * @param pts an array, usually an array of Groups\r\n * @param flattenAsGroup a boolean to specify whether the return type should be a Group or Array. Default is `true` which returns a Group.\r\n */\r\n static flatten( pts:any[], flattenAsGroup:boolean = true ) {\r\n let arr = ( flattenAsGroup ) ? new Group() : [];\r\n return arr.concat.apply( arr, pts );\r\n }\r\n\r\n\r\n /**\r\n * Given two arrays of objects, and a function that operate on two objects, return an array. Objects must be of same type. \r\n * @param a an array of object, eg `[Group, Group, ...]` \r\n * @param b another array of object \r\n * @param op a function that takes two parameters (a, b) and returns an object. \r\n */\r\n static combine<T>( a:T[], b:T[], op:( a:T, b:T ) => T ):T[] {\r\n let result = [];\r\n for ( let i = 0, len = a.length; i < len; i++ ) {\r\n for ( let k = 0, lenB = b.length; k < lenB; k++ ) {\r\n result.push( op( a[i], b[k] ) );\r\n }\r\n }\r\n return result;\r\n }\r\n\r\n\r\n /**\r\n * Zip arrays. eg, `[[1,2],[3,4],[5,6]] => [[1,3,5],[2,4,6]]`.\r\n * @param arrays an array of arrays \r\n */\r\n static zip( arrays:Array<any>[] ) {\r\n let z = [];\r\n for ( let i = 0, len = arrays[0].length; i < len; i++ ) {\r\n let p = [];\r\n for ( let k = 0; k < arrays.length; k++ ) {\r\n p.push( arrays[k][i] );\r\n }\r\n z.push( p );\r\n }\r\n return z;\r\n }\r\n\r\n\r\n /**\r\n * Create a convenient stepper. This returns a function which you can call repeatedly to step a counter.\r\n * @param max Maximum of the stepper range. The resulting stepper will return (min to max-1) values.\r\n * @param min Minimum of the stepper range. Default is 0.\r\n * @param stride Stride of the step. Default is 1.\r\n * @param callback An optional callback function `fn( step )`, which will be called each time when stepper function is called.\r\n * @example `let counter = stepper(100); let c = counter(); c = counter(); ...`\r\n * @returns a function which will increment the stepper and return its value at each call.\r\n */\r\n static stepper( max:number, min:number = 0, stride:number = 1, callback?:( n:number ) => void ):( () => number ) {\r\n let c = min;\r\n return function() {\r\n c += stride;\r\n if ( c >= max ) {\r\n c = min + ( c - max );\r\n }\r\n if ( callback ) callback( c );\r\n return c;\r\n };\r\n }\r\n\r\n\r\n /**\r\n * A convenient way to step through a range. Same as `for (i=0; i<range; i++)`, except this also stores the resulting return values at each step and return them as an array.\r\n * @param range a range to step through\r\n * @param fn a callback function `fn(index)`. If this function returns a value, it will be stored at each step\r\n * @returns an array of returned values at each step \r\n */\r\n static forRange( fn:( index:number ) => any, range:number, start:number = 0, step:number = 1 ):any[] {\r\n let temp = [];\r\n for ( let i = start, len = range; i < len; i += step ) {\r\n temp[i] = fn( i );\r\n }\r\n return temp;\r\n }\r\n\r\n\r\n /**\r\n * A helper function to load data from a url via XMLHttpRequest GET. Since the response passed into callback is a string, if you're loading json data, you may use standard `JSON.parse(response)` to get a JSON object. For csv, try using a javascript csv library like papaparse or vega/datalib.\r\n * @param url the request url\r\n * @param callback a function to capture the data. It receives two parameters: a `response` as string, and a `success` status as boolean.\r\n */\r\n static load( url:string, callback:( response:string, success:boolean ) => void ) {\r\n let request = new XMLHttpRequest();\r\n request.open( 'GET', url, true );\r\n\r\n request.onload = function() {\r\n if ( request.status >= 200 && request.status < 400 ) {\r\n callback( request.responseText, true );\r\n } else {\r\n callback( `Server error (${request.status}) when loading \"${url}\"`, false );\r\n }\r\n };\r\n\r\n request.onerror = function() {\r\n callback( `Unknown network error`, false );\r\n };\r\n\r\n request.send();\r\n }\r\n\r\n\r\n /**\r\n * Download the current `CanvasSpace` as an image (jpg/png/webp). Calling this function will automatically trigger a download.\r\n * @param space an instance of `CanvasSpace`\r\n * @param filename the name of the file, without the extension name. \r\n * @param filetype the image type (jpg/png/webp)\r\n * @param quality a value between 0 to 1, if filetype is either \"jpg\" or \"png\"\r\n */\r\n static download( space: CanvasSpace, filename:string = 'pts_canvas_image', filetype:( \"jpeg\" | \"jpg\" | \"png\" | \"webp\" ) = \"png\", quality:number = 1 ) {\r\n const ftype = filetype === 'jpg' ? 'jpeg' : filetype;\r\n space.element.toBlob( function( blob ) {\r\n const link = document.createElement( 'a' );\r\n const url = URL.createObjectURL( blob );\r\n link.href = url;\r\n link.download = `${filename}.${filetype}`;\r\n document.body.appendChild( link );\r\n link.click();\r\n document.body.removeChild( link );\r\n URL.revokeObjectURL( url );\r\n },`image/${ftype}`, quality );\r\n }\r\n\r\n\r\n /**\r\n * Estimate performance by checking how long it takes to render a frame\r\n * @param avgFrames The number of frames used calculate to average\r\n * @example `let perf = Util.performance(); perf();` \r\n * @returns milliseconds per frame\r\n */\r\n static performance( avgFrames:number = 10 ): () => number {\r\n let last = Date.now();\r\n let avg = [];\r\n return function() {\r\n const now = Date.now();\r\n avg.push( now - last );\r\n if ( avg.length >= avgFrames ) avg.shift();\r\n last = now;\r\n return Math.floor( avg.reduce( ( a,b ) => a + b, 0 ) / avg.length );\r\n };\r\n }\r\n\r\n /**\r\n * Check number of items in a Group against a required number\r\n * @param pts a Group or an Iterable<PtLike> \r\n * @param minRequired minimum number of items required\r\n */\r\n static arrayCheck( pts:PtLikeIterable, minRequired:number = 2 ):boolean {\r\n if ( Array.isArray( pts ) && pts.length < minRequired ) {\r\n Util.warn( `Requires ${minRequired} or more Pts in this Group.` );\r\n return false;\r\n } \r\n return true;\r\n }\r\n\r\n\r\n /**\r\n * Convert an iterable into an array\r\n * @param it an iterable\r\n */\r\n static iterToArray( it:Iterable<any> ): any[] {\r\n return ( !Array.isArray( it ) ) ? [...it] : it;\r\n }\r\n \r\n\r\n /**\r\n * Check if accessing from a mobile device. Can be useful since some experimental features may not be availble in mobile browsers.\r\n */\r\n static isMobile() {\r\n return /iPhone|iPad|Android/i.test( navigator.userAgent );\r\n }\r\n\r\n}\r\n\r\n\r\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport { Const, Util } from \"./Util\";\nimport { Curve } from \"./Op\";\nimport { Pt, Group } from \"./Pt\";\nimport { Vec, Mat } from \"./LinearAlgebra\";\nimport {PtLike, GroupLike, PtLikeIterable, PtIterable} from \"./Types\";\n\nimport generator from './uheprng';\n\n/**\n * Num class provides static helper functions for basic numeric operations.\n */\nexport class Num {\n static generator: any;\n\n /**\n * Check if two numbers are equal or almost equal within a threshold.\n * @param a number a\n * @param b number b\n * @param threshold threshold value that specifies the minimum difference within which the two numbers are considered equal\n */\n static equals( a:number, b:number, threshold = 0.00001 ):boolean {\n return Math.abs( a - b ) < threshold;\n }\n\n\n /**\n * Calculate linear interpolation between 2 values.\n * @param a start value\n * @param b end value\n * @param t an interpolation value, usually between 0 to 1\n */\n static lerp( a:number, b:number, t:number ):number {\n return ( 1 - t ) * a + t * b;\n }\n\n\n /**\n * Clamp values between min and max.\n * @param val value to clamp\n * @param min min value\n * @param max max value\n */\n static clamp( val:number, min:number, max:number ):number {\n return Math.max( min, Math.min( max, val ) );\n }\n\n\n /**\n * Different from [`Num.clamp`](#link) in that the value out-of-bound will be \"looped back\" to the other end.\n * @param val value to bound\n * @param min min value\n * @param max max value\n * @example `boundValue(361, 0, 360)` will return 1\n */\n static boundValue( val:number, min:number, max:number ):number {\n const len = Math.abs( max - min );\n let a = val % len;\n\n if ( a > max ) a -= len;\n else if ( a < min ) a += len;\n\n return a;\n }\n\n\n /**\n * Check if a value is within two other values\n * @param p value to check\n * @param a first bounding value\n * @param b second bounding value\n */\n static within( p:number, a:number, b:number ):boolean {\n return p >= Math.min( a, b ) && p <= Math.max( a, b );\n }\n\n\n /**\n * Get a random number within a range.\n * @param a range value 1\n * @param b range value 2\n */\n static randomRange( a:number, b:number = 0 ):number {\n const r = ( a > b ) ? ( a - b ) : ( b - a );\n return a + Num.random() * r;\n }\n\n\n /**\n * Get a random Pt within the range defined by either 1 or 2 Pt\n * @param a the range if only one Pt is used, or the start of the range if two Pt were used\n * @param b optional Pt to define the end of the range\n */\n static randomPt( a:PtLike, b?:PtLike ):Pt {\n const p = new Pt( a.length );\n const range = b ? Vec.subtract( b.slice(), a ) : a;\n const start = b ? a : new Pt( a.length ).fill( 0 );\n for ( let i = 0, len = p.length; i < len; i++ ) {\n p[i] = Num.random() * range[i] + start[i];\n }\n return p;\n }\n\n\n /**\n * Normalize a value within a range.\n * @param n the value to normalize\n * @param a range value 1\n * @param b range value 1\n */\n static normalizeValue( n:number, a:number, b:number ):number {\n const min = Math.min( a, b );\n const max = Math.max( a, b );\n return ( n - min ) / ( max - min );\n }\n\n\n /**\n * Sum a group of numeric arrays.\n * @param pts a Group or an Iterable<PtLike>\n * @returns a Pt of the dimensional sums\n */\n static sum( pts: PtLikeIterable ): Pt {\n const _pts = Util.iterToArray( pts );\n const c = new Pt( _pts[0] );\n for ( let i = 1, len = _pts.length; i < len; i++ ) {\n Vec.add( c, _pts[i] );\n }\n return c;\n }\n\n\n /**\n * Average a group of numeric arrays\n * @param pts a Group or an Iterable<PtLike>\n * @returns a Pt of averages\n */\n static average( pts: PtLikeIterable ): Pt {\n const _pts = Util.iterToArray( pts );\n return Num.sum( _pts ).divide( _pts.length );\n }\n\n\n /**\n * Given a value between 0 to 1, returns a value that cycles between 0 -> 1 -> 0 using the provided shaping method.\n * @param t a value between 0 to 1\n * @param method a shaping method. Default to [`Shaping.sineInOut`](#link).\n * @return a value between 0 to 1\n */\n static cycle( t:number, method:( t:number ) => number = Shaping.sineInOut ):number {\n return method( t > 0.5 ? 2 - t * 2 : t * 2 );\n }\n\n\n /** \n * Map a value from one range to another.\n * @param n a value in the first range\n * @param currMin lower bound of the first range\n * @param currMax upper bound of the first range\n * @param targetMin lower bound of the second range\n * @param targetMax upper bound of the second range\n * @returns a remapped value in the second range\n */\n static mapToRange( n:number, currA:number, currB:number, targetA:number, targetB:number ) {\n if ( currA == currB ) throw new Error( \"[currMin, currMax] must define a range that is not zero\" );\n const min = Math.min( targetA, targetB );\n const max = Math.max( targetA, targetB );\n return Num.normalizeValue( n, currA, currB ) * ( max - min ) + min;\n }\n\n /**\n * Seed the pseudorandom generator.\n * @param seed seed string\n */\n static seed( seed: string ): void {\n this.generator = generator( seed );\n }\n\n /**\n * Return a random number between 0 and 1 from a seed,\n * if the seed is not defined it uses Math.random\n * @returns a number between 0 and 1\n */\n static random(): number {\n return this.generator \n ? this.generator.random()\n : Math.random();\n }\n}\n\n\n\n/**\n * Geom class provides static helper functions for basic geometric operations.\n */\nexport class Geom {\n\n /**\n * Bound an angle between 0 to 360 degrees.\n * @param angle angle value\n */\n static boundAngle( angle:number ):number {\n return Num.boundValue( angle, 0, 360 );\n }\n\n\n /**\n * Bound a radian between 0 to two PI.\n * @param radian radian value\n */\n static boundRadian( radian:number ):number {\n return Num.boundValue( radian, 0, Const.two_pi );\n }\n\n\n /**\n * Convert an angle in degree to radian.\n * @param angle angle value\n */\n static toRadian( angle:number ):number {\n return angle * Const.deg_to_rad;\n }\n\n\n /**\n * Convert an angle in radian to degree.\n * @param radian radian value\n */\n static toDegree( radian:number ):number {\n return radian * Const.rad_to_deg;\n }\n\n\n /**\n * Get a bounding box for a set of Pts.\n * @param pts a Group or an Iterable<Pt>\n * @return a Group of two Pts, representing the top-left and bottom-right corners\n */\n static boundingBox( pts:PtIterable ): Group {\n let minPt: Pt, maxPt: Pt;\n for ( const p of pts ) {\n if ( minPt == undefined ) {\n minPt = p.clone();\n maxPt = p.clone();\n } else {\n minPt = minPt.$min( p );\n maxPt = maxPt.$max( p );\n }\n }\n return new Group( minPt, maxPt );\n }\n\n\n /**\n * Get a centroid (the average middle point) for a set of Pts.\n * @param pts a Group or an Iterable<PtLike> \n * @return a centroid Pt \n */\n static centroid( pts:PtLikeIterable ):Pt {\n return Num.average( pts );\n }\n\n\n /**\n * Given an anchor Pt, rebase all Pts in this group either to or from this anchor base.\n * @param pts a Group or an Iterable<PtLike> \n * @param ptOrIndex an index for the Pt array, or an external Pt\n * @param direction a string either \"to\" (subtract all Pt with this anchor base), or \"from\" (add all Pt from this anchor base)\n */\n static anchor( pts:PtLikeIterable, ptOrIndex:PtLike | number = 0, direction:( \"to\" | \"from\" ) = \"to\" ) {\n const method = ( direction == \"to\" ) ? \"subtract\" : \"add\";\n let i = 0;\n for ( const p of pts ) {\n if ( typeof ptOrIndex == \"number\" ) {\n if ( ptOrIndex !== i ) p[method]( pts[ptOrIndex] );\n } else {\n p[method]( ptOrIndex );\n }\n i++;\n }\n }\n\n\n /**\n * Get an interpolated (or extrapolated) value between two Pts. For linear interpolation between 2 scalar values, use [`Num.lerp`](#link).\n * @param a first Pt\n * @param b second Pt\n * @param t a value between 0 to 1 to interpolate, or any other value to extrapolate\n * @returns interpolated point as a new Pt\n */\n static interpolate( a:PtLike, b:PtLike, t:number = 0.5 ):Pt {\n const len = Math.min( a.length, b.length );\n const d = Pt.make( len );\n for ( let i = 0; i < len; i++ ) {\n d[i] = a[i] * ( 1 - t ) + b[i] * t;\n }\n return d;\n }\n\n\n /**\n * Find two Pts that are perpendicular to this Pt (2D only).\n * @param axis a string such as \"xy\" (use Const.xy) or an array to specify index for two dimensions\n * @returns an array of two Pt that are perpendicular to this Pt\n */\n static perpendicular( pt:PtLike, axis:string | PtLike = Const.xy ):Group {\n const y = axis[1];\n const x = axis[0];\n\n const p = new Pt( pt );\n const pa = new Pt( p );\n pa[x] = -p[y];\n pa[y] = p[x];\n const pb = new Pt( p );\n pb[x] = p[y];\n pb[y] = -p[x];\n\n return new Group( pa, pb );\n }\n\n\n /**\n * Check if two Pts are perpendicular to each other (2D only).\n */\n static isPerpendicular( p1:PtLike, p2:PtLike ):boolean {\n return new Pt( p1 ).dot( p2 ) === 0;\n }\n\n\n /**\n * Check if a Pt is within the rectangular boundary defined by two Pts.\n * @param pt the Pt to check\n * @param boundPt1 boundary Pt 1\n * @param boundPt2 boundary Pt 2\n */\n static withinBound( pt:PtLike, boundPt1:PtLike, boundPt2:PtLike ):boolean {\n for ( let i = 0, len = Math.min( pt.length, boundPt1.length, boundPt2.length ); i < len; i++ ) {\n if ( !Num.within( pt[i], boundPt1[i], boundPt2[i] ) ) return false;\n }\n return true;\n }\n\n\n /**\n * Sort the Pts so that their edges will form a non-overlapping polygon. ([Reference](https://stackoverflow.com/questions/6989100/sort-points-in-clockwise-order))\n * @param pts a Group or an Iterable<Pt>\n */\n static sortEdges( pts:PtIterable ):GroupLike {\n\n const _pts = Util.iterToArray( pts );\n const bounds = Geom.boundingBox( _pts );\n const center = bounds[1].add( bounds[0] ).divide( 2 );\n \n const fn = ( a:Pt, b:Pt ):number => {\n if ( a.length < 2 || b.length < 2 ) throw new Error( \"Pt dimension cannot be less than 2\" );\n\n const da = a.$subtract( center );\n const db = b.$subtract( center );\n \n if ( da[0] >= 0 && db[0] < 0 ) return 1;\n if ( da[0] < 0 && db[0] >= 0 ) return -1;\n if ( da[0] == 0 && db[0] == 0 ) {\n if ( da[1] >= 0 || db[1] >= 0 )\n return ( da[1] > db[1] ) ? 1 : -1;\n return ( db[1] > da[1] ) ? 1 : -1;\n }\n\n // compute the cross product of vectors (center -> a) x (center -> b)\n const det = da.$cross2D( db );\n if ( det < 0 ) return 1;\n if ( det > 0 ) return -1;\n \n // points a and b are on the same line from the center\n // check which point is closer to the center\n return ( da[0] * da[0] + da[1] * da[1] > db[0] * db[0] + db[1] * db[1] ) ? 1 : -1;\n };\n\n return _pts.sort( fn );\n }\n\n\n /**\n * Scale a Pt or a Group of Pts. You may also use [`Pt.scale`](#link) instance method.\n * @param ps either a single Pt, or a Group or an Iterable<Pt>\n * @param scale scale value\n * @param anchor optional anchor point to scale from\n */\n static scale( ps:Pt | PtIterable, scale:number | PtLike, anchor?:PtLike ):Geom {\n const pts = Util.iterToArray( ( ps[0] !== undefined && typeof ps[0] == 'number' ) ? [ps] : ps );\n const scs = ( typeof scale == \"number\" ) ? Pt.make( pts[0].length, scale ) : scale;\n if ( !anchor ) anchor = Pt.make( pts[0].length, 0 );\n\n for ( let i = 0, len = pts.length; i < len; i++ ) {\n const p = pts[i];\n for ( let k = 0, lenP = p.length; k < lenP; k++ ) {\n p[k] = ( anchor && anchor[k] ) ? anchor[k] + ( p[k] - anchor[k] ) * scs[k] : p[k] * scs[k];\n }\n }\n\n return Geom;\n }\n\n\n /**\n * Rotate a Pt or a Group of Pts in 2D space. You may also use [`Pt.rotate2D`](#link) instance method.\n * @param ps either a single Pt, or a Group or an Iterable<Pt>\n * @param angle rotate angle\n * @param anchor optional anchor point to rotate from\n * @param axis optional axis such as \"xy\" (use Const.xy) to define a 2D plane, or a number array to specify indices\n */\n static rotate2D( ps:Pt | PtIterable, angle:number, anchor?:PtLike, axis?:string | PtLike ):Geom {\n const pts = Util.iterToArray( ( ps[0] !== undefined && typeof ps[0] == 'number' ) ? [ps] : ps );\n const fn = ( anchor ) ? Mat.rotateAt2DMatrix : Mat.rotate2DMatrix;\n if ( !anchor ) anchor = Pt.make( pts[0].length, 0 );\n const cos = Math.cos( angle );\n const sin = Math.sin( angle );\n\n for ( let i = 0, len = pts.length; i < len; i++ ) {\n const p = ( axis ) ? pts[i].$take( axis ) : pts[i];\n p.to( Mat.transform2D( p, fn( cos, sin, anchor ) ) );\n if ( axis ) {\n for ( let k = 0; k < axis.length; k++ ) {\n pts[i][axis[k]] = p[k];\n }\n }\n }\n\n return Geom;\n }\n\n\n /**\n * Shear a Pt or a Group of Pts in 2D space. You may also use [`Pt.shear2D`](#link) instance method.\n * @param ps either a single Pt, or a Group or an Iterable<Pt>\n * @param scale shearing value which can be a number or an array of 2 numbers\n * @param anchor optional anchor point to shear from\n * @param axis optional axis such as \"xy\" (use Const.xy) to define a 2D plane, or a number array to specify indices\n */\n static shear2D( ps:Pt | PtIterable, scale:number | PtLike, anchor?:PtLike, axis?:string | PtLike ):Geom {\n const pts = Util.iterToArray( ( ps[0] !== undefined && typeof ps[0] == 'number' ) ? [ps] : ps );\n const s = ( typeof scale == \"number\" ) ? [scale, scale] : scale;\n if ( !anchor ) anchor = Pt.make( pts[0].length, 0 );\n const fn = ( anchor ) ? Mat.shearAt2DMatrix : Mat.shear2DMatrix;\n const tanx = Math.tan( s[0] );\n const tany = Math.tan( s[1] );\n\n for ( let i = 0, len = pts.length; i < len; i++ ) {\n const p = ( axis ) ? pts[i].$take( axis ) : pts[i];\n p.to( Mat.transform2D( p, fn( tanx, tany, anchor ) ) );\n if ( axis ) {\n for ( let k = 0; k < axis.length; k++ ) {\n pts[i][axis[k]] = p[k];\n }\n }\n }\n\n return Geom;\n }\n\n\n /**\n * Reflect a Pt or a Group of Pts along a 2D line. You may also use [`Pt.reflect2D`](#link) instance method.\n * @param ps either a single Pt, or a Group or an Iterable<Pt>\n * @param line a Group or an Iterable<PtLike> that defines a line for reflection\n * @param axis optional axis such as \"xy\" (use Const.xy) to define a 2D plane, or a number array to specify indices\n */\n static reflect2D( ps:Pt | PtIterable, line:PtLikeIterable, axis?:string | PtLike ):Geom {\n const pts = Util.iterToArray( ( ps[0] !== undefined && typeof ps[0] == 'number' ) ? [ps] : ps );\n const _line = Util.iterToArray( line );\n const mat = Mat.reflectAt2DMatrix( _line[0], _line[1] );\n\n for ( let i = 0, len = pts.length; i < len; i++ ) {\n const p = ( axis ) ? pts[i].$take( axis ) : pts[i];\n p.to( Mat.transform2D( p, mat ) );\n if ( axis ) {\n for ( let k = 0; k < axis.length; k++ ) {\n pts[i][axis[k]] = p[k];\n }\n }\n }\n\n return Geom;\n }\n\n\n /**\n * Generate a cosine lookup table.\n * @returns an object with a cosine tables (array of 360 values) and a function to get cosine given a radian input. \n */\n static cosTable() {\n const cos = new Float64Array( 360 );\n\n for ( let i = 0; i < 360; i++ ) cos[i] = Math.cos( i * Math.PI / 180 );\n const find = ( rad:number ) => cos[Math.floor( Geom.boundAngle( Geom.toDegree( rad ) ) )];\n\n return { table: cos, cos: find };\n }\n\n /**\n * Generate a sine lookup table.\n * @returns an object with a sine tables (array of 360 values) and a function to get sine value given a radian input. \n */\n static sinTable() {\n const sin = new Float64Array( 360 );\n\n for ( let i = 0; i < 360; i++ ) sin[i] = Math.sin( i * Math.PI / 180 );\n const find = ( rad:number ) => sin[Math.floor( Geom.boundAngle( Geom.toDegree( rad ) ) )];\n\n return { table: sin, sin: find };\n }\n}\n\n\n\n/**\n * Shaping provides shaping functions to interpolate a value. These are useful for easing and transitions.\n */\nexport class Shaping {\n\n /**\n * Linear mapping.\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static linear( t:number, c:number = 1 ):number {\n return c * t;\n }\n\n /** \n * Quadratic in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static quadraticIn( t:number, c:number = 1 ):number {\n return c * t * t;\n }\n\n /** \n * Quadratic out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static quadraticOut( t:number, c:number = 1 ):number {\n return -c * t * ( t - 2 );\n }\n\n /** \n * Quadratic in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static quadraticInOut( t:number, c:number = 1 ):number {\n const dt = t * 2;\n return ( t < 0.5 ) ? c / 2 * t * t * 4 : -c / 2 * ( ( dt - 1 ) * ( dt - 3 ) - 1 );\n }\n\n /** \n * Cubic in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static cubicIn( t:number, c:number = 1 ):number {\n return c * t * t * t;\n }\n\n /** \n * Cubic out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static cubicOut( t:number, c:number = 1 ):number {\n const dt = t - 1;\n return c * ( dt * dt * dt + 1 );\n }\n\n /** \n * Cubic in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static cubicInOut( t:number, c:number = 1 ):number {\n const dt = t * 2;\n return ( t < 0.5 ) ? c / 2 * dt * dt * dt : c / 2 * ( ( dt - 2 ) * ( dt - 2 ) * ( dt - 2 ) + 2 );\n }\n\n /** \n * Exponential ease in, adapted from Golan Levin's [polynomial shapers](http://www.flong.com/texts/code/shapers_poly/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p a value between 0 to 1 to control the curve. Default is 0.25.\n */\n static exponentialIn( t:number, c:number = 1, p:number = 0.25 ):number {\n return c * Math.pow( t, 1 / p );\n }\n\n /** \n * Exponential ease out, adapted from Golan Levin's [polynomial shapers](http://www.flong.com/texts/code/shapers_poly/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p a value between 0 to 1 to control the curve. Default is 0.25.\n */\n static exponentialOut( t:number, c:number = 1, p:number = 0.25 ):number {\n return c * Math.pow( t, p );\n }\n\n /** \n * Sinuous in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static sineIn( t:number, c:number = 1 ):number {\n return -c * Math.cos( t * Const.half_pi ) + c;\n }\n\n /** \n * Sinuous out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static sineOut( t:number, c:number = 1 ):number {\n return c * Math.sin( t * Const.half_pi );\n }\n\n /** \n * Sinuous in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static sineInOut( t:number, c:number = 1 ):number {\n return -c / 2 * ( Math.cos( Math.PI * t ) - 1 );\n }\n\n /** \n * A faster way to approximate cosine ease in-out using Blinn-Wyvill Approximation. Adapated from Golan Levin's [polynomial shaping](http://www.flong.com/texts/code/shapers_poly/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static cosineApprox( t:number, c:number = 1 ) {\n const t2 = t * t;\n const t4 = t2 * t2;\n const t6 = t4 * t2;\n return c * ( 4 * t6 / 9 - 17 * t4 / 9 + 22 * t2 / 9 );\n }\n\n /** \n * Circular in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static circularIn( t:number, c:number = 1 ):number {\n return -c * ( Math.sqrt( 1 - t * t ) - 1 );\n }\n\n /** \n * Circular out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static circularOut( t:number, c:number = 1 ):number {\n const dt = t - 1;\n return c * Math.sqrt( 1 - dt * dt );\n }\n\n /** \n * Circular in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static circularInOut( t:number, c:number = 1 ):number {\n const dt = t * 2;\n return ( t < 0.5 ) ? -c / 2 * ( Math.sqrt( 1 - dt * dt ) - 1 ) : c / 2 * ( Math.sqrt( 1 - ( dt - 2 ) * ( dt - 2 ) ) + 1 );\n }\n\n /** \n * Elastic in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.\n */\n static elasticIn( t:number, c:number = 1, p:number = 0.7 ):number {\n const dt = t - 1;\n const s = ( p / Const.two_pi ) * 1.5707963267948966;\n return c * ( -Math.pow( 2, 10 * dt ) * Math.sin( ( dt - s ) * Const.two_pi / p ) );\n }\n\n /** \n * Elastic out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.7.\n */\n static elasticOut( t:number, c:number = 1, p:number = 0.7 ):number {\n const s = ( p / Const.two_pi ) * 1.5707963267948966;\n return c * ( Math.pow( 2, -10 * t ) * Math.sin( ( t - s ) * Const.two_pi / p ) ) + c;\n }\n\n /** \n * Elastic in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p elastic parmeter between 0 to 1. The lower the number, the more elastic it will be. Default is 0.6.\n */\n static elasticInOut( t:number, c:number = 1, p:number = 0.6 ):number {\n let dt = t * 2;\n const s = ( p / Const.two_pi ) * 1.5707963267948966;\n if ( t < 0.5 ) {\n dt -= 1;\n return c * ( -0.5 * ( Math.pow( 2, 10 * dt ) * Math.sin( ( dt - s ) * Const.two_pi / p ) ) );\n } else {\n dt -= 1;\n return c * ( 0.5 * ( Math.pow( 2, -10 * dt ) * Math.sin( ( dt - s ) * Const.two_pi / p ) ) ) + c;\n }\n }\n\n /** \n * Bounce in, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static bounceIn( t:number, c:number = 1 ):number {\n return c - Shaping.bounceOut( ( 1 - t ), c );\n }\n\n /** \n * Bounce out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static bounceOut( t:number, c:number = 1 ) {\n if ( t < ( 1 / 2.75 ) ) {\n return c * ( 7.5625 * t * t );\n } else if ( t < ( 2 / 2.75 ) ) {\n t -= 1.5 / 2.75;\n return c * ( 7.5625 * t * t + 0.75 );\n } else if ( t < ( 2.5 / 2.75 ) ) {\n t -= 2.25 / 2.75;\n return c * ( 7.5625 * t * t + 0.9375 );\n } else {\n t -= 2.625 / 2.75;\n return c * ( 7.5625 * t * t + 0.984375 );\n }\n }\n\n /** \n * Bounce in-out, adapted from Robert Penner's [easing functions](http://robertpenner.com/easing/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n */\n static bounceInOut( t:number, c:number = 1 ):number {\n return ( t < 0.5 ) ? Shaping.bounceIn( t * 2, c ) / 2 : Shaping.bounceOut( t * 2 - 1, c ) / 2 + c / 2;\n }\n\n /** \n * Sigmoid curve changes its shape adapted from the input value, but always returns a value between 0 to 1.\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p the larger the value, the \"steeper\" the curve will be. Default is 10.\n */\n static sigmoid( t:number, c:number = 1, p:number = 10 ):number {\n const d = p * ( t - 0.5 );\n return c / ( 1 + Math.exp( -d ) );\n }\n\n /** \n * Logistic sigmoid, adapted from Golan Levin's [shaping function](http://www.flong.com/texts/code/shapers_exp/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p a parameter between 0 to 1 to control the steepness of the curve. Higher is steeper. Default is 0.7.\n */\n static logSigmoid( t:number, c:number = 1, p:number = 0.7 ):number {\n p = Math.max( Const.epsilon, Math.min( 1 - Const.epsilon, p ) );\n p = 1 / ( 1 - p );\n\n const A = 1 / ( 1 + Math.exp( ( ( t - 0.5 ) * p * -2 ) ) );\n const B = 1 / ( 1 + Math.exp( p ) );\n const C = 1 / ( 1 + Math.exp( -p ) );\n return c * ( A - B ) / ( C - B );\n }\n\n\n /** \n * Exponential seat curve, adapted from Golan Levin's [shaping functions](http://www.flong.com/texts/code/shapers_exp/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p a parameter between 0 to 1 to control the steepness of the curve. Higher is steeper. Default is 0.5.\n */\n static seat( t:number, c:number = 1, p:number = 0.5 ):number {\n if ( ( t < 0.5 ) ) {\n return c * ( Math.pow( 2 * t, 1 - p ) ) / 2;\n } else {\n return c * ( 1 - ( Math.pow( 2 * ( 1 - t ), 1 - p ) ) / 2 );\n }\n }\n\n\n /** \n * Quadratic bezier curve, adapted from Golan Levin's [shaping functions](http://www.flong.com/texts/code/shapers_exp/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p1 a Pt object specifying the first control Pt, or a value specifying the control Pt's x position (its y position will default to 0.5). Default is `Pt(0.95, 0.95)\n */\n static quadraticBezier( t:number, c:number = 1, p:number | PtLike = [0.05, 0.95] ):number {\n const a:number = ( typeof p != \"number\" ) ? p[0] : p;\n const b:number = ( typeof p != \"number\" ) ? p[1] : 0.5;\n let om2a = 1 - 2 * a;\n if ( om2a === 0 ) {\n om2a = Const.epsilon;\n }\n const d = ( Math.sqrt( a * a + om2a * t ) - a ) / om2a;\n return c * ( ( 1 - 2 * b ) * ( d * d ) + ( 2 * b ) * d );\n }\n\n\n /** \n * Cubic bezier curve. This reuses the bezier functions in Curve class.\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p1` a Pt object specifying the first control Pt. Default is `Pt(0.1, 0.7).\n * @param p2` a Pt object specifying the second control Pt. Default is `Pt(0.9, 0.2).\n */\n static cubicBezier( t:number, c:number = 1, p1:PtLike = [0.1, 0.7], p2:PtLike = [0.9, 0.2] ):number {\n const curve = new Group( new Pt( 0, 0 ), new Pt( p1 ), new Pt( p2 ), new Pt( 1, 1 ) );\n return c * Curve.bezierStep( new Pt( t * t * t, t * t, t, 1 ), Curve.controlPoints( curve ) ).y;\n }\n\n\n /** \n * Give a Pt, draw a quadratic curve that will pass through that Pt as closely as possible. Adapted from Golan Levin's [shaping functions](http://www.flong.com/texts/code/shapers_poly/).\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p1` a Pt object specifying the Pt to pass through. Default is `Pt(0.2, 0.35)\n */\n static quadraticTarget( t:number, c:number = 1, p1:PtLike = [0.2, 0.35] ):number {\n const a = Math.min( 1 - Const.epsilon, Math.max( Const.epsilon, p1[0] ) );\n const b = Math.min( 1, Math.max( 0, p1[1] ) );\n const A = ( 1 - b ) / ( 1 - a ) - ( b / a );\n const B = ( A * ( a * a ) - b ) / a;\n const y = A * ( t * t ) - B * t;\n return c * Math.min( 1, Math.max( 0, y ) );\n }\n\n\n /** \n * Step function is a simple jump from 0 to 1 at a specific Pt in time.\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param p usually a value between 0 to 1, which specify the Pt to \"jump\". Default is 0.5 which is in the middle.\n */\n static cliff( t:number, c:number = 1, p:number = 0.5 ):number {\n return ( t > p ) ? c : 0;\n }\n\n /** \n * Convert any shaping functions into a series of steps.\n * @param fn the original shaping function\n * @param steps the number of steps\n * @param t a value between 0 to 1\n * @param c the value to shape, default is 1\n * @param args optional paramters to pass to original function\n */\n static step( fn: Function, steps:number, t:number, c:number, ...args:any[] ) {\n const s = 1 / steps;\n const tt = Math.floor( t / s ) * s;\n return fn( tt, c, ...args );\n }\n\n}\n\n\n/**\n * Range object keeps track of a Group of n-dimensional Pts to provide its minimum, maximum, and magnitude in each dimension. \n * It also provides convenient functions such as mapping the Group to another range. This class may be useful for visualizing data in charts.\n */\nexport class Range {\n\n protected _source:Group;\n protected _max:Pt;\n protected _min:Pt;\n protected _mag:Pt;\n protected _dims:number = 0;\n\n\n /**\n * Construct a Range instance for a Group of Pts.\n * @param g a Group or an Iterable<Pt>\n */\n constructor( g:PtIterable ) {\n this._source = Group.fromPtArray( g );\n this.calc();\n }\n\n /**\n * Get this Range's maximum values per dimension.\n */\n get max():Pt { return this._max.clone(); }\n \n /**\n * Get this Range's minimum values per dimension.\n */\n get min():Pt { return this._min.clone(); }\n \n /**\n * Get this Range's magnitude in each dimension.\n */\n get magnitude():Pt { return this._mag.clone(); }\n\n\n /**\n * Go through the group and find its min and max values. Usually you don't need to call this function directly.\n */\n calc():this {\n if ( !this._source ) return;\n const dims = this._source[0].length;\n this._dims = dims;\n const max = new Pt( dims );\n const min = new Pt( dims );\n const mag = new Pt( dims );\n\n for ( let i = 0; i < dims; i++ ) {\n max[i] = Const.min;\n min[i] = Const.max;\n mag[i] = 0;\n\n const s = this._source.zipSlice( i );\n for ( let k = 0, len = s.length; k < len; k++ ) {\n max[i] = Math.max( max[i], s[k] );\n min[i] = Math.min( min[i], s[k] );\n mag[i] = max[i] - min[i];\n }\n }\n\n this._max = max;\n this._min = min;\n this._mag = mag;\n return this;\n }\n\n\n /**\n * Map this Range to another range of values.\n * @param min target range's minimum value\n * @param max target range's maximum value\n * @param exclude Optional boolean array where `true` means excluding the conversion in that specific dimension.\n */\n mapTo( min:number, max:number, exclude?:boolean[] ):Group {\n const target = new Group();\n for ( let i = 0, len = this._source.length; i < len; i++ ) {\n const g = this._source[i];\n const n = new Pt( this._dims );\n for ( let k = 0; k < this._dims; k++ ) {\n n[k] = ( exclude && exclude[k] ) ? g[k] : Num.mapToRange( g[k], this._min[k], this._max[k], min, max ); \n }\n target.push( n ); \n }\n return target;\n }\n\n\n /**\n * Add more Pts to this Range and recalculate its min and max values.\n * @param pts a Group or an Iterable<PtLike> to append to this Range\n * @param update Optional. Set the parameter to `false` if you want to append without immediately updating this Range's min and max values. Default is `true`.\n */\n append( pts:PtLikeIterable, update:boolean = true ):this {\n const _pts = Util.iterToArray( pts );\n if ( _pts[0].length !== this._dims ) throw new Error( `Dimensions don't match. ${this._dims} dimensions in Range and ${_pts[0].length} provided in parameter. ` );\n this._source = this._source.concat( _pts ) as Group;\n if ( update ) this.calc();\n return this;\n }\n\n\n /**\n * Create a number of evenly spaced \"ticks\" that span this Range's min and max value.\n * @param count number of subdivision. For example, 10 subdivision will return 11 tick values, which include first(min) and last(max) values.\n */\n ticks( count:number ):Group {\n const g = new Group();\n for ( let i = 0; i <= count; i++ ) {\n const p = new Pt( this._dims );\n for ( let k = 0, len = this._max.length; k < len; k++ ) {\n p[k] = Num.lerp( this._min[k], this._max[k], i / count );\n }\n g.push( p );\n }\n return g;\n }\n\n}\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Util} from \"./Util\";\nimport {Geom, Num} from \"./Num\";\nimport {Pt, Group} from \"./Pt\";\nimport {Mat} from \"./LinearAlgebra\";\nimport {PtLike, GroupLike, PtLikeIterable, IntersectContext, PtIterable} from \"./Types\";\n\n\nlet _errorLength = ( obj, param:number | string = \"expected\" ) => Util.warn( \"Group's length is less than \" + param, obj );\nlet _errorOutofBound = ( obj, param:number | string = \"\" ) => Util.warn( `Index ${param} is out of bound in Group`, obj );\n\n\n/**\n * Line class provides static functions to create and operate on lines. A line is usually represented as a Group of 2 Pts.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Line {\n\n /**\n * Create a line that originates from an anchor point, given an angle and a magnitude.\n * @param anchor an anchor Pt\n * @param angle an angle in radian\n * @param magnitude magnitude of the line\n * @return a Group of 2 Pts representing a line segement\n */\n static fromAngle( anchor:PtLike, angle:number, magnitude:number ):Group {\n let g = new Group( new Pt( anchor ), new Pt( anchor ) );\n g[1].toAngle( angle, magnitude, true );\n return g;\n }\n\n\n /**\n * Calculate the slope of a line.\n * @param p1 line's first end point\n * @param p2 line's second end point\n */\n static slope( p1:PtLike, p2:PtLike ):number {\n return ( p2[0] - p1[0] === 0 ) ? undefined : ( p2[1] - p1[1] ) / ( p2[0] - p1[0] );\n }\n\n\n /**\n * Calculate the slope and xy intercepts of a line.\n * @param p1 line's first end point\n * @param p2 line's second end point\n * @returns an object with `slope`, `xi`, `yi` properties \n */\n static intercept( p1:PtLike, p2:PtLike ):{ slope:number, xi:number, yi:number } {\n if ( p2[0] - p1[0] === 0 ) {\n return undefined;\n } else {\n let m = ( p2[1] - p1[1] ) / ( p2[0] - p1[0] );\n let c = p1[1] - m * p1[0];\n return { slope: m, yi: c, xi: ( m === 0 ) ? undefined : -c / m };\n }\n }\n\n\n /**\n * Given a 2D path and a point, find whether the point is on left or right side of the line.\n * @param line a Group or an Iterable<PtLike> representing a line\n * @param pt a Pt or numeric array\n * @returns a negative value if on left and a positive value if on right. If collinear, then the return value is 0.\n */\n static sideOfPt2D( line:PtLikeIterable, pt:PtLike ):number {\n let _line = Util.iterToArray( line );\n return ( _line[1][0] - _line[0][0] ) * ( pt[1] - _line[0][1] ) - ( pt[0] - _line[0][0] ) * ( _line[1][1] - _line[0][1] );\n }\n\n\n /**\n * Check if three Pts are collinear, ie, on the same straight path.\n * @param p1 first Pt\n * @param p2 second Pt\n * @param p3 third Pt\n * @param threshold a threshold where a smaller value means higher precision threshold for the straight line. Default is 0.01.\n */\n static collinear( p1:PtLike, p2:PtLike, p3:PtLike, threshold:number = 0.01 ):boolean {\n // Use cross product method\n let a = new Pt( 0,0,0 ).to( p1 ).$subtract( p2 );\n let b = new Pt( 0,0,0 ).to( p1 ).$subtract( p3 ); \n return a.$cross( b ).divide( 1000 ).equals( new Pt( 0,0,0 ), threshold );\n }\n\n\n /**\n * Get magnitude of a line segment.\n * @param line a Group or an Iterable<Pt> with at least 2 Pt\n */\n static magnitude( line:PtIterable ):number {\n let _line = Util.iterToArray( line );\n return ( _line.length >= 2 ) ? _line[1].$subtract( _line[0] ).magnitude() : 0;\n }\n\n\n /**\n * Get squared magnitude of a line segment.\n * @param _line a Group or an Iterable<Pt> with at least 2 Pt\n */\n static magnitudeSq( line:PtIterable ):number {\n let _line = Util.iterToArray( line );\n return ( _line.length >= 2 ) ? _line[1].$subtract( _line[0] ).magnitudeSq() : 0;\n }\n\n\n /**\n * Find a point on a line that is perpendicular (shortest distance) to a target point.\n * @param line a Group or an Iterable<Pt> that defines a line\n * @param pt a target Pt \n * @param asProjection if true, this returns the projection vector instead. Default is false.\n * @returns a Pt on the line that is perpendicular to the target Pt, or a projection vector if `asProjection` is true.\n */\n static perpendicularFromPt( line:PtIterable, pt:PtLike, asProjection:boolean = false ):Pt {\n let _line = Util.iterToArray( line );\n if ( _line[0].equals( _line[1] ) ) return undefined;\n let a = _line[0].$subtract( _line[1] );\n let b = _line[1].$subtract( pt );\n let proj = b.$subtract( a.$project( b ) );\n\n return ( asProjection ) ? proj : proj.$add( pt );\n }\n\n\n /**\n * Given a line and a point, find the shortest distance from the point to the line.\n * @param line a Group of 2 Pts\n * @param pt a Pt\n * @see `Line.perpendicularFromPt`\n */\n static distanceFromPt( line:GroupLike, pt:PtLike | number[] ):number {\n let _line = Util.iterToArray( line );\n let projectionVector = Line.perpendicularFromPt( _line, pt, true );\n if ( projectionVector ) {\n return projectionVector.magnitude();\n } else {\n // line is made of 2 identical points, return distance between this point and pt\n return _line[0].$subtract( pt ).magnitude();\n }\n }\n\n\n /**\n * Given two lines as rays (infinite lines), find their intersection point if any.\n * @param la a Group or an Iterable<Pt> with 2 Pt representing a ray\n * @param lb a Group or an Iterable<Pt> with 2 Pts representing another ray\n * @returns an intersection Pt or undefined if no intersection\n */\n static intersectRay2D( la:PtIterable, lb:PtIterable ):Pt {\n let _la = Util.iterToArray( la );\n let _lb = Util.iterToArray( lb );\n\n let a = Line.intercept( _la[0], _la[1] );\n let b = Line.intercept( _lb[0], _lb[1] );\n\n let pa = _la[0];\n let pb = _lb[0];\n\n if ( a == undefined ) {\n if ( b == undefined ) return undefined;\n // one of them is vertical line, while the other is not, so they will intersect\n let y1 = -b.slope * ( pb[0] - pa[0] ) + pb[1]; // -slope * x + y\n return new Pt( pa[0], y1 );\n\n } else {\n // diff slope, or b slope is vertical line\n if ( b == undefined ) {\n let y1 = -a.slope * ( pa[0] - pb[0] ) + pa[1];\n return new Pt( pb[0], y1 );\n\n } else if ( b.slope != a.slope ) {\n let px = ( a.slope * pa[0] - b.slope * pb[0] + pb[1] - pa[1] ) / ( a.slope - b.slope );\n let py = a.slope * ( px - pa[0] ) + pa[1];\n return new Pt( px, py );\n \n } else {\n if ( a.yi == b.yi ) { // exactly along the same path\n return new Pt( pa[0], pa[1] );\n } else {\n return undefined;\n }\n }\n }\n }\n\n\n /**\n * Given two line segemnts, find their intersection point if any.\n * @param la a Group or an Iterable<Pt> with 2 Pt representing a line segment\n * @param lb a Group or an Iterable<Pt> with 2 Pt representing a line segment\n * @returns an intersection Pt or undefined if no intersection\n */\n static intersectLine2D( la:PtIterable, lb:PtIterable ):Pt {\n let _la = Util.iterToArray( la );\n let _lb = Util.iterToArray( lb );\n\n let pt = Line.intersectRay2D( _la, _lb );\n return ( pt && Geom.withinBound( pt, _la[0], _la[1] ) && Geom.withinBound( pt, _lb[0], _lb[1] ) ) ? pt : undefined;\n }\n\n\n /**\n * Given a line segemnt and a ray (infinite line), find their intersection point if any.\n * @param line a Group of 2 Pts representing a line segment\n * @param ray a Group of 2 Pts representing a ray\n * @returns an intersection Pt or undefined if no intersection\n */\n static intersectLineWithRay2D( line:PtIterable, ray:PtIterable ):Pt {\n let _line = Util.iterToArray( line );\n let _ray = Util.iterToArray( ray );\n let pt = Line.intersectRay2D( _line, _ray );\n return ( pt && Geom.withinBound( pt, _line[0], _line[1] ) ) ? pt : undefined;\n }\n\n\n /**\n * Given a line segemnt or a ray (infinite line), find its intersection point(s) with a polygon.\n * @param lineOrRay a Group or an Iterable<Pt> with 2 Pt representing a line or ray\n * @param poly a Group or an Iterable<Pt> representing a polygon\n * @param sourceIsRay a boolean value to treat the line as a ray (infinite line). Default is `false`.\n */\n static intersectPolygon2D( lineOrRay:PtIterable, poly:PtIterable, sourceIsRay:boolean = false ):Group {\n let _lineOrRay = Util.iterToArray( lineOrRay );\n let _poly = Util.iterToArray( poly );\n\n let fn = sourceIsRay ? Line.intersectLineWithRay2D : Line.intersectLine2D; \n let pts = new Group();\n for ( let i = 0, len = _poly.length; i < len; i++ ) {\n let next = ( i === len - 1 ) ? 0 : i + 1;\n let d = fn( [_poly[i], _poly[next]], _lineOrRay );\n if ( d ) pts.push( d ); \n }\n return ( pts.length > 0 ) ? pts : undefined;\n } \n\n\n /**\n * Find intersection points of 2 sets of lines. This checks all line segments in the two lists. Consider using a bounding-box check before calling this. If you are checking convex polygon intersections, using [`Polygon.intersectPolygon2D`](#link) will be more efficient.\n * @param lines1 an Array/Iterable of (Groups or Iterables<Pt>)\n * @param lines2 an Array/Iterable of (Groups or Iterables<Pt>)\n * @param isRay a boolean value to treat the line as a ray (infinite line). Default is `false`.\n */\n static intersectLines2D( lines1:Iterable<PtIterable>, lines2:Iterable<PtIterable>, isRay:boolean = false ):Group {\n let group = new Group();\n let fn = isRay ? Line.intersectLineWithRay2D : Line.intersectLine2D; \n for ( let l1 of lines1 ) {\n for ( let l2 of lines2 ) {\n let _ip = fn( l1, l2 );\n if ( _ip ) group.push( _ip );\n }\n }\n return group;\n }\n\n\n /**\n * Get two points of a ray that intersects with a point on a 2D grid.\n * @param ray a Group or an Iterable<Pt> representing a ray\n * @param gridPt a Pt on the grid\n * @returns a group of two intersecting Pts. The first one is horizontal intersection and the second one is vertical intersection.\n */\n static intersectGridWithRay2D( ray:PtIterable, gridPt:PtLike ):Group {\n let _ray = Util.iterToArray( ray );\n let t = Line.intercept( new Pt( _ray[0] ).subtract( gridPt ), new Pt( _ray[1] ).subtract( gridPt ) );\n let g = new Group();\n if ( t && t.xi ) g.push( new Pt( gridPt[0] + t.xi, gridPt[1] ) );\n if ( t && t.yi ) g.push( new Pt( gridPt[0], gridPt[1] + t.yi ) );\n return g;\n } \n\n\n /**\n * Get two intersection Pts of a line segment with a 2D grid point.\n * @param line a ray specified by 2 Pts\n * @param gridPt a Pt on the grid\n * @returns a group of two intersecting Pts. The first one is horizontal intersection and the second one is vertical intersection.\n */\n static intersectGridWithLine2D( line:GroupLike, gridPt:PtLike | number[] ):Group {\n let _line = Util.iterToArray( line );\n let g = Line.intersectGridWithRay2D( _line, gridPt );\n let gg = new Group();\n for ( let i = 0, len = g.length; i < len; i++ ) {\n if ( Geom.withinBound( g[i], _line[0], _line[1] ) ) gg.push( g[i] );\n }\n return gg;\n }\n\n\n /**\n * An easy way to get rectangle-line intersection points. For more optimized implementation, store the rectangle's sides separately (eg, `Rectangle.sides()`) and use `Polygon.intersectPolygon2D()`.\n * @param line a Group representing a line\n * @param rect a Group representing a rectangle\n * @returns a Group of intersecting Pts\n */\n static intersectRect2D( line:GroupLike, rect:GroupLike ):Group {\n let _line = Util.iterToArray( line );\n let _rect = Util.iterToArray( rect );\n let box = Geom.boundingBox( Group.fromPtArray( _line ) );\n if ( !Rectangle.hasIntersectRect2D( box, _rect ) ) return new Group();\n return Line.intersectLines2D( [_line], Rectangle.sides( _rect ) );\n }\n\n\n /**\n * Get evenly distributed points on a line. Similar to [`Create.distributeLinear`](#link) but excluding end points.\n * @param line a Group or an Iterable<PtLike> representing a line\n * @param num number of points to get\n */\n static subpoints( line:PtLikeIterable, num:number ) {\n let _line = Util.iterToArray( line );\n let pts = new Group();\n for ( let i = 1; i <= num; i++ ) {\n pts.push( Geom.interpolate( _line[0], _line[1], i / ( num + 1 ) ) );\n }\n return pts;\n }\n\n\n /**\n * Crop this line by a circle or rectangle at end points. This can be useful for creating arrows that connect to an object's edge.\n * @param line a Group or an Iterable<Pt> representing a line to crop\n * @param size size of circle or rectangle as Pt\n * @param index line's end point index, ie, 0 = start and 1 = end.\n * @param cropAsCircle a boolean to specify whether the `size` parameter should be treated as circle. Default is `true`.\n * @return an intersecting point on the line that can be used for cropping.\n */\n static crop( line:PtIterable, size:PtLike, index:number = 0, cropAsCircle:boolean = true ):Pt {\n let _line = Util.iterToArray( line );\n let tdx = ( index === 0 ) ? 1 : 0;\n let ls = _line[tdx].$subtract( _line[index] );\n\n if ( ls[0] === 0 || size[0] === 0 ) return _line[index];\n\n if ( cropAsCircle ) {\n let d = ls.unit().multiply( size[1] );\n return _line[index].$add( d );\n\n } else {\n let rect = Rectangle.fromCenter( _line[index], size );\n let sides = Rectangle.sides( rect );\n let sideIdx = 0;\n\n if ( Math.abs( ls[1] / ls[0] ) > Math.abs( size[1] / size[0] ) ) {\n sideIdx = ( ls[1] < 0 ) ? 0 : 2;\n } else {\n sideIdx = ( ls[0] < 0 ) ? 3 : 1;\n }\n return Line.intersectRay2D( sides[sideIdx], _line );\n\n }\n }\n\n /**\n * Create an marker arrow or line, placed at an end point of this line.\n * @param line a Group or an Iterable<Pt> representing a line to place marker\n * @param size size of the marker as Pt\n * @param graphic either \"arrow\" or \"line\"\n * @param atTail a boolean, if `true`, the marker will be positioned at tail of the line (ie, index = 1). Default is `true`.\n * @returns a Group that defines the marker's shape\n */\n static marker( line:PtIterable, size:PtLike, graphic:string = ( \"arrow\" || \"line\" ), atTail:boolean = true ):Group {\n let _line = Util.iterToArray( line );\n let h = atTail ? 0 : 1;\n let t = atTail ? 1 : 0;\n let unit = _line[h].$subtract( _line[t] );\n\n if ( unit.magnitudeSq() === 0 ) return new Group();\n unit.unit();\n \n let ps = Geom.perpendicular( unit ).multiply( size[0] ).add( _line[t] );\n if ( graphic == \"arrow\" ) {\n ps.add( unit.$multiply( size[1] ) );\n return new Group( _line[t], ps[0], ps[1] );\n } else {\n return new Group( ps[0], ps[1] );\n }\n\n }\n\n /**\n * Convert this line to a new rectangle representation.\n * @param line a Group representing a line\n */\n static toRect( line:GroupLike ) {\n let _line = Util.iterToArray( line );\n return new Group( _line[0].$min( _line[1] ), _line[0].$max( _line[1] ) );\n }\n\n}\n\n\n\n/**\n * Rectangle class provides static functions to create and operate on rectangles. A rectangle is usually represented as a Group of 2 Pts, marking the top-left and bottom-right corners of the rectangle.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Rectangle {\n\n /**\n * Create a rectangle from top-left anchor point. Same as [`Rectangle.fromTopLeft`](#link).\n * @param topLeft top-left point\n * @param widthOrSize width as a number, or a Pt that defines its size\n * @param height optional height as a number\n * @returns a Group of 2 Pts representing a rectangle\n */\n static from( topLeft:PtLike, widthOrSize:number | PtLike, height?:number ):Group {\n return Rectangle.fromTopLeft( topLeft, widthOrSize, height );\n }\n\n\n /**\n * Create a rectangle given a top-left position and a size.\n * @param topLeft top-left point\n * @param widthOrSize width as a number, or a Pt that defines its size\n * @param height optional height as a number\n * @returns a Group of 2 Pts representing a rectangle\n */\n static fromTopLeft( topLeft:PtLike, widthOrSize:number | PtLike, height?:number ):Group {\n let size = ( typeof widthOrSize == \"number\" ) ? [widthOrSize, ( height || widthOrSize )] : widthOrSize;\n return new Group( new Pt( topLeft ), new Pt( topLeft ).add( size ) );\n }\n\n\n /**\n * Create a rectangle given a center position and a size.\n * @param topLeft top-left point\n * @param widthOrSize width as a number, or a Pt that defines its size\n * @param height optional height as a number\n * @returns a Group of 2 Pts representing a rectangle\n */\n static fromCenter( center:PtLike, widthOrSize:number | PtLike, height?:number ):Group {\n let half = ( typeof widthOrSize == \"number\" ) ? [widthOrSize / 2, ( height || widthOrSize ) / 2] : new Pt( widthOrSize ).divide( 2 );\n return new Group( new Pt( center ).subtract( half ), new Pt( center ).add( half ) );\n }\n\n\n /**\n * Create a new circle that either fits within or encloses the rectangle. Same as [`Circle.fromRect`](#link).\n * @param pts a Group or an Iterable<Pt> with 2 Pt representing a rectangle\n * @param within if `true`, the circle will be within the rectangle. If `false`, the circle will enclose the rectangle. \n * @returns a Group that represents a circle\n */\n static toCircle( pts:PtIterable, within:boolean = true ):Group {\n return Circle.fromRect( pts, within );\n }\n\n \n /**\n * Create a square that either fits within or encloses a rectangle.\n * @param pts a Group or an Iterable<Pt> with 2 Pt representing a rectangle\n * @param enclose if `true`, the square will enclose the rectangle. Default is `false`, which will fit the square inside the rectangle.\n * @returns a Group of 2 Pts representing a rectangle\n */\n static toSquare( pts:PtIterable, enclose = false ):Group {\n let _pts = Util.iterToArray( pts );\n let s = Rectangle.size( _pts );\n let m = ( enclose ) ? s.maxValue().value : s.minValue().value;\n return Rectangle.fromCenter( Rectangle.center( _pts ), m, m );\n }\n\n\n /**\n * Get the size of this rectangle as a Pt.\n * @param p a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n */\n static size( pts:PtIterable ):Pt {\n let p = Util.iterToArray( pts );\n return p[0].$max( p[1] ).subtract( p[0].$min( p[1] ) );\n }\n\n\n /**\n * Get the center of this rectangle.\n * @param p a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n */\n static center( pts:PtIterable ):Pt {\n let p = Util.iterToArray( pts );\n let min = p[0].$min( p[1] );\n let max = p[0].$max( p[1] );\n return min.add( max.$subtract( min ).divide( 2 ) );\n }\n\n\n /**\n * Get the 4 corners of this rectangle as a Group.\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n */\n static corners( rect:PtIterable ):Group {\n let _rect = Util.iterToArray( rect );\n let p0 = _rect[0].$min( _rect[1] );\n let p2 = _rect[0].$max( _rect[1] );\n return new Group( p0, new Pt( p2.x, p0.y ), p2, new Pt( p0.x, p2.y ) );\n }\n\n\n /**\n * Get the 4 sides of this rectangle as an array of 4 Groups.\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n * @returns an array of 4 Groups, each of which represents a line segment\n */\n static sides( rect:PtIterable ):Group[] {\n let [p0, p1, p2, p3] = Rectangle.corners( rect );\n return [\n new Group( p0, p1 ), new Group( p1, p2 ),\n new Group( p2, p3 ), new Group( p3, p0 )\n ];\n }\n\n\n /**\n * Given an array of rectangles, get a rectangle that bounds all of them.\n * @param rects an array of (Groups or Iterables<PtLike>) that represents a set of rectangles\n * @returns the bounding rectangle as a Group\n */\n static boundingBox( rects:Iterable<PtLikeIterable> ):Group {\n let _rects = Util.iterToArray( rects );\n let merged = Util.flatten( _rects, false );\n let min = Pt.make( 2, Number.MAX_VALUE );\n let max = Pt.make( 2, Number.MIN_VALUE );\n\n // calculate min max in a single pass\n for ( let i = 0, len = merged.length; i < len; i++ ) {\n let k = 0;\n for ( let m of merged[i] ) {\n min[k] = Math.min( min[k], m[k] );\n max[k] = Math.max( max[k], m[k] );\n if ( ++k >= 2 ) break;\n }\n }\n return new Group( min, max );\n }\n\n\n /**\n * Convert this rectangle into a Group representing a polygon. An alias for [`Rectangle.corners`](#link)\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n */\n static polygon( rect:PtIterable ):Group {\n return Rectangle.corners( rect );\n }\n\n\n /**\n * Subdivide a rectangle into 4 rectangles, one for each quadrant.\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n * @returns an array of 4 Groups of rectangles\n */\n static quadrants( rect:PtIterable, center?:PtLike ):Group[] {\n let _rect = Util.iterToArray( rect );\n let corners = Rectangle.corners( _rect );\n let _center = ( center != undefined ) ? new Pt( center ) : Rectangle.center( _rect );\n return corners.map( ( c ) => new Group( c, _center ).boundingBox() );\n }\n\n\n /**\n * Subdivde a rectangle into 2 rectangles, by row or by column.\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a Rectangle\n * @param ratio a value between 0 to 1 to indicate the split ratio\n * @param asRows if `true`, split into 2 rows. Default is `false` which splits into 2 columns.\n * @returns an array of 2 Groups of rectangles\n */\n static halves( rect:PtIterable, ratio:number = 0.5, asRows:boolean = false ):Group[] {\n let _rect = Util.iterToArray( rect );\n let min = _rect[0].$min( _rect[1] );\n let max = _rect[0].$max( _rect[1] );\n let mid = ( asRows ) ? Num.lerp( min[1], max[1], ratio ) : Num.lerp( min[0], max[0], ratio );\n return ( asRows ) \n ? [new Group( min, new Pt( max[0],mid ) ), new Group( new Pt( min[0],mid ), max )]\n : [new Group( min, new Pt( mid,max[1] ) ), new Group( new Pt( mid,min[1] ), max )];\n }\n\n\n /**\n * Check if a point is within a rectangle.\n * @param rect a Group of 2 Pts representing a Rectangle\n * @param pt the point to check\n */\n static withinBound( rect:GroupLike, pt:PtLike ):boolean {\n let _rect = Util.iterToArray( rect );\n return Geom.withinBound( pt, _rect[0], _rect[1] );\n }\n\n\n /**\n * Check if a rectangle is within the bounds of another rectangle.\n * @param rect1 a Group of 2 Pts representing a rectangle\n * @param rect2 a Group of 2 Pts representing a rectangle\n * @param resetBoundingBox if `true`, reset the bounding box. Default is `false` which assumes the rect's first Pt at is its top-left corner.\n */\n static hasIntersectRect2D( rect1:GroupLike, rect2:GroupLike, resetBoundingBox:boolean = false ):boolean {\n let _rect1 = Util.iterToArray( rect1 );\n let _rect2 = Util.iterToArray( rect2 );\n\n if ( resetBoundingBox ) {\n _rect1 = Geom.boundingBox( _rect1 );\n _rect2 = Geom.boundingBox( _rect2 );\n }\n\n if ( _rect1[0][0] > _rect2[1][0] || _rect2[0][0] > _rect1[1][0] ) return false;\n if ( _rect1[0][1] > _rect2[1][1] || _rect2[0][1] > _rect1[1][1] ) return false; \n return true;\n \n }\n\n\n /**\n * An easy way to get rectangle-rectangle intersection points. For more optimized implementation, store the rectangle's sides separately (eg, `Rectangle.sides()`) and use `Polygon.intersectPolygon2D()`.\n * @param rect1 a Group of 2 Pts representing a rectangle\n * @param rect2 a Group of 2 Pts representing a rectangle\n */\n static intersectRect2D( rect1:GroupLike, rect2:GroupLike ):Group {\n let _rect1 = Util.iterToArray( rect1 );\n let _rect2 = Util.iterToArray( rect2 );\n if ( !Rectangle.hasIntersectRect2D( _rect1, _rect2 ) ) return new Group();\n return Line.intersectLines2D( Rectangle.sides( _rect1 ), Rectangle.sides( _rect2 ) );\n }\n\n}\n\n\n\n/**\n * Circle class provides static functions to create and operate on circles. A circle is usually represented as a Group of 2 Pts, where the first Pt specifies the center, and the second Pt specifies the radius.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Circle {\n \n\n /**\n * Create a circle that either fits within, or encloses, a rectangle.\n * @param pts a Group or an Iterable<PtLike> with 2 Pt representing a rectangle\n * @param enclose if `true`, the circle will enclose the rectangle. Default is `false`, which will fit the circle inside the rectangle.\n * @returns a Group that represents a circle\n */\n static fromRect( pts:PtLikeIterable, enclose = false ):Group {\n let _pts = Util.iterToArray( pts );\n let r = 0;\n let min = r = Rectangle.size( _pts ).minValue().value / 2;\n if ( enclose ) {\n let max = Rectangle.size( _pts ).maxValue().value / 2;\n r = Math.sqrt( min * min + max * max );\n } else {\n r = min;\n }\n return new Group( Rectangle.center( _pts ), new Pt( r, r ) );\n }\n\n\n /**\n * Create a circle that either fits within, or encloses, a triangle. Same as [`Triangle.circumcircle`](#link) or [`Triangle.incircle`](#link).\n * @param pts a Group or an Iterable<Pt> with 3 Pt representing a rectangle\n * @param enclose if `true`, the circle will enclose the triangle. Default is `false`, which will fit the circle inside the triangle.\n * @returns a Group that represents a circle\n */\n static fromTriangle( pts:PtIterable, enclose:boolean = false ):Group {\n if ( enclose ) {\n return Triangle.circumcircle( pts );\n } else {\n return Triangle.incircle( pts );\n }\n }\n\n\n /**\n * Create a circle based on a center point and a radius.\n * @param pt center point of circle\n * @param radius radius of circle\n * @returns a Group that represents a circle\n */\n static fromCenter( pt:PtLike, radius:number ):Group {\n return new Group( new Pt( pt ), new Pt( radius, radius ) );\n }\n\n\n /**\n * Check if a point is within a circle.\n * @param pts a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param pt the point to checks\n * @param threshold an optional small number to set threshold. Default is 0.\n */\n static withinBound( pts:PtIterable, pt:PtLike, threshold:number = 0 ):boolean {\n let _pts = Util.iterToArray( pts );\n let d = _pts[0].$subtract( pt );\n return d.dot( d ) + threshold < _pts[1].x * _pts[1].x;\n }\n\n\n /**\n * Get the intersection points between a circle and a ray (infinite line).\n * @param circle a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param ray a Group or an Iterable<Pt> with 2 Pt representing a ray \n * @returns a Group of intersection points, or an empty Group if no intersection is found\n */\n static intersectRay2D( circle:PtIterable, ray:PtIterable ):Group {\n let _pts = Util.iterToArray( circle );\n let _ray = Util.iterToArray( ray );\n\n let d = _ray[0].$subtract( _ray[1] );\n let f = _pts[0].$subtract( _ray[0] );\n\n let a = d.dot( d );\n let b = f.dot( d );\n let c = f.dot( f ) - _pts[1].x * _pts[1].x;\n let p = b / a;\n let q = c / a;\n let disc = p * p - q; // discriminant\n\n if ( disc < 0 ) {\n return new Group();\n } else {\n let discSqrt = Math.sqrt( disc );\n\n let t1 = -p + discSqrt;\n let p1 = _ray[0].$subtract( d.$multiply( t1 ) );\n if ( disc === 0 ) return new Group( p1 );\n\n let t2 = -p - discSqrt;\n let p2 = _ray[0].$subtract( d.$multiply( t2 ) );\n return new Group( p1, p2 );\n }\n }\n\n\n /**\n * Get the intersection points between a circle and a line segment.\n * @param circle a Group or an Iterable<Pt> with Pt representing a circle\n * @param line a Group or an Iterable<Pt> with 2 Pt representing a line\n * @returns a Group of intersection points, or an empty Group if no intersection is found\n */\n static intersectLine2D( circle:PtIterable, line:PtIterable ):Group {\n let _pts = Util.iterToArray( circle );\n let _line = Util.iterToArray( line );\n\n let ps = Circle.intersectRay2D( _pts, _line );\n let g = new Group();\n if ( ps.length > 0 ) {\n for ( let i = 0, len = ps.length; i < len; i++ ) {\n if ( Rectangle.withinBound( _line, ps[i] ) ) g.push( ps[i] );\n }\n }\n return g;\n }\n\n\n /**\n * Get the intersection points between two circles.\n * @param circle1 a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param circle2 a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @returns a Group of intersection points, or an empty Group if no intersection is found\n */\n static intersectCircle2D( circle1:PtIterable, circle2:PtIterable ):Group {\n let _pts = Util.iterToArray( circle1 );\n let _circle = Util.iterToArray( circle2 );\n \n let dv = _circle[0].$subtract( _pts[0] );\n let dr2 = dv.magnitudeSq();\n let dr = Math.sqrt( dr2 );\n\n let ar = _pts[1].x;\n let br = _circle[1].x;\n let ar2 = ar * ar;\n let br2 = br * br;\n\n\n if ( dr > ar + br ) { // not intersected\n return new Group();\n } else if ( dr < Math.abs( ar - br ) ) { // completely enclosed\n return new Group( _pts[0].clone() );\n } else {\n let a = ( ar2 - br2 + dr2 ) / ( 2 * dr );\n let h = Math.sqrt( ar2 - a * a );\n let p = dv.$multiply( a / dr ).add( _pts[0] );\n return new Group( \n new Pt( p.x + h * dv.y / dr, p.y - h * dv.x / dr ),\n new Pt( p.x - h * dv.y / dr, p.y + h * dv.x / dr )\n );\n }\n }\n\n\n /**\n * Quick way to check rectangle intersection with a circle. \n * For more optimized implementation, store the rectangle's sides separately (eg, [`Rectangle.sides`](#link)) and use [`Polygon.intersectPolygon2D()`](#link).\n * @param circle a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a rectangle\n * @returns a Group of intersection points, or an empty Group if no intersection is found\n */\n static intersectRect2D( circle:PtIterable, rect:PtIterable ):Group {\n let _pts = Util.iterToArray( circle );\n let _rect = Util.iterToArray( rect );\n\n let sides = Rectangle.sides( _rect );\n let g = [];\n for ( let i = 0, len = sides.length; i < len; i++ ) {\n let ps = Circle.intersectLine2D( _pts, sides[i] );\n if ( ps.length > 0 ) g.push( ps );\n }\n return Util.flatten( g );\n }\n\n\n /**\n * Get a rectangle that either fits within or encloses this circle. See also [`Rectangle.toCircle`](#link)\n * @param circle a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param within if `true`, the rectangle will be within the circle. If `false`, the rectangle will enclose the circle. \n * @returns a Group representing a rectangle\n */\n static toRect( circle:PtIterable, within:boolean = false ):Group {\n let _pts = Util.iterToArray( circle );\n let r = _pts[1][0];\n if ( within ) {\n let half = Math.sqrt( r * r ) / 2;\n return new Group( _pts[0].$subtract( half ), _pts[0].$add( half ) );\n } else {\n return new Group( _pts[0].$subtract( r ), _pts[0].$add( r ) );\n }\n }\n\n\n /**\n * Get a triangle that fits within this circle.\n * @param circle a Group or an Iterable<Pt> with 2 Pt representing a circle\n * @param within if `true`, the triangle will be within the circle. If `false`, the triangle will enclose the circle. \n */\n static toTriangle( circle:PtIterable, within:boolean = true ):Group {\n let _pts = Util.iterToArray( circle );\n if ( within ) {\n let ang = -Math.PI / 2;\n let inc = Math.PI * 2 / 3;\n let g = new Group();\n for ( let i = 0; i < 3; i++ ) {\n g.push( _pts[0].clone().toAngle( ang, _pts[1][0], true ) );\n ang += inc;\n }\n return g;\n } else {\n return Triangle.fromCenter( _pts[0], _pts[1][0] );\n }\n }\n\n}\n\n\n\n/**\n * Triangle class provides static functions to create and operate on trianges. A triange is a polygon represented as a Group of 3 Pts.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Triangle {\n \n /**\n * Create a triangle from a rectangle. The triangle will be isosceles, with the bottom of the rectangle as its base.\n * @param rect a Group or an Iterable<Pt> with 2 Pt representing a rectangle\n */\n static fromRect( rect:PtIterable ):Group {\n let _rect = Util.iterToArray( rect );\n let top = _rect[0].$add( _rect[1] ).divide( 2 );\n top.y = _rect[0][1];\n let left = _rect[1].clone();\n left.x = _rect[0][0];\n return new Group( top, _rect[1].clone(), left );\n }\n\n\n /**\n * Create a triangle that fits within a circle.\n * @param circle a Group or an Iterable<Pt> with 2 Pt representing a circle\n */\n static fromCircle( circle:PtIterable ):Group {\n return Circle.toTriangle( circle, true );\n }\n\n\n /**\n * Create an equilateral triangle based on a center point and a size.\n * @param pt the center point\n * @param size size is the magnitude of lines from center to the triangle's vertices, like a \"radius\".\n */\n static fromCenter( pt:PtLike, size:number ):Group {\n return Triangle.fromCircle( Circle.fromCenter( pt, size ) );\n }\n\n\n /**\n * Get the medial, which is an inner triangle formed by connecting the midpoints of this triangle's sides.\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @returns a Group representing a medial triangle\n */\n static medial( tri:PtIterable ):Group {\n let _pts = Util.iterToArray( tri );\n if ( _pts.length < 3 ) return _errorLength( new Group(), 3 );\n return Polygon.midpoints( _pts, true );\n }\n\n\n /**\n * Given a point of the triangle, the opposite side is the side which the point doesn't touch.\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @param index a Pt on the triangle group\n * @returns a Group that represents a line of the opposite side\n */\n static oppositeSide( tri:PtIterable, index:number ):Group {\n let _pts = Util.iterToArray( tri );\n if ( _pts.length < 3 ) return _errorLength( new Group(), 3 );\n if ( index === 0 ) {\n return Group.fromPtArray( [_pts[1], _pts[2]] );\n } else if ( index === 1 ) {\n return Group.fromPtArray( [_pts[0], _pts[2]] );\n } else {\n return Group.fromPtArray( [_pts[0], _pts[1]] );\n }\n }\n\n /**\n * Get a triangle's altitude, which is a line from a triangle's point to its opposite side, and perpendicular to its opposite side.\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @param index a Pt on the triangle group\n * @returns a Group that represents the altitude line\n */\n static altitude( tri:PtIterable, index:number ):Group {\n let _pts = Util.iterToArray( tri );\n let opp = Triangle.oppositeSide( _pts, index );\n if ( opp.length > 1 ) {\n return new Group( _pts[index], Line.perpendicularFromPt( opp, _pts[index] ) ); \n } else {\n return new Group();\n }\n }\n\n /**\n * Get orthocenter, which is the intersection point of a triangle's 3 altitudes (the 3 lines that are perpendicular to its 3 opposite sides).\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @returns the orthocenter as a Pt\n */\n static orthocenter( tri:PtIterable ):Pt {\n let _pts = Util.iterToArray( tri );\n if ( _pts.length < 3 ) return _errorLength( undefined, 3 );\n let a = Triangle.altitude( _pts, 0 );\n let b = Triangle.altitude( _pts, 1 );\n return Line.intersectRay2D( a, b );\n }\n\n /**\n * Get incenter, which is the center point of its inner circle, and also the intersection point of its 3 angle bisector lines (each of which cuts one of the 3 angles in half).\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @returns the incenter as a Pt\n */\n static incenter( tri:PtIterable ):Pt {\n let _pts = Util.iterToArray( tri );\n if ( _pts.length < 3 ) return _errorLength( undefined, 3 );\n let a = Polygon.bisector( _pts, 0 ).add( _pts[0] );\n let b = Polygon.bisector( _pts, 1 ).add( _pts[1] );\n return Line.intersectRay2D( new Group( _pts[0], a ), new Group( _pts[1], b ) );\n }\n\n /**\n * Get an interior circle, which is the largest circle completed enclosed by this triangle.\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @param center Optional parameter if the incenter is already known. Otherwise, leave it empty and the incenter will be calculated\n */\n static incircle( tri:PtIterable, center?:Pt ):Group {\n let _pts = Util.iterToArray( tri );\n let c = ( center ) ? center : Triangle.incenter( _pts );\n let area = Polygon.area( _pts );\n let perim = Polygon.perimeter( _pts, true );\n let r = 2 * area / perim.total;\n return Circle.fromCenter( c, r );\n }\n\n /**\n * Get circumcenter, which is the intersection point of its 3 perpendicular bisectors lines ( each of which divides a side in half and is perpendicular to the side).\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @returns the circumcenter as a Pt\n */\n static circumcenter( tri:PtIterable ):Pt {\n let _pts = Util.iterToArray( tri );\n let md = Triangle.medial( _pts );\n let a = [md[0], Geom.perpendicular( _pts[0].$subtract( md[0] ) ).p1.$add( md[0] )];\n let b = [md[1], Geom.perpendicular( _pts[1].$subtract( md[1] ) ).p1.$add( md[1] )];\n return Line.intersectRay2D( a, b );\n } \n\n /**\n * Get circumcenter, which is the intersection point of its 3 perpendicular bisectors lines ( each of which divides a side in half and is perpendicular to the side).\n * @param tri a Group or an Iterable<Pt> representing a triangle\n * @param center Optional parameter if the circumcenter is already known. Otherwise, leave it empty and the circumcenter will be calculated \n */\n static circumcircle( tri:PtIterable, center?:Pt ):Group {\n let _pts = Util.iterToArray( tri );\n let c = ( center ) ? center : Triangle.circumcenter( _pts );\n let r = _pts[0].$subtract( c ).magnitude();\n return Circle.fromCenter( c, r );\n }\n}\n\n\n\n/**\n * Polygon class provides static functions to create and operate on polygons. A polygon is usually represented as a Group of 3 or more Pts.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Polygon {\n\n /**\n * Get the centroid of a polygon, which is the average of all its points.\n * @param pts a Group or an Iterable<PtLike> representing a polygon\n */\n static centroid( pts:PtLikeIterable ):Pt {\n return Geom.centroid( pts );\n }\n\n\n /**\n * Create a rectangular polygon. Same as creating a Rectangle and then getting its corners via [`Rectangle.corners`](#link).\n * @param center center point of the rectangle\n * @param widthOrSize width as number, or a Pt representing the size of the rectangle\n * @param height optional height\n */\n static rectangle( center:PtLike, widthOrSize:number | PtLike, height?: number ):Group {\n return Rectangle.corners( Rectangle.fromCenter( center, widthOrSize, height ) );\n }\n\n\n /**\n * Create a regular polygon.\n * @param center The center position of the polygon\n * @param radius The radius, ie, a length from the center position to one of the polygon's corners.\n * @param sides Number of sides\n */\n static fromCenter( center:PtLike, radius:number, sides:number ) {\n let g = new Group();\n for ( let i = 0; i < sides; i++ ) {\n let ang = Math.PI * 2 * i / sides;\n g.push( new Pt( Math.cos( ang ) * radius, Math.sin( ang ) * radius ).add( center ) );\n }\n return g;\n }\n\n\n /**\n * Given a polygon, get one edge using an index.\n * @param pts a Group or an Iterable<PtLike> representing a polygon\n * @param index index of a Pt in the Group\n */\n static lineAt( pts:PtLikeIterable, index:number ) {\n let _pts = Util.iterToArray( pts );\n if ( index < 0 || index >= _pts.length ) throw new Error( \"index out of the Polygon's range\" );\n return new Group( _pts[index], ( index === _pts.length - 1 ) ? _pts[0] : _pts[index + 1] );\n }\n\n /**\n * Get the line segments in this polygon.\n * @param poly a Group or an Iterable<Pt>\n * @param closePath a boolean to specify whether the polygon should be closed (ie, whether the final segment should be counted).\n * @returns an array of Groups which has 2 Pts in each group\n */\n static lines( poly:PtIterable, closePath:boolean = true ):Group[] {\n let _pts = Util.iterToArray( poly );\n if ( _pts.length < 2 ) return _errorLength( new Group(), 2 );\n let sp = Util.split( _pts, 2, 1 );\n if ( closePath ) sp.push( new Group( _pts[_pts.length - 1], _pts[0] ) );\n return sp.map( ( g ) => g as Group );\n }\n\n /**\n * Get a new polygon group that is derived from midpoints in this polygon.\n * @param poly a Group or an Iterable<Pt>\n * @param closePath a boolean to specify whether the polygon should be closed (ie, whether the final segment should be counted).\n * @param t a value between 0 to 1 for interpolation. Default to 0.5 which will get the middle point.\n */\n static midpoints( poly:PtIterable, closePath:boolean = false, t:number = 0.5 ):Group {\n let sides = Polygon.lines( poly, closePath );\n let mids = sides.map( ( s ) => Geom.interpolate( s[0], s[1], t ) );\n return mids as Group;\n }\n\n /**\n * Given a Pt in the polygon group, the adjacent sides are the two sides which the Pt touches.\n * @param poly a Group or an Iterable<Pt>\n * @param index the target Pt\n * @param closePath a boolean to specify whether the polygon should be closed (ie, whether the final segment should be counted).\n */\n static adjacentSides( poly:PtIterable, index:number, closePath:boolean = false ):Group[] {\n let _pts = Util.iterToArray( poly );\n if ( _pts.length < 2 ) return _errorLength( new Group(), 2 );\n if ( index < 0 || index >= _pts.length ) return _errorOutofBound( new Group(), index );\n\n let gs = [];\n let left = index - 1;\n if ( closePath && left < 0 ) left = _pts.length - 1;\n if ( left >= 0 ) gs.push( new Group( _pts[index], _pts[left] ) );\n\n let right = index + 1;\n if ( closePath && right > _pts.length - 1 ) right = 0;\n if ( right <= _pts.length - 1 ) gs.push( new Group( _pts[index], _pts[right] ) );\n\n return gs;\n }\n\n\n /**\n * Get a bisector which is a line that split between two sides of a polygon equally. \n * @param poly a Group or an Iterable<Pt>\n * @param index the Pt in the polygon to bisect from\n * @param closePath a boolean to specify whether the polygon should be closed (ie, whether the final segment should be counted).\n * @returns a bisector Pt that's a normalized unit vector\n */\n static bisector( poly:PtIterable, index:number ):Pt {\n let sides = Polygon.adjacentSides( poly, index, true );\n if ( sides.length >= 2 ) {\n let a = sides[0][1].$subtract( sides[0][0] ).unit();\n let b = sides[1][1].$subtract( sides[1][0] ).unit();\n return a.add( b ).divide( 2 ); \n } else {\n return undefined;\n }\n }\n \n\n /**\n * Find the perimeter of this polygon, ie, the lengths of its sides.\n * @param poly a Group or an Iterable<Pt>\n * @param closePath a boolean to specify whether the polygon should be closed (ie, whether the final segment should be counted).\n * @returns an object with `total` length, and `segments` which is a Pt that stores each segment's length\n */\n static perimeter( poly:PtIterable, closePath:boolean = false ):{total:number, segments:Pt} {\n let lines = Polygon.lines( poly, closePath );\n let mag = 0;\n let p = Pt.make( lines.length, 0 );\n\n for ( let i = 0, len = lines.length; i < len; i++ ) {\n let m = Line.magnitude( lines[i] );\n mag += m;\n p[i] = m;\n }\n\n return {\n total: mag,\n segments: p\n };\n }\n\n \n /**\n * Find the area of a *convex* polygon.\n * @param pts a Group or an Iterable<PtLike> representing a polygon\n */\n static area( pts:PtLikeIterable ) {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 3 ) return _errorLength( new Group(), 3 );\n // determinant\n let det = ( a, b ) => a[0] * b[1] - a[1] * b[0];\n\n let area = 0;\n for ( let i = 0, len = _pts.length; i < len; i++ ) {\n if ( i < _pts.length - 1 ) {\n area += det( _pts[i], _pts[i + 1] );\n } else { \n area += det( _pts[i], _pts[0] );\n }\n }\n return Math.abs( area / 2 );\n }\n\n /**\n * Get a convex hull of a set of points, using Melkman's algorithm. ([Reference](http://geomalgorithms.com/a12-_hull-3.html)).\n * @param pts a Group or an Iterable<PtLike>\n * @param sorted a boolean value to indicate if the group is pre-sorted by x position. Default is false.\n * @returns a group of Pt that defines the convex hull polygon\n */\n static convexHull( pts:PtLikeIterable, sorted:boolean = false ): Group {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 3 ) return _errorLength( new Group(), 3 );\n\n if ( !sorted ) {\n _pts = _pts.slice();\n _pts.sort( ( a,b ) => a[0] - b[0] );\n } \n\n // check if is on left of ray a-b\n let left = ( a, b, c ) => {\n return ( b[0] - a[0] ) * ( c[1] - a[1] ) - ( c[0] - a[0] ) * ( b[1] - a[1] ) > 0;\n };\n \n // double end queue\n let dq = [];\n let bot = _pts.length - 2;\n let top = bot + 3;\n dq[bot] = _pts[2];\n dq[top] = _pts[2];\n\n // first 3 pt as counter-clockwise triangle\n if ( left( _pts[0], _pts[1], _pts[2] ) ) {\n dq[bot + 1] = _pts[0];\n dq[bot + 2] = _pts[1];\n } else {\n dq[bot + 1] = _pts[1];\n dq[bot + 2] = _pts[0];\n }\n\n // remaining pts\n for ( let i = 3, len = _pts.length; i < len; i++ ) {\n let pt = _pts[i];\n \n // if inside the hull\n if ( left( dq[bot], dq[bot + 1], pt ) && left( dq[top - 1], dq[top], pt ) ) {\n continue;\n }\n\n // rightmost tangent\n while ( !left( dq[bot], dq[bot + 1], pt ) ) { bot += 1; }\n bot -= 1;\n dq[bot] = pt;\n \n // leftmost tangent\n while ( !left( dq[top - 1], dq[top], pt ) ) { top -= 1; }\n top += 1;\n dq[top] = pt;\n }\n\n let hull = new Group();\n for ( let h = 0; h < ( top - bot ); h++ ) {\n hull.push( dq[bot + h] );\n }\n\n return hull;\n\n }\n\n\n /**\n * Given a point in the polygon as an origin, get an array of lines that connect all the remaining points to the origin point.\n * @param poly a Group or an Iterable<Pt> representing a polygon\n * @param originIndex the origin point's index in the polygon\n * @returns an array of Groups of line segments\n */\n static network( poly:PtIterable, originIndex:number = 0 ):Group[] {\n let _pts = Util.iterToArray( poly );\n let g = [];\n for ( let i = 0, len = _pts.length; i < len; i++ ) {\n if ( i != originIndex ) g.push( new Group( _pts[originIndex], _pts[i] ) );\n }\n return g;\n }\n\n\n /**\n * Given a target Pt, find a Pt in the polygon's corners that's nearest to it.\n * @param poly a Group or an Iterable<Pt>\n * @param pt Pt to check\n * @returns an index in the pts indicating the nearest Pt, or -1 if none found\n */\n static nearestPt( poly:PtIterable, pt:PtLike ):number {\n let _near = Number.MAX_VALUE;\n let _item = -1;\n let i = 0;\n for ( let p of poly ) {\n let d = p.$subtract( pt ).magnitudeSq();\n if ( d < _near ) {\n _near = d;\n _item = i;\n }\n i++;\n }\n return _item;\n }\n\n\n /**\n * Project axis (eg, for use in Separation Axis Theorem).\n * @param poly a Group or an Iterable<Pt>\n * @param unitAxis unit axis for calculating dot product\n */\n static projectAxis( poly:PtIterable, unitAxis:Pt ):Pt {\n let _poly = Util.iterToArray( poly );\n let dot = unitAxis.dot( _poly[0] );\n let d = new Pt( dot, dot );\n for ( let n = 1, len = _poly.length; n < len; n++ ) {\n dot = unitAxis.dot( _poly[n] );\n d = new Pt( Math.min( dot, d[0] ), Math.max( dot, d[1] ) );\n }\n return d;\n }\n\n\n /**\n * Check overlap distance from projected axis.\n * @param poly1 a Group or an Iterable<Pt> representing the first polygon\n * @param poly2 a Group or an Iterable<Pt> representing the second polygon\n * @param unitAxis unit axis\n */\n protected static _axisOverlap( poly1:PtIterable, poly2:PtIterable, unitAxis:Pt ) {\n let pa = Polygon.projectAxis( poly1, unitAxis );\n let pb = Polygon.projectAxis( poly2, unitAxis );\n return ( pa[0] < pb[0] ) ? pb[0] - pa[1] : pa[0] - pb[1];\n }\n\n\n /**\n * Check if a Pt is inside a convex polygon.\n * @param poly a Group or an Iterable<PtLike> representing a convex polygon\n * @param pt the Pt to check\n */\n static hasIntersectPoint( poly:PtLikeIterable, pt:PtLike ):boolean {\n let _poly = Util.iterToArray( poly );\n let c = false;\n for ( let i = 0, len = _poly.length; i < len; i++ ) {\n let ln = Polygon.lineAt( _poly, i );\n if ( ( ( ln[0][1] > pt[1] ) != ( ln[1][1] > pt[1] ) ) &&\n ( pt[0] < ( ln[1][0] - ln[0][0] ) * ( pt[1] - ln[0][1] ) / ( ln[1][1] - ln[0][1] ) + ln[0][0] ) ) {\n c = !c;\n }\n }\n return c;\n\n }\n\n\n /**\n * Check if a convex polygon and a circle has intersections using Separating Axis Theorem. \n * @param poly a Group or an Iterable<Pt> representing a convex polygon\n * @param circle a Group or an Iterable<Pt> representing a circle\n * @returns an `IntersectContext` object that stores the intersection info, or undefined if there's no intersection\n */\n static hasIntersectCircle( poly:PtIterable, circle:PtIterable ):IntersectContext {\n let _poly = Util.iterToArray( poly );\n let _circle = Util.iterToArray( circle );\n\n let info = {\n which: -1, // 0 if vertex is on second polygon and edge is on first polygon. 1 if the other way round.\n dist: 0,\n normal: null, // perpendicular to edge\n edge: null, // the edge where the intersection occur\n vertex: null, // the vertex on a polygon that has intersected\n };\n\n let c = _circle[0];\n let r = _circle[1][0];\n\n let minDist = Number.MAX_SAFE_INTEGER;\n \n for ( let i = 0, len = _poly.length; i < len; i++ ) {\n let edge = Polygon.lineAt( _poly, i );\n let axis = new Pt( edge[0].y - edge[1].y, edge[1].x - edge[0].x ).unit();\n let poly2 = new Group( c.$add( axis.$multiply( r ) ), c.$subtract( axis.$multiply( r ) ) );\n \n let dist = Polygon._axisOverlap( _poly, poly2, axis );\n\n if ( dist > 0 ) {\n return null;\n } else if ( Math.abs( dist ) < minDist ) {\n // Fix edge case and make sure the circle is intersecting. To be improved.\n let check = Rectangle.withinBound( edge, Line.perpendicularFromPt( edge, c ) ) || Circle.intersectLine2D( circle, edge ).length > 0;\n\n if ( check ) {\n info.edge = edge;\n info.normal = axis;\n minDist = Math.abs( dist );\n info.which = i;\n }\n }\n\n }\n \n if ( !info.edge ) return null;\n\n // direction\n let dir = c.$subtract( Polygon.centroid( _poly ) ).dot( info.normal );\n if ( dir < 0 ) info.normal.multiply( -1 );\n\n info.dist = minDist;\n info.vertex = c;\n\n return info;\n\n }\n\n\n /**\n * Check if two convex polygons have intersections using Separating Axis Theorem. \n * @param poly1 a Group or an Iterable<Pt> representing a convex polygon\n * @param poly2 a Group or an Iterable<Pt> representing another convex polygon\n * @return an `IntersectContext` object that stores the intersection info, or undefined if there's no intersection\n */\n static hasIntersectPolygon( poly1:PtIterable, poly2:PtIterable ):IntersectContext { \n // Reference: https://www.gamedev.net/articles/programming/math-and-physics/a-verlet-based-approach-for-2d-game-physics-r2714/\n let _poly1 = Util.iterToArray( poly1 );\n let _poly2 = Util.iterToArray( poly2 );\n\n let info = {\n which: -1, // 0 if vertex is on second polygon and edge is on first polygon. 1 if the other way round.\n dist: 0,\n normal: new Pt(), // perpendicular to edge\n edge: new Group(), // the edge where the intersection occur\n vertex: new Pt() // the vertex on a polygon that has intersected\n };\n\n let minDist = Number.MAX_SAFE_INTEGER;\n\n\n for ( let i = 0, plen = ( _poly1.length + _poly2.length ); i < plen; i++ ) {\n \n let edge = ( i < _poly1.length ) ? Polygon.lineAt( _poly1, i ) : Polygon.lineAt( _poly2, i - _poly1.length );\n let axis = new Pt( edge[0].y - edge[1].y, edge[1].x - edge[0].x ).unit(); // unit of a perpendicular vector\n let dist = Polygon._axisOverlap( _poly1, _poly2, axis );\n\n if ( dist > 0 ) {\n return null;\n } else if ( Math.abs( dist ) < minDist ) {\n // store intersected edge and a normal vector\n info.edge = edge;\n info.normal = axis;\n minDist = Math.abs( dist );\n info.which = ( i < _poly1.length ) ? 0 : 1;\n }\n } \n\n info.dist = minDist;\n\n // flip if neded to make sure vertex and edge are in corresponding polygons\n let b1 = ( info.which === 0 ) ? _poly2 : _poly1;\n let b2 = ( info.which === 0 ) ? _poly1 : _poly2;\n \n let c1 = Polygon.centroid( b1 );\n let c2 = Polygon.centroid( b2 );\n\n // direction\n let dir = c1.$subtract( c2 ).dot( info.normal );\n if ( dir < 0 ) info.normal.multiply( -1 );\n\n // find vertex at smallest distance\n let smallest = Number.MAX_SAFE_INTEGER; \n for ( let i = 0, len = b1.length; i < len; i++ ) {\n let d = info.normal.dot( b1[i].$subtract( c2 ) );\n if ( d < smallest ) {\n smallest = d;\n info.vertex = b1[i];\n }\n }\n\n return info;\n }\n\n\n /**\n * Find intersection points of 2 polygons by checking every side of both polygons. Performance may be slow for complex polygons.\n * @param poly1 a Group or an Iterable<Pt> representing a polygon \n * @param poly2 a Group or an Iterable<Pt> representing another polygon\n */\n static intersectPolygon2D( poly1:PtIterable, poly2:PtIterable ):Group {\n let _poly1 = Util.iterToArray( poly1 );\n let _poly2 = Util.iterToArray( poly2 );\n\n let lp = Polygon.lines( _poly1 );\n let g = [];\n for ( let i = 0, len = lp.length; i < len; i++ ) {\n let ins = Line.intersectPolygon2D( lp[i], _poly2, false );\n if ( ins ) g.push( ins );\n }\n return Util.flatten( g, true ) as Group;\n }\n\n\n /**\n * Get a bounding box for each polygon group, as well as a union bounding-box for all groups.\n * @param polys an Array/Iterable of (Groups or Iterables<Pt>)\n */\n static toRects( polys:Iterable<PtIterable> ):Group[] {\n let boxes = [];\n for ( let g of polys ) {\n boxes.push( Geom.boundingBox( g ) );\n }\n\n let merged = Util.flatten( boxes, false );\n boxes.unshift( Geom.boundingBox( merged ) );\n return boxes;\n }\n\n}\n\n\n\n/**\n * Curve class provides static functions to interpolate curves. A curve is usually represented as a Group of 3 or more control points.\n * You can use the static functions as-is, or apply the [`Group.op`](#link) or [`Pt.op`](#link) to enable functional programming.\n * See [Op guide](../guide/Op-0400.html) for details.\n */\nexport class Curve {\n\n /**\n * Get a precalculated coefficients per step. \n * @param steps number of steps\n */\n static getSteps( steps:number ):Group {\n let ts = new Group();\n for ( let i = 0; i <= steps; i++ ) {\n let t = i / steps;\n ts.push( new Pt( t * t * t, t * t, t, 1 ) );\n }\n return ts;\n }\n\n /**\n * Given an index for the starting position in a Pt group, get the control and/or end points of a curve segment.\n * @param pts a Group or an Iterable<PtLike>\n * @param index start index in `pts` array. Default is 0.\n * @param copyStart an optional boolean value to indicate if the start index should be used twice. Default is false.\n * @returns a group of 4 Pts\n */\n static controlPoints( pts:PtLikeIterable, index:number = 0, copyStart:boolean = false ):Group {\n let _pts = Util.iterToArray( pts );\n\n if ( index > _pts.length - 1 ) return new Group();\n let _index = ( i ) => ( i < _pts.length - 1 ) ? i : _pts.length - 1;\n\n let p0 = _pts[index];\n index = ( copyStart ) ? index : index + 1;\n\n // get points based on index\n return new Group(\n p0, _pts[ _index( index++ ) ],\n _pts[ _index( index++ ) ], _pts[ _index( index++ ) ]\n );\n }\n\n /**\n * Calulcate weighted sum to get the interpolated points.\n * @param ctrls anchors\n * @param params parameters\n */\n static _calcPt( ctrls:GroupLike, params:PtLike ):Pt {\n let x = ctrls.reduce( ( a, c, i ) => a + c.x * params[i], 0 );\n let y = ctrls.reduce( ( a, c, i ) => a + c.y * params[i], 0 );\n if ( ctrls[0].length > 2 ) {\n let z = ctrls.reduce( ( a, c, i ) => a + c.z * params[i], 0 );\n return new Pt( x, y, z );\n }\n return new Pt( x, y );\n }\n\n /**\n * Create a Catmull-Rom curve. Catmull-Rom is a kind of smooth-looking Cardinal curve.\n * @param pts a Group or an Iterable<PtLike>\n * @param steps the number of line segments per curve. Defaults to 10 steps\n * @returns a curve as a group of interpolated Pt\n */\n static catmullRom( pts:PtLikeIterable, steps:number = 10 ):Group {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 2 ) return new Group();\n\n let ps = new Group();\n let ts = Curve.getSteps( steps );\n\n // use first point twice\n let c = Curve.controlPoints( _pts, 0, true );\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.catmullRomStep( ts[i], c ) );\n }\n\n let k = 0;\n while ( k < _pts.length - 2 ) {\n let cp = Curve.controlPoints( _pts, k );\n if ( cp.length > 0 ) {\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.catmullRomStep( ts[i], cp ) );\n }\n k++;\n }\n }\n\n return ps;\n }\n\n\n /**\n * Interpolate to get a point on Catmull-Rom curve.\n * @param step the coefficients [t*t*t, t*t, t, 1]\n * @param ctrls a group of anchor Pts\n * @return an interpolated Pt on the curve\n */\n static catmullRomStep( step:Pt, ctrls:GroupLike ):Pt {\n /*\n * Basis Matrix (http://mrl.nyu.edu/~perlin/courses/fall2002/hw/12.html)\n * [-0.5, 1.5, -1.5, 0.5],\n * [ 1 , -2.5, 2 ,-0.5],\n * [-0.5, 0 , 0.5, 0 ],\n * [ 0 , 1 , 0 , 0 ]\n */\n\n let m = new Group(\n new Pt( -0.5, 1, -0.5, 0 ),\n new Pt( 1.5, -2.5, 0, 1 ),\n new Pt( -1.5, 2, 0.5, 0 ),\n new Pt( 0.5, -0.5, 0, 0 )\n );\n\n return Curve._calcPt( ctrls, Mat.multiply( [step], m, true )[0] );\n }\n\n /**\n * Create a Cardinal curve.\n * @param pts a Group or an Iterable<PtLike>\n * @param steps the number of line segments per curve. Defaults to 10 steps.\n * @param tension optional value between 0 to 1 to specify a \"tension\". Default to 0.5 which is the tension for Catmull-Rom curve.\n * @returns a curve as a group of interpolated Pt\n */\n static cardinal( pts:PtLikeIterable, steps:number = 10, tension = 0.5 ):Group {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 2 ) return new Group();\n\n let ps = new Group();\n let ts = Curve.getSteps( steps );\n\n // use first point twice\n let c = Curve.controlPoints( _pts, 0, true );\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.cardinalStep( ts[i], c, tension ) );\n }\n\n let k = 0;\n while ( k < _pts.length - 2 ) {\n let cp = Curve.controlPoints( _pts, k );\n if ( cp.length > 0 ) {\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.cardinalStep( ts[i], cp, tension ) );\n }\n k++;\n }\n }\n\n return ps;\n }\n\n /**\n * Interpolate to get a point on Cardinal curve.\n * @param step the coefficients [t*t*t, t*t, t, 1]\n * @param ctrls a group of anchor Pts\n * @param tension optional value between 0 to 1 to specify a \"tension\". Default to 0.5 which is the tension for Catmull-Rom curve\n * @return an interpolated Pt on the curve\n */\n static cardinalStep( step:Pt, ctrls:GroupLike, tension:number = 0.5 ):Pt {\n /*\n * Basis Matrix (http://algorithmist.wordpress.com/2009/10/06/cardinal-splines-part-4/)\n * [ -s 2-s s-2 s ]\n * [ 2s s-3 3-2s -s ]\n * [ -s 0 s 0 ]\n * [ 0 1 0 0 ]\n */\n\n let m = new Group(\n new Pt( -1, 2, -1, 0 ),\n new Pt( -1, 1, 0, 0 ),\n new Pt( 1, -2, 1, 0 ),\n new Pt( 1, -1, 0, 0 )\n );\n\n let h = Mat.multiply( [step], m, true )[0].multiply( tension );\n let h2 = ( 2 * step[0] - 3 * step[1] + 1 );\n let h3 = -2 * step[0] + 3 * step[1];\n\n let pt = Curve._calcPt( ctrls, h );\n\n pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;\n pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;\n if ( pt.length > 2 ) pt.z += h2 * ctrls[1].z + h3 * ctrls[2].z;\n\n return pt;\n }\n\n\n /**\n * Create a Bezier curve. In a cubic bezier curve, the first and 4th anchors are end-points, and 2nd and 3rd anchors are control-points.\n * @param pts a group of anchor Pt\n * @param steps the number of line segments per curve. Defaults to 10 steps.\n * @returns a curve as a group of interpolated Pt\n */\n static bezier( pts:GroupLike, steps:number = 10 ) {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 4 ) return new Group();\n\n let ps = new Group();\n let ts = Curve.getSteps( steps );\n\n let k = 0;\n while ( k < _pts.length - 3 ) {\n let c = Curve.controlPoints( _pts, k );\n if ( c.length > 0 ) {\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.bezierStep( ts[i], c ) );\n }\n\n // go to the next set of point, but assume current end pt is next start pt\n k += 3;\n }\n }\n\n return ps;\n }\n\n /**\n * Interpolate to get a point on a cubic Bezier curve.\n * @param step the coefficients [t*t*t, t*t, t, 1]\n * @param ctrls a group of anchor Pts\n * @return an interpolated Pt on the curve\n */\n static bezierStep( step:Pt, ctrls:GroupLike ) {\n /*\n * Bezier basis matrix\n * [ -1, 3, -3, 1 ]\n * [ 3, -6, 3, 0 ]\n * [ -3, 3, 0, 0 ]\n * [ 1, 0, 0, 0 ]\n */\n\n let m = new Group(\n new Pt( -1, 3, -3, 1 ),\n new Pt( 3, -6, 3, 0 ),\n new Pt( -3, 3, 0, 0 ),\n new Pt( 1, 0, 0, 0 )\n );\n\n return Curve._calcPt( ctrls, Mat.multiply( [step], m, true )[0] );\n }\n\n /**\n * Create a basis spline (NURBS) curve.\n * @param pts a group of anchor Pt\n * @param steps the number of line segments per curve. Defaults to 10 steps.\n * @param tension optional value between 0 to n to specify a \"tension\". Default is 1 which is the usual tension.\n * @returns a curve as a group of interpolated Pt\n */\n static bspline( pts:GroupLike, steps:number = 10, tension:number = 1 ):Group {\n let _pts = Util.iterToArray( pts );\n if ( _pts.length < 2 ) return new Group();\n\n let ps = new Group();\n let ts = Curve.getSteps( steps );\n\n\n let k = 0;\n while ( k < _pts.length - 3 ) {\n let c = Curve.controlPoints( _pts, k );\n if ( c.length > 0 ) {\n if ( tension !== 1 ) {\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.bsplineTensionStep( ts[i], c, tension ) );\n }\n } else {\n for ( let i = 0; i <= steps; i++ ) {\n ps.push( Curve.bsplineStep( ts[i], c ) );\n }\n }\n k++;\n }\n }\n\n return ps;\n }\n\n /**\n * Interpolate to get a point on a basis spline curve.\n * @param step the coefficients [t*t*t, t*t, t, 1]\n * @param ctrls a group of anchor Pts\n * @return an interpolated Pt on the curve\n */ \n static bsplineStep( step:Pt, ctrls:GroupLike ):Pt {\n /*\n * Basis matrix:\n * [ -1.0/6.0, 3.0/6.0, -3.0/6.0, 1.0/6.0 ],\n * [ 3.0/6.0, -6.0/6.0, 3.0/6.0, 0.0 ],\n * [ -3.0/6.0, 0.0, 3.0/6.0, 0.0 ],\n * [ 1.0/6.0, 4.0/6.0, 1.0/6.0, 0.0 ]\n */\n\n let m = new Group(\n new Pt( -0.16666666666666666, 0.5, -0.5, 0.16666666666666666 ),\n new Pt( 0.5, -1, 0, 0.6666666666666666 ),\n new Pt( -0.5, 0.5, 0.5, 0.16666666666666666 ),\n new Pt( 0.16666666666666666, 0, 0, 0 )\n );\n\n return Curve._calcPt( ctrls, Mat.multiply( [step], m, true )[0] );\n }\n\n /**\n * Interpolate to get a point on a basis spline curve with tension.\n * @param step the coefficients [t*t*t, t*t, t, 1]\n * @param ctrls a group of anchor Pts\n * @param tension optional value between 0 to n to specify a \"tension\". Default to 1 which is the usual tension.\n * @return an interpolated Pt on the curve\n */ \n static bsplineTensionStep( step:Pt, ctrls:GroupLike, tension:number = 1 ):Pt {\n /*\n * Basis matrix:\n * [ -1/6a, 2 - 1.5a, 1.5a - 2, 1/6a ]\n * [ 0.5a, 2a-3, 3-2.5a 0 ]\n * [ -0.5a, 0, 0.5a, 0 ]\n * [ 1/6a, 1 - 1/3a, 1/6a, 0 ]\n */\n\n let m = new Group(\n new Pt( -0.16666666666666666, 0.5, -0.5, 0.16666666666666666 ),\n new Pt( -1.5, 2, 0, -0.3333333333333333 ),\n new Pt( 1.5, -2.5, 0.5, 0.16666666666666666 ),\n new Pt( 0.16666666666666666, 0, 0, 0 )\n );\n\n let h = Mat.multiply( [step], m, true )[0].multiply( tension );\n let h2 = ( 2 * step[0] - 3 * step[1] + 1 );\n let h3 = -2 * step[0] + 3 * step[1];\n\n let pt = Curve._calcPt( ctrls, h );\n\n pt.x += h2 * ctrls[1].x + h3 * ctrls[2].x;\n pt.y += h2 * ctrls[1].y + h3 * ctrls[2].y;\n if ( pt.length > 2 ) pt.z += h2 * ctrls[1].z + h3 * ctrls[2].z;\n\n return pt;\n } \n\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Pt, Group} from \"./Pt\";\nimport {Line} from \"./Op\";\nimport {PtLike, GroupLike} from \"./Types\";\n\n\n/**\n * Vec provides various static functions for vector operations. It's not fully optimized but good enough to use.\n */\nexport class Vec {\n\n /**\n * Add `b` to vector `a`.\n * @returns vector `a`\n */\n static add( a:PtLike, b:PtLike | number ):PtLike {\n if ( typeof b == \"number\" ) {\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] += b;\n } else {\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] += b[i] || 0;\n }\n return a;\n }\n\n /**\n * Subtract `b` from vector `a`.\n * @returns vector `a`\n */\n static subtract( a:PtLike, b:PtLike | number ):PtLike {\n if ( typeof b == \"number\" ) {\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] -= b;\n } else {\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] -= b[i] || 0;\n }\n return a;\n }\n\n /**\n * Multiply `b` with vector `a`.\n * @returns vector `a`\n */\n static multiply( a:PtLike, b:PtLike | number ):PtLike {\n if ( typeof b == \"number\" ) {\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] *= b;\n } else {\n if ( a.length != b.length ) {\n throw new Error( `Cannot do element-wise multiply since the array lengths don't match: ${a.toString()} multiply-with ${b.toString()}` );\n }\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] *= b[i];\n }\n return a;\n }\n\n\n /**\n * Divide `a` over `b`.\n * @returns vector `a`\n */\n static divide( a:PtLike, b:PtLike | number ):PtLike {\n if ( typeof b == \"number\" ) {\n if ( b === 0 ) throw new Error( \"Cannot divide by zero\" );\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] /= b;\n } else {\n if ( a.length != b.length ) {\n throw new Error( `Cannot do element-wise divide since the array lengths don't match. ${a.toString()} divide-by ${b.toString()}` );\n }\n for ( let i = 0, len = a.length; i < len; i++ ) a[i] /= b[i];\n }\n return a;\n }\n\n\n /**\n * Dot product of `a` and `b`.\n */\n static dot( a:PtLike, b:PtLike ):number {\n if ( a.length != b.length ) throw new Error( \"Array lengths don't match\" );\n let d = 0;\n for ( let i = 0, len = a.length; i < len; i++ ) {\n d += a[i] * b[i];\n }\n return d;\n } \n\n \n /**\n * 2D cross product of `a` and `b`.\n */\n static cross2D( a:PtLike, b:PtLike ):number {\n return a[0] * b[1] - a[1] * b[0];\n }\n\n /**\n * 3D Cross product of `a` and `b`.\n */\n static cross( a:PtLike, b:PtLike ):Pt {\n return new Pt( ( a[1] * b[2] - a[2] * b[1] ), ( a[2] * b[0] - a[0] * b[2] ), ( a[0] * b[1] - a[1] * b[0] ) );\n }\n\n\n /**\n * Magnitude of `a`.\n */\n static magnitude( a:PtLike ):number {\n return Math.sqrt( Vec.dot( a, a ) );\n }\n\n\n /**\n * Unit vector of `a`. If magnitude of `a` is already known, pass it in the second paramter to optimize calculation.\n */\n static unit( a:PtLike, magnitude:number = undefined ):PtLike {\n const m = ( magnitude === undefined ) ? Vec.magnitude( a ) : magnitude;\n if ( m === 0 ) return Pt.make( a.length );\n return Vec.divide( a, m );\n }\n\n\n /**\n * Set `a` to its absolute value in each dimension.\n * @returns vector `a`\n */\n static abs( a:PtLike ):PtLike {\n return Vec.map( a, Math.abs );\n }\n\n\n /**\n * Set `a` to its floor value in each dimension.\n * @returns vector `a`\n */\n static floor( a:PtLike ):PtLike {\n return Vec.map( a, Math.floor );\n }\n\n\n /**\n * Set `a` to its ceiling value in each dimension.\n * @returns vector `a`\n */\n static ceil( a:PtLike ):PtLike {\n return Vec.map( a, Math.ceil );\n }\n\n\n /**\n * Set `a` to its rounded value in each dimension.\n * @returns vector `a`\n */\n static round( a:PtLike ):PtLike {\n return Vec.map( a, Math.round );\n }\n\n \n /**\n * Find the max value within a vector's dimensions.\n * @returns an object with `value` and `index` that specifies the max value and its corresponding dimension.\n */\n static max( a:PtLike ):{value, index} {\n let m = Number.MIN_VALUE;\n let index = 0;\n for ( let i = 0, len = a.length; i < len; i++ ) {\n m = Math.max( m, a[i] );\n if ( m === a[i] ) index = i;\n }\n return {value: m, index: index};\n }\n\n\n /**\n * Find the min value within a vector's dimensions.\n * @returns an object with `value` and `index` that specifies the min value and its corresponding dimension.\n */\n static min( a:PtLike ):{value, index} {\n let m = Number.MAX_VALUE;\n let index = 0;\n for ( let i = 0, len = a.length; i < len; i++ ) {\n m = Math.min( m, a[i] );\n if ( m === a[i] ) index = i;\n }\n return {value: m, index: index};\n }\n\n\n /**\n * Add up all the dimensions' values and returns a scalar of the sum.\n */\n static sum( a:PtLike ):number {\n let s = 0;\n for ( let i = 0, len = a.length; i < len; i++ ) s += a[i];\n return s;\n }\n\n\n /**\n * Given a mapping function, update `a`'s value in each dimension.\n * @returns vector `a`\n */\n static map( a:PtLike, fn:( n:number, index:number, arr ) => number ):PtLike {\n for ( let i = 0, len = a.length; i < len; i++ ) {\n a[i] = fn( a[i], i, a );\n }\n return a;\n }\n \n}\n\n\n/**\n * Mat provides various static functions for matrix operations as well as a convenient way to chain a 3x3 transformation matrix. It's not fully optimized but good enough to use.\n */\nexport class Mat {\n\n protected _33: GroupLike;\n\n constructor() {\n this.reset();\n }\n\n\n /**\n * Get the current value of its stored 3x3 matrix\n */\n get value(): GroupLike {\n return this._33;\n }\n\n\n /**\n * Convert the value of its stored 3x3 matrix to a 2D [`DOMMatrix`](https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix) instance\n */\n get domMatrix(): DOMMatrix {\n return new DOMMatrix( Mat.toDOMMatrix( this._33 ) ) ;\n }\n\n\n /**\n * Reset the internal 3x3 matrix to its identity\n */\n reset() {\n this._33 = Mat.scale2DMatrix( 1,1 );\n }\n\n\n /**\n * Scale the internal 3x3 matrix. You can chain this function with other related functions.\n * @param val [x, y] scale factors\n * @param at Optional origin location to scale from. \n */\n scale2D( val:PtLike, at:PtLike = [0,0] ): this {\n const m = Mat.scaleAt2DMatrix( val[0] || 1, val[1] || 1, at );\n this._33 = Mat.multiply( this._33, m );\n return this;\n }\n\n\n /**\n * Scale the internal 3x3 matrix. You can chain this function with other related functions.\n * @param ang Angle of rotation\n * @param at Optional origin location to rotate from. \n */\n rotate2D( ang:number, at:PtLike = [0,0] ): this {\n const m = Mat.rotateAt2DMatrix( Math.cos( ang ), Math.sin( ang ), at );\n this._33 = Mat.multiply( this._33, m );\n return this;\n }\n\n\n /**\n * Translate the internal 3x3 matrix. You can chain this function with other related functions.\n * @param val [x, y] offset values\n */\n translate2D( val:PtLike ): this {\n const m = Mat.translate2DMatrix( val[0] || 0, val[1] || 0 );\n this._33 = Mat.multiply( this._33, m );\n return this;\n }\n\n\n /**\n * Shear the internal 3x3 matrix. You can chain this function with other related functions.\n * @param val [x, y] shear factors (before tan() operation)\n * @param at Optional origin location to scale from. \n */\n shear2D( val:PtLike, at:PtLike = [0,0] ): this {\n const m = Mat.shearAt2DMatrix( Math.tan( val[0] || 0 ), Math.tan( val[1] || 1 ), at );\n this._33 = Mat.multiply( this._33, m );\n return this;\n }\n\n\n /**\n * Matrix addition. Matrices should have the same rows and columns.\n * @param a a group of Pt\n * @param b a scalar number, an array of numeric arrays, or a group of Pt\n * @returns a new group with the same rows and columns as a and b\n */\n static add( a:GroupLike, b:GroupLike | number[][] | number ):Group {\n if ( typeof b != \"number\" ) {\n if ( a[0].length != b[0].length ) throw new Error( \"Cannot add matrix if rows' and columns' size don't match.\" );\n if ( a.length != b.length ) throw new Error( \"Cannot add matrix if rows' and columns' size don't match.\" );\n }\n\n const g = new Group();\n const isNum = typeof b == \"number\"; \n for ( let i = 0, len = a.length; i < len; i++ ) {\n g.push( a[i].$add( ( isNum ) ? b : b[i] ) );\n }\n\n return g;\n }\n\n\n /**\n * Matrix multiplication.\n * @param a a Group of M Pts, each with K dimensions (M-rows, K-columns)\n * @param b a scalar number, an array of numeric arrays, or a Group of K Pts, each with N dimensions (K-rows, N-columns) -- or if transposed is true, then N Pts with K dimensions\n * @param transposed (Only applicable if it's not elementwise multiplication) If true, then a and b's columns should match (ie, each Pt should have the same dimensions). Default is `false`.\n * @param elementwise if true, then the multiplication is done element-wise. Default is `false`.\n * @returns If not elementwise, this will return a new group with M Pt, each with N dimensions (M-rows, N-columns).\n */\n static multiply( a:GroupLike, b:GroupLike | number[][] | number, transposed:boolean = false, elementwise:boolean = false ):Group {\n \n const g = new Group();\n\n if ( typeof b != \"number\" ) {\n\n if ( elementwise ) {\n if ( a.length != b.length ) throw new Error( \"Cannot multiply matrix element-wise because the matrices' sizes don't match.\" );\n for ( let ai = 0, alen = a.length; ai < alen; ai++ ) {\n g.push( a[ai].$multiply( b[ai] ) );\n }\n\n } else {\n \n if ( !transposed && a[0].length != b.length ) throw new Error( \"Cannot multiply matrix if rows in matrix-a don't match columns in matrix-b.\" );\n if ( transposed && a[0].length != b[0].length ) throw new Error( \"Cannot multiply matrix if transposed and the columns in both matrices don't match.\" );\n\n if ( !transposed ) b = Mat.transpose( b );\n\n for ( let ai = 0, alen = a.length; ai < alen; ai++ ) {\n const p = Pt.make( b.length, 0 );\n for ( let bi = 0, blen = b.length; bi < blen; bi++ ) {\n p[bi] = Vec.dot( a[ai], b[bi] );\n }\n g.push( p );\n }\n }\n\n } else {\n for ( let ai = 0, alen = a.length; ai < alen; ai++ ) {\n g.push( a[ai].$multiply( b ) );\n }\n }\n\n return g;\n }\n\n\n /**\n * Zip one slice of an array of Pts. For example, if the input `g` are organized in rows, then this function will take the values in a specific column.\n * @param g a group of Pt\n * @param idx index to zip at\n * @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.\n */\n static zipSlice( g:GroupLike | number[][], index:number, defaultValue:number | boolean = false ):Pt {\n const z = [];\n for ( let i = 0, len = g.length; i < len; i++ ) {\n if ( g[i].length - 1 < index && defaultValue === false ) throw `Index ${index} is out of bounds`;\n z.push( g[i][index] || defaultValue );\n }\n return new Pt( z );\n }\n\n\n /**\n * Zip a group of Pt. For example, `[[1,2],[3,4],[5,6]]` will become `[[1,3,5],[2,4,6]]`.\n * @param g a group of Pt\n * @param defaultValue a default value to fill if index out of bound. If not provided, it will throw an error instead.\n * @param useLongest If true, find the longest list of values in a Pt and use its length for zipping. Default is false, which uses the first item's length for zipping.\n */\n static zip( g:GroupLike | number[][], defaultValue:number | boolean = false, useLongest = false ):Group {\n const ps = new Group();\n const len:number = ( useLongest ) ? ( g as Array<number[] | Pt> ).reduce( ( a,b ) => Math.max( a, b.length ), 0 ) : g[0].length;\n for ( let i = 0; i < len; i++ ) {\n ps.push( Mat.zipSlice( g, i, defaultValue ) );\n }\n return ps;\n }\n\n\n /**\n * Same as `zip` function.\n */\n static transpose( g:GroupLike | number[][], defaultValue:number | boolean = false, useLongest = false ):Group {\n return Mat.zip( g, defaultValue, useLongest );\n }\n\n\n static toDOMMatrix( m:GroupLike | number[][] ) { \n return [m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]];\n }\n\n\n /**\n * Transform a 2D point given a 2x3 or 3x3 matrix.\n * @param pt a Pt to be transformed\n * @param m 2x3 or 3x3 matrix\n * @returns a new transformed Pt\n */\n static transform2D( pt:PtLike, m:GroupLike | number[][] ):Pt {\n const x = pt[0] * m[0][0] + pt[1] * m[1][0] + m[2][0];\n const y = pt[0] * m[0][1] + pt[1] * m[1][1] + m[2][1];\n return new Pt( x, y );\n }\n\n\n /**\n * Get a scale matrix for use in `transform2D`.\n */\n static scale2DMatrix( x:number, y:number ):GroupLike {\n return new Group(\n new Pt( x, 0, 0 ),\n new Pt( 0, y, 0 ),\n new Pt( 0, 0, 1 )\n );\n }\n\n\n /**\n * Get a rotate matrix for use in `transform2D`.\n */\n static rotate2DMatrix( cosA:number, sinA:number ):GroupLike {\n return new Group(\n new Pt( cosA, sinA, 0 ),\n new Pt( -sinA, cosA, 0, ),\n new Pt( 0, 0, 1 )\n );\n }\n\n\n /**\n * Get a shear matrix for use in `transform2D`.\n */\n static shear2DMatrix( tanX:number, tanY:number ):GroupLike {\n return new Group(\n new Pt( 1, tanX, 0 ),\n new Pt( tanY, 1, 0 ),\n new Pt( 0, 0, 1 )\n );\n }\n\n\n /**\n * Get a translate matrix for use in `transform2D`.\n */\n static translate2DMatrix( x:number, y:number ):GroupLike {\n return new Group(\n new Pt( 1, 0, 0 ),\n new Pt( 0, 1, 0 ),\n new Pt( x, y, 1 )\n );\n }\n\n\n /**\n * Get a matrix to scale a point from an origin point. For use in `transform2D`.\n */\n static scaleAt2DMatrix( sx:number, sy:number, at:PtLike ):GroupLike {\n const m = Mat.scale2DMatrix( sx, sy );\n m[2][0] = -at[0] * sx + at[0];\n m[2][1] = -at[1] * sy + at[1];\n return m;\n }\n\n\n /**\n * Get a matrix to rotate a point from an origin point. For use in `transform2D`.\n */\n static rotateAt2DMatrix( cosA:number, sinA:number, at:PtLike ):GroupLike {\n const m = Mat.rotate2DMatrix( cosA, sinA );\n m[2][0] = at[0] * ( 1 - cosA ) + at[1] * sinA;\n m[2][1] = at[1] * ( 1 - cosA ) - at[0] * sinA;\n return m;\n }\n\n\n /**\n * Get a matrix to shear a point from an origin point. For use in `transform2D`.\n */\n static shearAt2DMatrix( tanX:number, tanY:number, at:PtLike ):GroupLike {\n const m = Mat.shear2DMatrix( tanX, tanY );\n m[2][0] = -at[1] * tanY;\n m[2][1] = -at[0] * tanX;\n return m;\n }\n\n\n /**\n * Get a matrix to reflect a point along a line. For use in `transform2D`.\n * @param p1 first end point to define the reflection line\n * @param p1 second end point to define the reflection line\n */\n static reflectAt2DMatrix( p1:PtLike, p2:PtLike ) {\n const intercept = Line.intercept( p1, p2 );\n \n if ( intercept == undefined ) {\n return [\n new Pt( [-1, 0, 0] ),\n new Pt( [0, 1, 0] ),\n new Pt( [p1[0] + p2[0], 0, 1] ) \n ];\n } else {\n\n const yi = intercept.yi;\n const ang2 = Math.atan( intercept.slope ) * 2;\n const cosA = Math.cos( ang2 );\n const sinA = Math.sin( ang2 );\n \n return [\n new Pt( [cosA, sinA, 0] ),\n new Pt( [sinA, -cosA, 0] ),\n new Pt( [-yi * sinA, yi + yi * cosA, 1] )\n ];\n }\n }\n\n \n}","'use strict';\r\n/* This code has been written by Steve Gibson and can be found here:\r\n *\r\n * https://www.grc.com/otg/uheprng.htm\r\n * \r\n * The code has been converted to typescript and unused functions have \r\n * been removed\r\n */\r\n\r\n/*\t============================================================================\r\n Gibson Research Corporation\r\n UHEPRNG - Ultra High Entropy Pseudo-Random Number Generator\r\n ============================================================================\r\n LICENSE AND COPYRIGHT: THIS CODE IS HEREBY RELEASED INTO THE PUBLIC DOMAIN\r\n Gibson Research Corporation releases and disclaims ALL RIGHTS AND TITLE IN\r\n THIS CODE OR ANY DERIVATIVES. Anyone may be freely use it for any purpose.\r\n ============================================================================\r\n This is GRC's cryptographically strong PRNG (pseudo-random number generator)\r\n for JavaScript. It is driven by 1536 bits of entropy, stored in an array of\r\n 48, 32-bit JavaScript variables. Since many applications of this generator,\r\n including ours with the \"Off The Grid\" Latin Square generator, may require\r\n the deteriministic re-generation of a sequence of PRNs, this PRNG's initial\r\n entropic state can be read and written as a static whole, and incrementally\r\n evolved by pouring new source entropy into the generator's internal state.\r\n ----------------------------------------------------------------------------\r\n ENDLESS THANKS are due Johannes Baagoe for his careful development of highly\r\n robust JavaScript implementations of JS PRNGs. This work was based upon his\r\n JavaScript \"Alea\" PRNG which is based upon the extremely robust Multiply-\r\n With-Carry (MWC) PRNG invented by George Marsaglia. MWC Algorithm References:\r\n http://www.GRC.com/otg/Marsaglia_PRNGs.pdf\r\n http://www.GRC.com/otg/Marsaglia_MWC_Generators.pdf\r\n ----------------------------------------------------------------------------\r\n The quality of this algorithm's pseudo-random numbers have been verified by\r\n multiple independent researchers. It handily passes the fermilab.ch tests as\r\n well as the \"diehard\" and \"dieharder\" test suites. For individuals wishing\r\n to further verify the quality of this algorithm's pseudo-random numbers, a\r\n 256-megabyte file of this algorithm's output may be downloaded from GRC.com,\r\n and a Microsoft Windows scripting host (WSH) version of this algorithm may be\r\n downloaded and run from the Windows command prompt to generate unique files\r\n of any size:\r\n The Fermilab \"ENT\" tests: http://fourmilab.ch/random/\r\n The 256-megabyte sample PRN file at GRC: https://www.GRC.com/otg/uheprng.bin\r\n The Windows scripting host version: https://www.GRC.com/otg/wsh-uheprng.js\r\n ----------------------------------------------------------------------------\r\n Qualifying MWC multipliers are: 187884, 686118, 898134, 1104375, 1250205,\r\n 1460910 and 1768863. (We use the largest one that's < 2^21)\r\n ============================================================================ \r\n*/\r\n\r\n/*\t============================================================================\r\n This is based upon Johannes Baagoe's carefully designed and efficient hash\r\n function for use with JavaScript. It has a proven \"avalanche\" effect such\r\n that every bit of the input affects every bit of the output 50% of the time,\r\n which is good.\tSee: http://baagoe.com/en/RandomMusings/hash/avalanche.xhtml\r\n ============================================================================\r\n*/\r\nfunction Mash() {\r\n let n = 0xefc8249d;\r\n let mash = function ( data?: string ) {\r\n if ( data ) {\r\n data = data.toString();\r\n for ( let i = 0; i < data.length; i++ ) {\r\n n += data.charCodeAt( i );\r\n let h = 0.02519603282416938 * n;\r\n n = h >>> 0;\r\n h -= n;\r\n h *= n;\r\n n = h >>> 0;\r\n h -= n;\r\n n += h * 0x100000000; // 2^32\r\n }\r\n return ( n >>> 0 ) * 2.3283064365386963e-10; // 2^-32\r\n } else n = 0xefc8249d;\r\n };\r\n return mash;\r\n}\r\n\r\nexport default function( seed: string ) {\r\n let o = 48; // set the 'order' number of ENTROPY-holding 32-bit values\r\n let c = 1; // init the 'carry' used by the multiply-with-carry (MWC) algorithm\r\n let p = o; // init the 'phase' (max-1) of the intermediate variable pointer\r\n let s = new Array( o ); // declare our intermediate variables array\r\n let i: number,\r\n j: number,\r\n k = 0; // general purpose locals\r\n\r\n // when our \"uheprng\" is initially invoked our PRNG state is initialized from the\r\n // browser's own local PRNG. This is okay since although its generator might not\r\n // be wonderful, it's useful for establishing large startup entropy for our usage.\r\n let mash = Mash(); // get a pointer to our high-performance \"Mash\" hash\r\n for ( i = 0; i < o; i++ ) s[i] = mash( Math.random().toString() ); // fill the array with initial mash hash values\r\n\r\n // if we want to provide a deterministic startup context for our PRNG,\r\n // but without directly setting the internal state variables, this allows\r\n // us to initialize the mash hash and PRNG's internal state before providing\r\n // some hashing input\r\n function initState() {\r\n mash(); // pass a null arg to force mash hash to init\r\n for ( i = 0; i < o; i++ ) s[i] = mash( ' ' ); // fill the array with initial mash hash values\r\n c = 1; // init our multiply-with-carry carry\r\n p = o; // init our phase\r\n }\r\n\r\n // this EXPORTED \"clean string\" function removes leading and trailing spaces and non-printing\r\n // control characters, including any embedded carriage-return (CR) and line-feed (LF) characters,\r\n // from any string it is handed. this is also used by the 'hashstring' function (below) to help\r\n // users always obtain the same EFFECTIVE uheprng seeding key.\r\n function cleanString( inStr: string ) {\r\n inStr = inStr.replace( /(^\\s*)|(\\s*$)/gi, '' ); // remove any/all leading spaces\r\n inStr = inStr.replace( /[\\x00-\\x1F]/gi, '' ); // remove any/all control characters\r\n inStr = inStr.replace( /\\n /, '\\n' ); // remove any/all trailing spaces\r\n return inStr; // return the cleaned up result\r\n }\r\n\r\n // this EXPORTED \"hash string\" function hashes the provided character string after first removing\r\n // any leading or trailing spaces and ignoring any embedded carriage returns (CR) or Line Feeds (LF)\r\n function hashString( inStr: string ) {\r\n inStr = cleanString( inStr );\r\n mash( inStr ); // use the string to evolve the 'mash' state\r\n for ( i = 0; i < inStr.length; i++ ) {\r\n // scan through the characters in our string\r\n k = inStr.charCodeAt( i ); // get the character code at the location\r\n for ( j = 0; j < o; j++ ) {\r\n // \t\"mash\" it into the UHEPRNG state\r\n s[j] -= mash( k.toString() );\r\n if ( s[j] < 0 ) s[j] += 1;\r\n }\r\n }\r\n }\r\n\r\n initState();\r\n hashString( seed );\r\n\r\n return {\r\n /**\r\n * this (not anymore) PRIVATE (internal access only) function is the heart of the multiply-with-carry\r\n * (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a\r\n * 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default\r\n * [0-1] return function, and by the random 'string(n)' function which returns 'n'\r\n * characters from 33 to 126.\r\n * @returns a number between 0.0 and 1.0\r\n */\r\n random() {\r\n if ( ++p >= o ) p = 0;\r\n let t = 1768863 * s[p] + c * 2.3283064365386963e-10; // 2^-32\r\n return ( s[p] = t - ( c = t | 0 ) );\r\n }\r\n };\r\n}\r\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Pt, Group} from \"./Pt\";\nimport { Rectangle, Circle, Polygon } from \"./Op\";\nimport {UIHandler, GroupLike, PtLike, PtLikeIterable} from \"./Types\";\n\n\n/**\n * **[Experimental]** A set of string constatns to represent different UI types, for use in [`UI`](#link) instances.\n */\nexport const UIShape = {\n rectangle: \"rectangle\", circle: \"circle\", polygon: \"polygon\", polyline: \"polyline\", line: \"line\"\n};\n\n\n/**\n * **[Experimental]** A set of string constants to represent different UI event types.\n */\nexport const UIPointerActions = {\n up: \"up\", down: \"down\", move: \"move\", \n drag: \"drag\", uidrag: \"uidrag\", drop: \"drop\", uidrop: \"uidrop\", \n over: \"over\", out: \"out\", enter: \"enter\", leave: \"leave\", click: \"click\", \n keydown: 'keydown', keyup: 'keyup',\n pointerdown: \"pointerdown\", pointerup: \"pointerup\",\n contextmenu: \"contextmenu\", all: \"all\"\n};\n\n\n\n/**\n * **[Experimental]** An abstract class that represents an UI element. It wraps a [`Group`](#link) and supports UI event handling. \n * Extend this class to create custom UI elements.\n */\nexport class UI {\n _group: Group;\n _shape: string;\n\n protected static _counter:number = 0;\n protected _id:string;\n protected _actions: {[type:string]: UIHandler[] };\n protected _states: {[key:string]: any};\n\n protected _holds = new Map<number, string>();\n\n /**\n * Create an UI element. You may also create a new UI using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).\n * @param group a Group or an Iterable<PtLike> that defines the UI's appearance\n * @param shape specifies the shape of the Group\n * @param states optional a state object keep track of custom states for this UI\n * @param id optional id string\n */\n constructor( group:PtLikeIterable, shape:string, states:{[key:string]: any} = {}, id?:string ) {\n this._group = Group.fromArray( group );\n this._shape = shape;\n this._id = id === undefined ? `ui_${( UI._counter++ )}` : id;\n this._states = states;\n this._actions = {};\n }\n\n\n /**\n * A static helper function to create a Rectangle UI.\n * @param group a Group or an Iterable<PtLike> with 2 Pt representing a rectangle\n * @param states optional a state object keep track of custom states for this UI\n * @param id optional id string\n */\n static fromRectangle( group:PtLikeIterable, states: {}, id?:string ):UI {\n return new this( group, UIShape.rectangle, states, id );\n }\n\n\n /**\n * A static helper function to create a Circle UI.\n * @param group a Group or an Iterable<PtLike> with 2 Pt representing a circle\n * @param states optional a state object keep track of custom states for this UI\n * @param id optional id string\n */\n static fromCircle( group:PtLikeIterable, states: {}, id?:string ):UI {\n return new this( group, UIShape.circle, states, id );\n }\n\n\n /**\n * A static helper function to create a Polygon UI.\n * @param group a Group or an Iterable<PtLike> representing a polygon\n * @param states optional a state object keep track of custom states for this UI\n * @param id optional id string\n */\n static fromPolygon( group:PtLikeIterable, states: {}, id?:string ):UI {\n return new this( group, UIShape.polygon, states, id );\n }\n\n\n /**\n * A static helper function to create a new UI based on another UI.\n * @param ui base UI\n * @param states optional a state object keep track of custom states for this UI\n */\n static fromUI( ui:UI, states?:object, id?:string ):UI {\n return new this( ui.group, ui.shape, states || ui._states, id );\n }\n\n\n /**\n * An unique id of the UI.\n */\n get id():string { return this._id; }\n set id( d:string ) { this._id = d; } \n\n\n /**\n * A group of Pts that defines this UI's shape.\n */\n get group():Group { return this._group; }\n set group( d:Group ) { this._group = d; } \n\n\n /**\n * A string that describes this UI's shape.\n */\n get shape():string { return this._shape; }\n set shape( d:string ) { this._shape = d; } \n\n\n /**\n * Get and/or set a specific UI state.\n * @param key state's name\n * @param value optionally set a new value for this state.key\n * @param if `value` is changed, return this instance. Otherwise, return the value of the specific key.\n */\n state( key:string, value?:any ):any {\n if ( !key ) return null;\n if ( value !== undefined ) {\n this._states[key] = value;\n return this; \n }\n return this._states[key];\n }\n\n\n /**\n * Add an event handler. Remember this UI will also need to be tracked for events via `UI.track`.\n * @param type event type\n * @param fn a [`UIHandler`](#link) callback function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @returns an id number that reference to this handler, for use in [`UI.off`](#link)\n */\n on( type:string, fn:UIHandler ):number {\n if ( !this._actions[type] ) this._actions[type] = [];\n return UI._addHandler( this._actions[type], fn );\n }\n\n\n /**\n * Remove an event handler.\n * @param type event type\n * @param which an ID number returned by [`UI.on`](#link). If this is not defined, all handlers in this type will be removed.\n * @param fn a [`UIHandler`](#link) function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n */\n off( type:string, which?:number ):boolean {\n if ( !this._actions[type] ) return false;\n if ( which === undefined ) {\n delete this._actions[type];\n return true;\n } else {\n return UI._removeHandler( this._actions[type], which );\n }\n }\n\n\n /**\n * Listen for UI events and trigger action handlers.\n * @param type an action type. Can be one of UIPointerActions or a custom one.\n * @param p a point to check\n * @param evt a MouseEvent emitted by the browser (See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent))\n */\n listen( type:string, p:PtLike, evt:MouseEvent ):boolean {\n if ( this._actions[type] !== undefined ) {\n \n if ( this._within( p ) || Array.from( this._holds.values() ).indexOf( type ) >= 0 ) {\n UI._trigger( this._actions[type], this, p, type, evt );\n return true;\n } else if ( this._actions['all'] ) { // listen for all regardless of trigger\n UI._trigger( this._actions['all'], this, p, type, evt );\n return true;\n }\n }\n return false;\n }\n\n\n /**\n * Continue to keep track of an actions even if it's not within this UI. Useful for hover-leave and drag-outside.\n * @param type a string defined in [`UIPointerActions`](#link)\n */\n protected hold( type:string ):number {\n let newKey = Math.max( 0, ...Array.from( this._holds.keys() ) ) + 1;\n this._holds.set( newKey, type );\n return newKey;\n }\n\n\n /**\n * Stop keeping track of this action\n * @param key an id returned by the [`UI.hold`](#link) function\n */\n protected unhold( key?:number ):void {\n if ( key !== undefined ) {\n this._holds.delete( key );\n } else {\n this._holds.clear();\n }\n }\n\n\n /**\n * A static function to listen for a list of UIs. See also [`UI.listen`](#link).\n * @param uis an array of UI\n * @param type an action type. Can be one of `UIPointerActions` or a custom one.\n * @param p a point to check\n * @param evt a MouseEvent emitted by the browser (See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent))\n */\n static track( uis:UI[], type:string, p:PtLike, evt:MouseEvent ):void {\n for ( let i = 0, len = uis.length; i < len; i++ ) {\n uis[i].listen( type, p, evt );\n }\n }\n\n\n /**\n * Take a custom render function to render this UI.\n * @param fn a render function\n */\n render( fn:( group:Group, states:{[key:string]: any} ) => void ):void {\n fn( this._group, this._states );\n }\n\n\n /**\n * Returns a string representation of this UI\n */\n toString():string {\n return `UI ${this.group.toString}`;\n }\n\n /**\n * Check intersection using a specific function based on the shape of the UI.\n * @param p a point to check\n * @returns a boolean to indicate if the event should be triggered\n */\n protected _within( p:PtLike ):boolean {\n let fn = null;\n if ( this._shape === UIShape.rectangle ) {\n fn = Rectangle.withinBound;\n } else if ( this._shape === UIShape.circle ) {\n fn = Circle.withinBound;\n } else if ( this._shape === UIShape.polygon ) {\n fn = Polygon.hasIntersectPoint;\n } else {\n return false;\n }\n\n return fn( this._group, p );\n }\n\n\n /**\n * Static function to trigger an array of UIHandlers\n */\n protected static _trigger( fns:UIHandler[], target:UI, pt:PtLike, type:string, evt:MouseEvent ) {\n if ( fns ) {\n for ( let i = 0, len = fns.length; i < len; i++ ) {\n if ( fns[i] ) fns[i]( target, pt, type, evt );\n }\n }\n }\n\n\n /**\n * Static function to add a new handler to an array store of UIHandlers.\n */\n protected static _addHandler( fns:UIHandler[], fn:UIHandler ):number {\n if ( fn ) {\n fns.push( fn );\n return fns.length - 1;\n } else {\n return -1;\n }\n }\n\n\n /**\n * Static function to remove an existing handler from an array store of UIHandlers.\n */\n protected static _removeHandler( fns:UIHandler[], index:number ):boolean {\n if ( index >= 0 && index < fns.length ) {\n let temp = fns.length;\n fns.splice( index, 1 );\n return ( temp > fns.length );\n } else {\n return false;\n }\n }\n\n}\n\n\n/**\n * **[Experimental]** A simple button that extends [`UI`](#link) to track clicks and hovers.\n */\nexport class UIButton extends UI {\n\n private _hoverID:number = -1;\n\n /**\n * Create an UIButton. A button has 2 states, \"clicks\" (number) and \"hover\" (boolean), which you can access through [`UI.state`](#link) function. You may also create a new UIButton using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).\n * @param group a Group or an Iterable<PtLike> that defines the UI's appearance\n * @param shape specifies the shape of the Group\n * @param states Optional default state object\n * @param id Optional id string\n */\n constructor( group:PtLikeIterable, shape:string, states:{[key:string]: any} = {}, id?:string ) {\n super( group, shape, states, id );\n \n if ( states.hover === undefined ) this._states['hover'] = false;\n if ( states.clicks === undefined ) this._states['clicks'] = 0;\n\n const UA = UIPointerActions;\n\n // listen for clicks when mouse up and increment clicks \n this.on( UA.up, ( target:UI, pt:PtLike, type:string, evt:MouseEvent ) => {\n this.state( 'clicks', this._states.clicks + 1 );\n } );\n\n\n // listen for move events and fire enter and leave events accordingly\n this.on( UA.move, ( target:UI, pt:PtLike, type:string, evt:MouseEvent ) => {\n let hover = this._within( pt );\n\n // hover on\n if ( hover && !this._states.hover ) {\n this.state( 'hover', true );\n\n // enter trigger\n UI._trigger( this._actions[UA.enter], this, pt, UA.enter, evt );\n \n // listen for hover off\n let _capID = this.hold( UA.move ); // keep hold of second move\n this._hoverID = this.on( UA.move, ( t:UI, p:PtLike ) => {\n \n if ( !this._within( p ) && !this.state( 'dragging' ) ) {\n this.state( 'hover', false );\n // leave trigger\n UI._trigger( this._actions[UA.leave], this, pt, UA.leave, evt );\n this.off( UA.move, this._hoverID ); // remove second move listener\n this.unhold( _capID ); // stop keeping hold of second move\n }\n } );\n }\n } );\n }\n \n\n /**\n * Add a new click handler. Remember this button will also need to be tracked for events via `UI.track`. If you want to track right clicks, you may also consider [`UIButton.onContextMenu`](#link).\n * @param fn a [`UIHandler`](#link) callback function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @returns an id number that refers to this handler, for use in [`UIButton.offClick`](#link) or [`UI.off`](#link).\n */\n onClick( fn:UIHandler ):number {\n return this.on( UIPointerActions.up, fn ) ;\n }\n\n\n /**\n * Remove an existing click handler\n * @param id an ID number returned by [`UIButton.onClick`](#link). If this is not defined, all handlers in this type will be removed.\n * @returns a boolean indicating whether the handler was removed successfully\n */\n offClick( id:number ):boolean {\n return this.off( UIPointerActions.up, id );\n }\n\n \n /**\n * Add a new contextmenu handler. `contextmenu` is similar to right click, see the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Element/contextmenu_event). Remember this button will also need to be tracked for events via `UI.track`. Also note that you may need to use `event.preventDefault()` in the callback function to prevent other events from triggering.\n * @param fn a [`UIHandler`](#link) callback function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @returns an id number that refers to this handler, for use in [`UIButton.offContextMenu`](#link) or [`UI.off`](#link).\n */\n onContextMenu( fn:UIHandler ):number {\n return this.on( UIPointerActions.contextmenu, fn ) ;\n }\n\n\n /**\n * Remove an existing contextmenu handler\n * @param id an ID number returned by [`UIButton.onContextMenu`](#link). If this is not defined, all handlers in this type will be removed.\n * @returns a boolean indicating whether the handler was removed successfully\n */\n offContextMenu( id:number ):boolean {\n return this.off( UIPointerActions.contextmenu, id );\n }\n\n \n /**\n * Add handlers for hover events. Remember this button will also need to be tracked for events via `UI.track`.\n * @param enter an optional [`UIHandler`](#link) function to handle when pointer enters hover. Eg, `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @param leave an optional [`UIHandler`](#link) function to handle when pointer exits hover. Eg, `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @returns id numbers that refer to enter/leave handlers, for use in [`UIButton.offHover`](#link) or [`UI.off`](#link).\n */\n onHover( enter?:UIHandler, leave?:UIHandler ):number[] {\n let ids = [undefined, undefined];\n if ( enter ) ids[0] = this.on( UIPointerActions.enter, enter );\n if ( leave ) ids[1] = this.on( UIPointerActions.leave, leave );\n return ids;\n }\n\n\n /**\n * Remove handlers for hover events.\n * @param enterID an ID number returned by [`UI.onClick`](#link), or -1 to skip. If this is not defined, all handlers in this type will be removed. \n * @param leaveID an ID number returned by [`UI.onClick`](#link), or -1 to skip. If this is not defined, all handlers in this type will be removed. \n * @returns an array of booleans indicating whether the handlers were removed successfully\n */\n offHover( enterID?:number, leaveID?:number ):boolean[] {\n let s = [false, false];\n if ( enterID === undefined || enterID >= 0 ) s[0] = this.off( UIPointerActions.enter, enterID );\n if ( leaveID === undefined || leaveID >= 0 ) s[1] = this.off( UIPointerActions.leave, leaveID );\n return s;\n }\n\n}\n\n\n/**\n * [Experimental] A draggable UI that provides handler such as [`UIDragger.onDrag`](#link) and [`UIDragger.onDrop`](#link).\n */\nexport class UIDragger extends UIButton {\n\n private _draggingID:number = -1;\n private _moveHoldID:number = -1;\n private _dropHoldID:number = -1;\n private _upHoldID:number = -1;\n\n /**\n * Create a dragger which has all the states in UIButton, with additional \"dragging\" (a boolean indicating whether it's currently being dragged) and \"offset\" (a Pt representing the offset between this UI's position and the pointer's position when dragged) states. (See [`UI.state`](#link)) You may also create a new UIDragger using one of the static helper like [`UI.fromRectangle`](#link) or [`UI.fromCircle`](#link).\n * @param group a Group or an Iterable<PtLike> that defines the UI's appearance\n * @param shape specifies the shape of the Group\n * @param states Optional default state object\n * @param id Optional id string\n */\n constructor( group:PtLikeIterable, shape:string, states:{[key:string]: any} = {}, id?:string ) {\n super( group, shape, states, id );\n if ( states.dragging === undefined ) this._states['dragging'] = false;\n if ( states.moved === undefined ) this._states['moved'] = false;\n if ( states.offset === undefined ) this._states['offset'] = new Pt();\n\n const UA = UIPointerActions;\n\n /* \n * Note: drag/drop is implemented in Space.ts, uidrag/uidrop is \n * reimplemented here so that we can keep track of move events happening \n * outside of the UI element. E.g. when the mouse moves faster than the \n * UI refreshes.\n */\n\n // Handle pointer down and begin dragging\n this.on( UA.down, ( target:UI, pt:PtLike, type:string, evt: MouseEvent ) => {\n // begin listening for all events after dragging starts\n if ( this._moveHoldID === -1 ) {\n this.state( 'dragging', true );\n this.state( 'offset', new Pt( pt ).subtract( target.group[0] ) );\n this._moveHoldID = this.hold( UA.move ); // keep hold of move\n }\n if ( this._dropHoldID === -1 ) {\n this._dropHoldID = this.hold( UA.drop ); // keep hold of drop (normal drag and drop)\n }\n if ( this._upHoldID === -1 ) {\n this._upHoldID = this.hold( UA.up ); // keep hold of up (cancel dragging if simple click)\n }\n if ( this._draggingID === -1 ) {\n this._draggingID = this.on( UA.move, ( t:UI, p:PtLike ) => {\n if ( this.state( 'dragging' ) ) {\n UI._trigger( this._actions[UA.uidrag], t, p, UA.uidrag, evt );\n this.state( 'moved', true );\n }\n } );\n }\n } );\n\n // Handle pointer drop or up and end dragging\n const endDrag = ( target:UI, pt:PtLike, type:string, evt:MouseEvent ) => {\n this.state( 'dragging', false );\n // remove move listener\n this.off( UA.move, this._draggingID );\n this._draggingID = -1;\n // stop keeping hold of move\n this.unhold( this._moveHoldID );\n this._moveHoldID = -1;\n // stop keeping hold of drop\n this.unhold( this._dropHoldID );\n this._dropHoldID = -1;\n // stop keeping hold of up\n this.unhold( this._upHoldID );\n this._upHoldID = -1;\n // trigger event\n if ( this.state( 'moved' ) ) {\n UI._trigger( this._actions[UA.uidrop], target, pt, UA.uidrop, evt );\n this.state( 'moved', false );\n }\n };\n this.on( UA.drop, endDrag );\n this.on( UA.up, endDrag );\n this.on( UA.out, endDrag );\n\n }\n\n\n /**\n * Add a new drag handler. Remember this button will also need to be tracked for events via `UI.track`.\n * @param fn a [`UIHandler`](#link) callback function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`. You can access the states \"dragging\" and \"offset\" (See [`UI.state`](#link)) in the callback.\n * @returns an id number that refers to this handler, for use in [`UIDragger.offDrag`](#link) or [`UI.off`](#link).\n */\n onDrag( fn:UIHandler ):number {\n return this.on( UIPointerActions.uidrag, fn ) ;\n }\n \n\n /**\n * Remove an existing drag handler\n * @param id an ID number returned by [`UIDragger.onDrag`](#link). If this is not defined, all handlers in this type will be removed.\n * @returns a boolean indicating whether the handler was removed successfully\n */\n offDrag( id:number ):boolean {\n return this.off( UIPointerActions.uidrag, id );\n }\n\n\n /**\n * Add a new drop handler. Remember this button will also need to be tracked for events via `UI.track`.\n * @param fn a [`UIHandler`](#link) callback function: `fn( target:UI, pt:Pt, type:string, evt:MouseEvent )`\n * @returns an id number that refers to this handler, for use in [`UIDragger.offDrop`](#link) or [`UI.off`](#link).\n */\n onDrop( fn:UIHandler ):number {\n return this.on( UIPointerActions.uidrop, fn ) ;\n }\n\n\n /**\n * Remove an existing drop handler\n * @param id an ID number returned by [`UIDragger.onDrag`](#link). If this is not defined, all handlers in this type will be removed.\n * @returns a boolean indicating whether the handler was removed successfully\n */\n offDrop( id:number ):boolean {\n return this.off( UIPointerActions.uidrop, id );\n }\n\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport {Pt} from \"./Pt\";\r\nimport {Util} from \"./Util\";\r\nimport {PtLike, GroupLike} from \"./Types\";\r\n\r\n\r\n/**\r\n* Form is an abstract class that represents a form that's used in a Space for expressions. Learn more about Space and Form in [this guide](../guide/Space-0500.html).\r\n*/\r\nexport abstract class Form {\r\n \r\n protected _ready:boolean = false;\r\n \r\n /**\r\n * get whether the Form has received the Space's rendering context.\r\n */\r\n get ready():boolean { return this._ready; }\r\n\r\n}\r\n\r\n\r\n\r\n\r\n/**\r\n* VisualForm is an abstract class that represents a form that can be used to express Pts visually.\r\n* For example, [`CanvasForm`](#link) is an implementation of VisualForm that draws on [`CanvasSpace`](#link) which represents a html canvas. Learn more about Space and Form in [this guide](../guide/Space-0500.html).\r\n*/\r\nexport abstract class VisualForm extends Form {\r\n \r\n protected _filled = true;\r\n protected _stroked = true;\r\n protected _font:Font = new Font( 14, \"sans-serif\" );\r\n\r\n /**\r\n * Check whether this form currently has fill style. \r\n */\r\n get filled():boolean { return this._filled; }\r\n set filled( b:boolean ) { this._filled = b; }\r\n \r\n\r\n /**\r\n * Check whether this form currently has stroke style.\r\n */\r\n get stroked():boolean { return this._stroked; }\r\n set stroked( b:boolean ) { this._stroked = b; }\r\n\r\n\r\n /**\r\n * Get the current font in use in this form.\r\n */\r\n get currentFont():Font { return this._font; }\r\n \r\n \r\n protected _multiple( groups:GroupLike[], shape:string, ...rest ):this {\r\n if ( !groups ) return this;\r\n for ( let i = 0, len = groups.length; i < len; i++ ) {\r\n this[shape]( groups[i], ...rest );\r\n }\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Abstract reset style\r\n */\r\n abstract reset(): this;\r\n \r\n \r\n /**\r\n * Set alpha (not implemented here -- to be implemented in subclasses).\r\n * @param a alpha value between 0 and 1\r\n */\r\n alpha( a:number ):this {\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set fill color (not implemented here -- to be implemented in subclasses).\r\n * @param c fill color as string or `false` to specify transparent.\r\n */\r\n fill( c:string | boolean ):this {\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set current fill style and remove stroke style. (not implemented here -- to be implemented in subclasses).\r\n * @param c fill color as string or `false` to specify transparent.\r\n */\r\n fillOnly( c:string | boolean ):this {\r\n this.stroke( false );\r\n return this.fill( c );\r\n }\r\n \r\n \r\n /**\r\n * Set stroke style (not implemented here -- to be implemented in subclasses). \r\n * @param c stroke color as string or `false` to specify transparent.\r\n * @param width Optional value (can be floating point) to set line width\r\n * @param linejoin Optional string to set line joint style. Can be \"miter\", \"bevel\", or \"round\".\r\n * @param linecap Optional string to set line cap style. Can be \"butt\", \"round\", or \"square\".\r\n */\r\n stroke( c:string | boolean, width?:number, linejoin?:string, linecap?:string ):this {\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Set stroke style and remove fill style. (not implemented here -- to be implemented in subclasses). \r\n * @param c stroke color as string or `false` to specify transparent.\r\n * @param width Optional value (can be floating point) to set line width\r\n * @param linejoin Optional string to set line joint style. Can be \"miter\", \"bevel\", or \"round\".\r\n * @param linecap Optional string to set line cap style. Can be \"butt\", \"round\", or \"square\".\r\n */\r\n strokeOnly( c:string | boolean, width?:number, linejoin?:string, linecap?:string ):this {\r\n this.fill( false );\r\n return this.stroke( c, width, linejoin, linecap );\r\n }\r\n \r\n /**\r\n * Draw a point (not implemented here -- to be implemented in subclasses).\r\n * @param p a Pt object\r\n * @param radius radius of the point. Default is 5.\r\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\r\n * @example `form.point( p )`, `form.point( p, 10, \"circle\" )`\r\n */\r\n abstract point( p:PtLike, radius:number, shape:string ):this;\r\n \r\n \r\n /**\r\n * Draw multiple points at once.\r\n * @param pts an array of Pt or an array of number arrays\r\n * @param radius radius of the point. Default is 5.\r\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\r\n */\r\n points( pts:GroupLike | number[][], radius:number, shape:string ): this {\r\n if ( !pts ) return;\r\n for ( let i = 0, len = pts.length; i < len; i++ ) {\r\n this.point( pts[i], radius, shape );\r\n }\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Draw a circle (not implemented here -- to be implemented in subclasses).\r\n * @param pts usually a Group of 2 Pts, but it can also take an array of two numeric arrays [ [position], [size] ]\r\n * @see [`Circle.fromCenter`](./?p=Op_Circle#function_fromCenter)\r\n */\r\n abstract circle( pts:GroupLike | number[][] ):this;\r\n \r\n \r\n \r\n /**\r\n * Draw multiple circles at once.\r\n * @param groups an array of Groups that defines multiple circles\r\n */\r\n circles( groups:GroupLike[] ):this {\r\n return this._multiple( groups, \"circle\" );\r\n }\r\n \r\n \r\n /**\r\n * Draw multiple squares at once.\r\n * @param groups an array of Groups that defines multiple circles\r\n */\r\n squares( groups:GroupLike[] ):this {\r\n return this._multiple( groups, \"square\" );\r\n }\r\n \r\n \r\n /**\r\n * Draw an arc (not implemented here -- to be implemented in subclasses).\r\n * @param pt center position\r\n * @param radius radius of the arc circle\r\n * @param startAngle start angle of the arc\r\n * @param endAngle end angle of the arc\r\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\r\n */\r\n abstract arc( pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ):this;\r\n \r\n \r\n /**\r\n * Draw a line or polyline (not implemented here -- to be implemented in subclasses).\r\n * @param pts a Group of multiple Pts, or an array of multiple numeric arrays\r\n */\r\n abstract line( pts:GroupLike | number[][] ):this;\r\n \r\n \r\n /**\r\n * Draw multiple lines at once.\r\n * @param groups An array of Groups of Pts\r\n */\r\n lines( groups:GroupLike[] ):this {\r\n return this._multiple( groups, \"line\" );\r\n }\r\n \r\n \r\n /**\r\n * Draw a polygon (not implemented here -- to be implemented in subclasses).\r\n * @param pts a Group of multiple Pts, or an array of multiple numeric arrays\r\n */\r\n abstract polygon( pts:GroupLike | number[][] ):this;\r\n \r\n \r\n /**\r\n * Draw multiple polygons at once.\r\n * @param groups An array of Groups of Pts\r\n */\r\n polygons( groups:GroupLike[] ):this {\r\n return this._multiple( groups, \"polygon\" );\r\n }\r\n \r\n \r\n \r\n /**\r\n * Draw a rectangle (not implemented here -- to be implemented in subclasses).\r\n * @param pts usually a Group of 2 Pts specifying the top-left and bottom-right positions. Alternatively it can be an array of numeric arrays.\r\n */\r\n abstract rect( pts:number[][] | Pt[] ):this;\r\n \r\n \r\n /**\r\n * Draw multiple rectangles at once.\r\n * @param groups An array of Groups of Pts\r\n */\r\n rects( groups:GroupLike[] ):this {\r\n return this._multiple( groups, \"rect\" );\r\n }\r\n \r\n \r\n /**\r\n * Draw text (not implemented here -- to be implemented in subclasses).\r\n * @param `pt` a Pt or numeric array to specify the anchor point\r\n * @param `txt` text\r\n * @param `maxWidth` specify a maximum width per line\r\n */\r\n abstract text( pt:PtLike, txt:string, maxWidth?:number ): this;\r\n \r\n \r\n /**\r\n * Set font style (not implemented here -- to be implemented in subclasses).\r\n * @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties\r\n * @param weight Optional font-weight string such as \"bold\"\r\n * @param style Optional font-style string such as \"italic\"\r\n * @param lineHeight Optional line-height number suchas 1.5\r\n * @param family Optional font-family such as \"Helvetica, sans-serif\"\r\n * @see `Font` class\r\n * @example `form.font( myFont )`, `form.font(14, \"bold\")`\r\n */\r\n abstract font( sizeOrFont:number | Font, weight?:string, style?:string, lineHeight?:number, family?:string ):this;\r\n}\r\n\r\n\r\n\r\n/**\r\n* Font class lets you create a specific font style with properties for its size and style. A font instance can be passed as parameter to set a form's font. For example, see [`CanvasForm.font`](#link).\r\n*/\r\nexport class Font {\r\n public size:number;\r\n public lineHeight:number;\r\n public face:string;\r\n public style:string;\r\n public weight:string;\r\n \r\n /**\r\n * Create a font style.\r\n * @param size font size. Defaults is 12px.\r\n * @param face Optional font-family, use css-like string such as \"Helvetica\" or \"Helvetica, sans-serif\". Default is \"sans-serif\".\r\n * @param weight Optional font weight such as \"bold\". Default is \"\" (none).\r\n * @param style Optional font style such as \"italic\". Default is \"\" (none).\r\n * @param lineHeight Optional line height. Default is 1.5.\r\n * @example `new Font(12, \"Frutiger, sans-serif\", \"bold\", \"underline\", 1.5)`\r\n */\r\n constructor( size:number = 12, face:string = \"sans-serif\", weight:string = \"\", style:string = \"\", lineHeight:number = 1.5 ) {\r\n this.size = size;\r\n this.face = face;\r\n this.style = style;\r\n this.weight = weight;\r\n this.lineHeight = lineHeight;\r\n }\r\n \r\n /**\r\n * Get a string representing the font style, in css-like string such as \"italic bold 12px/1.5 sans-serif\".\r\n */\r\n get value():string { return `${this.style} ${this.weight} ${this.size}px/${this.lineHeight} ${this.face}`; }\r\n \r\n \r\n /**\r\n * Get a string representing the font style, in css-like string such as \"italic bold 12px/1.5 sans-serif\".\r\n */\r\n toString():string { return this.value; }\r\n \r\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Pt, Bound} from \"./Pt\";\nimport {Util} from \"./Util\";\nimport {GroupLike, PtLikeIterable} from \"./Types\";\n\n/** \n * Typography provides helper functions to support typographic layouts. For a concrete example, see [a demo here](../demo/index.html?name=canvasform.textBox) that uses the [`CanvasForm.textBox`](#link) function.\n */\nexport class Typography {\n\n /**\n * Create a heuristic text width estimate function. It will be less accurate but faster.\n * @param fn a reference function that can measure text width accurately\n * @param samples a list of string samples. Default is [\"M\", \"n\", \".\"]\n * @param distribution a list of the samples' probability distribution. Default is [0.06, 0.8, 0.14].\n * @return a function that can estimate text width\n */\n static textWidthEstimator( fn:( string ) => number, samples:string[] = [\"M\", \"n\", \".\"], distribution:number[] = [0.06, 0.8, 0.14] ):( string ) => number {\n let m = samples.map( fn );\n let avg = new Pt( distribution ).dot( m );\n return ( str:string ) => str.length * avg;\n }\n\n\n /**\n * Truncate text to fit width.\n * @param fn a function that can measure text width\n * @param str text to truncate\n * @param width width to fit\n * @param tail text to indicate overflow such as \"...\". Default is empty \"\".\n */\n static truncate( fn:( string ) => number, str:string, width:number, tail:string = \"\" ):[string, number] {\n let trim = Math.floor( str.length * Math.min( 1, width / fn( str ) ) );\n if ( trim < str.length ) {\n trim = Math.max( 0, trim - tail.length );\n return [str.substr( 0, trim ) + tail, trim];\n } else {\n return [str, str.length];\n }\n }\n\n\n /**\n * Get a function to scale font size proportionally to text box size changes.\n * @param box a Group or an Iterable<PtLike> representing the initial box\n * @param ratio font-size change ratio. Default is 1.\n * @returns a function where input parameter is a new box, and returns the new font size value\n */\n static fontSizeToBox( box:PtLikeIterable, ratio:number = 1, byHeight:boolean = true ): ( GroupLike ) => number {\n let bound = Bound.fromGroup( box );\n let h = byHeight ? bound.height : bound.width;\n let f = ratio * h;\n return function( box2:GroupLike ) {\n let bound2 = Bound.fromGroup( box2 );\n let nh = ( byHeight ? bound2.height : bound2.width ) / h;\n return f * nh;\n };\n }\n\n\n /**\n * Get a function to scale font size based on a threshold value.\n * @param defaultSize default font size to base on\n * @param threshold threshold value\n * @param direction if negative, get a font size <= defaultSize; if positive, get a font size >= defaultSize; Default is 0 which will scale font without min or max limits.\n * @returns a function where input parameter is the default font size and a value to compare with threshold, and returns new font size value\n */\n static fontSizeToThreshold( threshold:number, direction:number = 0 ): ( a:number, b:number ) => number {\n return function( defaultSize:number, val:number ) {\n let d = defaultSize * val / threshold; \n if ( direction < 0 ) return Math.min( d, defaultSize );\n if ( direction > 0 ) return Math.max( d, defaultSize );\n return d;\n };\n }\n}\n\n","import { CanvasForm, CanvasSpace } from \"./Canvas\";\nimport { Bound, Pt } from \"./Pt\";\nimport { Mat } from \"./LinearAlgebra\";\nimport { PtLike, CanvasPatternRepetition } from \"./Types\";\n\n/**\n * Img provides convenient functions to support image operations on HTML Canvas and [`CanvasSpace`](#link). Combine this with other Pts functions to experiment with visual forms that integrate bitmaps and vector graphics.\n */\nexport class Img {\n\n protected _img:HTMLImageElement;\n protected _data:ImageData;\n protected _cv:HTMLCanvasElement;\n protected _ctx:CanvasRenderingContext2D;\n protected _scale:number = 1;\n\n protected _loaded:boolean = false;\n protected _editable:boolean;\n\n protected _space:CanvasSpace;\n\n /**\n * Create an Img\n * @param editable Specify if you want to manipulate pixels of this image. Default is `false`.\n * @param space Set the `CanvasSpace` reference. This is optional but will make sure the image's pixelScale match the canvas and set the context for creating pattern.\n * @param crossOrigin an optional parameter to enable loading cross-domain images if set to true. The image server's configuration must also be set correctly. For more, see [this documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image).\n */\n constructor( editable:boolean = false, space?:CanvasSpace, crossOrigin?:boolean ) {\n this._editable = editable;\n this._space = space;\n this._scale = this._space ? this._space.pixelScale : 1;\n this._img = new Image();\n if ( crossOrigin ) this._img.crossOrigin = \"Anonymous\";\n }\n\n\n /**\n * A static function to load an image with an optional ready callback. The Img instance will returned immediately before the image is loaded. To use async/await, use the `loadAsync` function or `new Img(...).load(...)`.\n * @param src an url of the image in same domain. Alternatively you can use a base64 string. To load from Blob, use `Img.fromBlob`.\n * @param editable Specify if you want to manipulate pixels of this image. Default is `false`.\n * @param space Set the `CanvasSpace` reference. This is optional but will make sure the image's pixelScale match the canvas and set the context for creating pattern.\n * @param ready An optional ready callback function \n */\n static load( src:string, editable:boolean = false, space?:CanvasSpace, ready?:( img ) => {} ):Img {\n const img = new Img( editable, space );\n img.load( src ).then( res => {\n if ( ready ) ready( res );\n } );\n return img;\n }\n\n\n /**\n * A static method to load an image using async/await.\n * @param src an url of the image in same domain. Alternatively you can use a base64 string. To load from Blob, use `Img.fromBlob`.\n * @param editable Specify if you want to manipulate pixels of this image. Default is `false`.\n * @param space Set the `CanvasSpace` reference. This is optional but will make sure the image's pixelScale match the canvas and set the context for creating pattern.\n * @returns \n */\n static async loadAsync( src:string, editable:boolean = false, space?:CanvasSpace ) {\n const img = await new Img( editable, space ).load( src );\n return img;\n }\n\n\n /**\n * A static method to load an image pattern using async/await.\n * @param src an url of the image in same domain. Alternatively you can use a base64 string. To load from Blob, use `Img.fromBlob`.\n * @param space Set the `CanvasSpace` reference. This is optional but will make sure the image's pixelScale match the canvas and set the context for creating pattern.\n * @param repeat set how the pattern will repeat fills\n * @param editable Specify if you want to manipulate pixels of this image. Default is `false`.\n * @returns a `CanvasPattern` instance for use in `fill()`\n */\n static async loadPattern( src:string, space:CanvasSpace, repeat:CanvasPatternRepetition = 'repeat', editable:boolean = false ) {\n const img = await Img.loadAsync( src, editable, space );\n return img.pattern( repeat );\n }\n\n\n /**\n * Create an editable blank image\n * @param size of image\n * @param space Set the `CanvasSpace` reference. This is optional but will make sure the image's pixelScale match the canvas and set the context for creating pattern.\n * @param scale Optionally set a specific pixel scale (density) of the image canvas. \n */\n static blank( size:PtLike, space:CanvasSpace, scale?:number ):Img {\n let img = new Img( true, space );\n const s = scale ? scale : space.pixelScale;\n img.initCanvas( size[0], size[1], s );\n return img;\n }\n \n\n /**\n * Load an image. \n * @param src an url of the image in same domain. Alternatively you can use a base64 string. To load from Blob, use `Img.fromBlob`.\n * @returns a Promise that resolves to an Img\n */\n load( src:string ): Promise<Img> {\n return new Promise( ( resolve,reject ) => {\n if ( this._editable && !document ) {\n reject( \"Cannot create html canvas element. document not found.\" );\n }\n\n this._img.src = src;\n\n this._img.onload = () => {\n if ( this._editable ) {\n if ( !this._cv ) this._cv = document.createElement( \"canvas\" ) as HTMLCanvasElement;\n this._drawToScale( this._scale, this._img );\n this._data = this._ctx.getImageData( 0, 0, this._cv.width, this._cv.height );\n }\n \n this._loaded = true;\n resolve( this );\n };\n \n this._img.onerror = ( evt:Event ) => {\n reject( evt );\n };\n\n } );\n }\n \n\n /**\n * Rescale the canvas and draw an image-source on it.\n * @param imgScale rescale factor for the image\n * @param canvasScale rescale factor for the canvas\n * @param img an image source like Image, Canvas, or ImageBitmap.\n */\n protected _drawToScale( canvasScale:number | PtLike, img:HTMLImageElement | HTMLCanvasElement | ImageBitmap | OffscreenCanvas | HTMLVideoElement ) {\n const nw = img.width as number;\n const nh = img.height as number;\n this.initCanvas( nw, nh, canvasScale );\n if ( img ) this._ctx.drawImage( img, 0, 0, nw, nh, 0, 0, this._cv.width, this._cv.height );\n }\n\n\n /**\n * Initiate an editable canvas\n * @param width width of canvas\n * @param height height of canvas\n * @param canvasScale pixel scale\n */\n initCanvas( width:number, height:number, canvasScale:number | PtLike = 1 ) {\n if ( !this._editable ) {\n console.error( 'Cannot initiate canvas because this Img is not set to be editable' );\n return;\n }\n \n if ( !this._cv ) this._cv = document.createElement( \"canvas\" ) as HTMLCanvasElement;\n \n const cms = ( typeof canvasScale === 'number' ) ? [canvasScale, canvasScale] : canvasScale; \n this._cv.width = width * cms[0];\n this._cv.height = height * cms[1];\n this._ctx = this._cv.getContext( '2d' );\n this._loaded = true;\n }\n\n\n /**\n * Get an efficient, readonly bitmap of the current canvas.\n * @param size Optional size to crop\n * @returns a Promise that resolves to an ImageBitmap\n */\n bitmap( size?:PtLike ):Promise<ImageBitmap> {\n const w = ( size ) ? size[0] : this._cv.width;\n const h = ( size ) ? size[1] : this._cv.height;\n return createImageBitmap( this._cv, 0, 0, w, h );\n }\n\n\n /**\n * Create a canvas pattern for `fill()`\n * @param reptition set how the pattern should repeat-fill\n * @param dynamic If true, use this Img's internal canvas content as pattern fill. This enables the pattern to update dynamically.\n * @returns a `CanvasPattern` instance for use in `fill()`\n */\n pattern( reptition:CanvasPatternRepetition = 'repeat', dynamic:boolean = false ):CanvasPattern {\n if ( !this._space ) throw \"Cannot find CanvasSpace ctx to create image pattern\";\n return this._space.ctx.createPattern( dynamic ? this._cv : this._img, reptition );\n }\n\n\n /**\n * Replace the image with the current canvas data. For example, you can use CanvasForm's static functions to draw on `this.ctx` and then update the current image.\n * To display the internal canvas, you can also use `form.image( img.canvas )` directly.\n */\n sync() {\n // retina: resize canvas to fit image original size\n if ( this._scale !== 1 ) {\n this.bitmap().then( b => {\n this._drawToScale( 1 / this._scale, b ); // rescale canvas to match original and draw saved bitmap \n this.load( this.toBase64() ); // load current canvas into image\n } );\n\n // no retina so no need to rescale\n } else {\n this._img.src = this.toBase64(); \n }\n }\n\n\n /**\n * Get the RGBA values of a pixel in the image\n * @param p position of the pixel\n * @param rescale Specify if the pixel position should be scaled. Usually use rescale when tracking image and don't rescale when tracking canvas. You may also set a custom scale value.\n * @returns [R,G,B,A] values of the pixel at the specific position\n */\n pixel( p:PtLike, rescale:boolean | number = true ):Pt {\n const s = ( typeof rescale == 'number' ) ? rescale : ( rescale ? this._scale : 1 );\n return Img.getPixel( this._data, [p[0] * s, p[1] * s] );\n }\n \n\n /**\n * Given an ImaegData object and a position, return the RGBA pixel value at that position.\n * @param imgData an ImageData object\n * @param p a position on the image\n * @returns [R,G,B,A] values of the pixel at the specific position\n */\n static getPixel( imgData:ImageData, p:PtLike ):Pt {\n const no = new Pt( 0,0,0,0 );\n if ( p[0] >= imgData.width || p[1] >= imgData.height ) return no;\n\n const i = Math.floor( p[1] ) * ( imgData.width * 4 ) + ( Math.floor( p[0] ) * 4 );\n const d = imgData.data;\n if ( i >= d.length - 4 ) return no;\n\n return new Pt( d[i], d[i + 1], d[i + 2], d[i + 3] );\n }\n\n\n /**\n * Resize the canvas image. The original image is unchanged until `sync()`.\n * @param sizeOrScale A PtLike array specifying either [x, y] scales or [x, y] sizes.\n * @param asScale If true, treat the first parameter as scales. Otherwise, treat it as specific sizes.\n */\n resize( sizeOrScale:PtLike, asScale:boolean = false ):this {\n let s = asScale ? sizeOrScale : [sizeOrScale[0] / this._img.naturalWidth, sizeOrScale[1] / this._img.naturalHeight];\n this._drawToScale( s, this._img );\n this._data = this._ctx.getImageData( 0, 0, this._cv.width, this._cv.height );\n return this;\n }\n\n\n /**\n * Crop an area of the image.\n * @param box bounding box\n */\n crop( box:Bound ):ImageData {\n let p = box.topLeft.scale( this._scale );\n let s = box.size.scale( this._scale );\n return this._ctx.getImageData( p.x, p.y, s.x, s.y );\n }\n\n\n /**\n * Apply filters such as blur and grayscale to the canvas image. The original image is unchanged until `sync()`.\n * @param css a css filter string such as \"blur(10px) | contrast(200%)\". See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter#browser_compatibility) for a list of filter functions.\n */\n filter( css:string ):this {\n this._ctx.filter = css;\n this._ctx.drawImage( this._cv, 0, 0 );\n this._ctx.filter = \"none\";\n return this;\n }\n\n\n /**\n * Remove the elements and data associated with this Img.\n */\n cleanup() {\n if ( this._cv ) this._cv.remove();\n if ( this._img ) this._img.remove();\n this._data = null;\n }\n\n\n /**\n * Create a blob url that can be passed to `Img.load`\n * @param blob an image blob such as `new Blob([my_Uint8Array], {type: 'image/png'})`\n * @param editable Specify if you want to manipulate pixels of this image. Default is `false`.\n */\n static fromBlob( blob:Blob, editable:boolean = false, space?:CanvasSpace ):Promise<Img> {\n let url = URL.createObjectURL( blob );\n return new Img( editable, space ).load( url );\n }\n\n\n /**\n * Convert ImageData object to a Blob, which you can then create an Img instance via [`Img.fromBlob`](#link). Note that the resulting image's dimensions will not account for pixel density.\n * @param data \n */\n static imageDataToBlob( data:ImageData ):Promise<Blob> {\n return new Promise( function ( resolve, reject ) { \n if ( !document ) {\n reject( \"Cannot create html canvas element. document not found.\" );\n }\n let cv = document.createElement( \"canvas\" ) as HTMLCanvasElement;\n cv.width = data.width;\n cv.height = data.height;\n cv.getContext( \"2d\" ).putImageData( data, 0, 0 );\n cv.toBlob( blob => {\n resolve( blob );\n cv.remove();\n } );\n } );\n }\n\n\n /**\n * Export current canvas image as base64 string\n */\n toBase64():string {\n return this._cv.toDataURL();\n }\n\n\n /**\n * Export current canvas image as a blob\n */\n toBlob():Promise<Blob> {\n return new Promise( ( resolve ) => { \n this._cv.toBlob( blob => resolve( blob ) );\n } );\n }\n\n\n /**\n * Get a CanvasForm for drawing on the internal canvas if this Img is editable\n */\n getForm():CanvasForm {\n if ( !this._editable ) {\n console.error( \"Cannot get a CanvasForm because this Img is not editable\" );\n }\n return this._ctx ? new CanvasForm( this._ctx ) : undefined;\n }\n\n /**\n * Get current image source. If editable, this will return the canvas, otherwise it will return the original image.\n */\n get current():CanvasImageSource {\n return this._editable ? this._cv : this._img;\n }\n\n\n /**\n * Get the original image\n */\n get image():HTMLImageElement {\n return this._img;\n }\n\n\n /**\n * Get the internal canvas\n */\n get canvas():HTMLCanvasElement {\n return this._cv;\n }\n\n\n /**\n * Get the internal canvas' ImageData\n */\n get data():ImageData {\n return this._data;\n }\n\n\n /**\n * Get the internal canvas' context. You can use this to draw directly on canvas, or create a new [CanvasForm](#link) instance with it.\n */\n get ctx():CanvasRenderingContext2D {\n return this._ctx;\n }\n\n\n /**\n * Get whether the image is loaded\n */\n get loaded():boolean {\n return this._loaded;\n }\n\n \n /**\n * Get pixel density scale\n */\n get pixelScale():number {\n return this._scale;\n }\n\n\n /**\n * Get size of the original image\n */\n get imageSize():Pt {\n if ( !this._img.width || !this._img.height ) {\n return this.canvasSize.$divide( this._scale );\n } else {\n return new Pt( this._img.width, this._img.height );\n }\n }\n\n\n /**\n * Get size of the canvas\n */\n get canvasSize():Pt {\n return new Pt( this._cv.width, this._cv.height );\n }\n\n\n /**\n * Get a Mat instance with a scale transform based on current `pixelScale`. \n * This can be useful for generating a domMatrix for transforming patterns consistently across different pixel-density screens.\n * @example `img.scaledMatrix.translate2d(...).rotate2D(...).domMatrix`\n */\n get scaledMatrix():Mat {\n const s = 1 / this._scale;\n return new Mat().scale2D( [s, s] );\n }\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\r\n\r\nimport {Pt, Group, Bound} from \"./Pt\";\r\nimport {Line, Triangle} from \"./Op\";\r\nimport {Const, Util} from \"./Util\";\r\nimport {Num, Geom} from \"./Num\";\r\nimport {Vec} from \"./LinearAlgebra\";\r\nimport {PtLike, GroupLike, PtIterable, DelaunayMesh, DelaunayShape} from \"./Types\";\r\n\r\n\r\n/**\r\n * The `Create` class helps you create structures from sets of points. \r\n */\r\nexport class Create {\r\n \r\n\r\n /**\r\n * Create a set of random points inside a bounday.\r\n * @param bound the rectangular boundary\r\n * @param count number of random points to create\r\n * @param dimensions number of dimensions in each point\r\n */\r\n static distributeRandom( bound:Bound, count:number, dimensions:number = 2 ):Group {\r\n let pts = new Group();\r\n for ( let i = 0; i < count; i++ ) {\r\n let p = [bound.x + Num.random() * bound.width];\r\n if ( dimensions > 1 ) p.push( bound.y + Num.random() * bound.height, );\r\n if ( dimensions > 2 ) p.push( bound.z + Num.random() * bound.depth );\r\n pts.push( new Pt( p ) );\r\n }\r\n return pts;\r\n }\r\n\r\n\r\n /**\r\n * Create a set of points that distribute evenly on a line. Similar to [`Line.subpoints`](#link) but includes the end points.\r\n * @param line a Group or an Iterable<Pt> representing a line\r\n * @param count number of points to create\r\n */\r\n static distributeLinear( line:PtIterable, count:number ):Group {\r\n let _line = Util.iterToArray( line );\r\n let ln = Line.subpoints( _line, count - 2 );\r\n ln.unshift( _line[0] );\r\n ln.push( _line[_line.length - 1] );\r\n return ln;\r\n }\r\n \r\n\r\n /**\r\n * Create an evenly distributed set of points (like a grid of points) inside a boundary.\r\n * @param bound the rectangular boundary\r\n * @param columns number of columns\r\n * @param rows number of rows\r\n * @param orientation a Pt or number array to specify where the point should be inside a cell. Default is [0.5, 0.5] which places the point in the middle.\r\n * @returns a Group of Pts\r\n */\r\n static gridPts( bound:Bound, columns:number, rows:number, orientation:PtLike = [0.5, 0.5] ):Group {\r\n if ( columns === 0 || rows === 0 ) throw new Error( \"grid columns and rows cannot be 0\" );\r\n let unit = bound.size.$subtract( 1 ).$divide( columns, rows );\r\n let offset = unit.$multiply( orientation );\r\n let g = new Group();\r\n for ( let r = 0; r < rows; r++ ) {\r\n for ( let c = 0; c < columns; c++ ) {\r\n g.push( bound.topLeft.$add( unit.$multiply( c, r ) ).add( offset ) );\r\n }\r\n }\r\n return g;\r\n \r\n }\r\n\r\n /**\r\n * Create a grid of cells inside a boundary, where each cell is defined by a group of 2 Pt.\r\n * @param bound the rectangular boundary\r\n * @param columns number of columns\r\n * @param rows number of rows\r\n * @returns an array of Groups, where each group represents a rectangular cell\r\n */\r\n static gridCells( bound:Bound, columns:number, rows:number ):Group[] {\r\n if ( columns === 0 || rows === 0 ) throw new Error( \"grid columns and rows cannot be 0\" );\r\n let unit = bound.size.$subtract( 1 ).divide( columns, rows ); // subtract 1 to fill whole border of rectangles\r\n let g = [];\r\n for ( let r = 0; r < rows; r++ ) {\r\n for ( let c = 0; c < columns; c++ ) {\r\n g.push( new Group(\r\n bound.topLeft.$add( unit.$multiply( c, r ) ),\r\n bound.topLeft.$add( unit.$multiply( c, r ).add( unit ) )\r\n ) );\r\n }\r\n }\r\n return g;\r\n }\r\n\r\n\r\n /**\r\n * Create a set of Pts around a circular path.\r\n * @param center circle center\r\n * @param radius circle radius\r\n * @param count number of Pts to create\r\n * @param angleOffset offset starting angle\r\n */\r\n static radialPts( center:PtLike, radius:number, count:number, angleOffset:number = -Const.half_pi ):Group {\r\n let g = new Group();\r\n let a = Const.two_pi / count;\r\n for ( let i = 0; i < count; i++ ) {\r\n g.push( new Pt( center ).toAngle( a * i + angleOffset, radius, true ) );\r\n }\r\n return g;\r\n }\r\n\r\n\r\n /**\r\n * Given a group of Pts, return a new group of `Noise` Pts.\r\n * @param pts a Group or an Iterable<Pt>\r\n * @param dx small increment value in x dimension\r\n * @param dy small increment value in y dimension\r\n * @param rows Optional row count to generate 2D noise\r\n * @param columns Optional column count to generate 2D noise\r\n */\r\n static noisePts( pts:PtIterable, dx = 0.01, dy = 0.01, rows = 0, columns = 0 ):Group {\r\n let seed = Num.random();\r\n let g = new Group();\r\n let i = 0;\r\n for ( let p of pts ) {\r\n let np = new Noise( p );\r\n let r = ( rows && rows > 0 ) ? Math.floor( i / rows ) : i;\r\n let c = ( columns && columns > 0 ) ? i % columns : i;\r\n np.initNoise( dx * c, dy * r );\r\n np.seed( seed );\r\n g.push( np );\r\n i++;\r\n }\r\n return g;\r\n }\r\n\r\n\r\n /**\r\n * Create a Delaunay Group. Use the [`Delaunay.delaunay()`](#link) and [`Delaunay.voronoi()`](#link) functions in the returned group to generate tessellations.\r\n * @param pts a Group or an array of Pts\r\n * @returns an instance of the Delaunay class\r\n */\r\n static delaunay( pts:GroupLike ):Delaunay {\r\n return Delaunay.from( pts ) as Delaunay;\r\n }\r\n \r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * Perlin noise gradient indices\r\n */\r\nconst __noise_grad3 = [\r\n [1,1, 0], [-1,1, 0], [1,-1,0], [-1,-1,0],\r\n [1,0, 1], [-1, 0, 1], [1,0,-1], [-1,0,-1],\r\n [0, 1,1], [0,-1,1], [0,1,-1], [0,-1,-1]\r\n];\r\n\r\n\r\n/**\r\n * Perlin noise permutation table\r\n */ \r\nconst __noise_permTable = [151,160,137,91,90,15,\r\n 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,\r\n 190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,\r\n 88,237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,\r\n 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,\r\n 102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200,196,\r\n 135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,\r\n 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,\r\n 223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,\r\n 129,22,39,253,9,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,\r\n 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,\r\n 49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,\r\n 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180\r\n];\r\n\r\n\r\n/**\r\n * Noise is a subclass of Pt that generates Perlin noise. Current implementation supports basic 2D noise.\r\n * This implementation is based on this [gist](https://gist.github.com/banksean/304522).\r\n */\r\nexport class Noise extends Pt {\r\n\r\n protected perm:number[] = [];\r\n private _n:Pt = new Pt( 0.01, 0.01 );\r\n\r\n /**\r\n * Create a Noise Pt that can generate noise continuously. See a [Noise demo here](../demo/index.html?name=create.noisePts).\r\n * @param args a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\r\n */\r\n constructor( ...args ) {\r\n super( ...args );\r\n\r\n // For easier index wrapping, double the permutation table length\r\n this.perm = __noise_permTable.concat( __noise_permTable );\r\n }\r\n\r\n\r\n /**\r\n * Set the initial dimensional values of the noise.\r\n * @param args a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\r\n * @example `noise.initNoise( 0.01, 0.1 )`\r\n */\r\n initNoise( ...args ) {\r\n this._n = new Pt( ...args );\r\n return this;\r\n }\r\n\r\n\r\n /**\r\n * Add a small increment to the noise values.\r\n * @param x step in x dimension\r\n * @param y step in y dimension\r\n */\r\n step( x = 0, y = 0 ) {\r\n this._n.add( x, y );\r\n return this;\r\n }\r\n\r\n /**\r\n * Specify a seed for this Noise.\r\n * @param s seed value\r\n */\r\n seed( s ) {\r\n if ( s > 0 && s < 1 ) s *= 65536;\r\n \r\n s = Math.floor( s );\r\n if ( s < 256 )s |= s << 8;\r\n\r\n for ( let i = 0; i < 255; i++ ) {\r\n let v = ( i & 1 ) ? __noise_permTable[i] ^ ( s & 255 ) : __noise_permTable[i] ^ ( ( s >> 8 ) & 255 );\r\n this.perm[i] = this.perm[i + 256] = v;\r\n }\r\n\r\n return this;\r\n }\r\n \r\n \r\n /**\r\n * Generate a 2D Perlin noise value.\r\n */\r\n noise2D() {\r\n \r\n let i = Math.max( 0, Math.floor( this._n[0] ) ) % 255;\r\n let j = Math.max( 0, Math.floor( this._n[1] ) ) % 255;\r\n let x = ( this._n[0] % 255 ) - i;\r\n let y = ( this._n[1] % 255 ) - j;\r\n\r\n let n00 = Vec.dot( __noise_grad3[ ( i + this.perm[j] ) % 12 ], [x, y, 0] );\r\n let n01 = Vec.dot( __noise_grad3[ ( i + this.perm[j + 1] ) % 12 ], [x, y - 1, 0] );\r\n let n10 = Vec.dot( __noise_grad3[ ( i + 1 + this.perm[j] ) % 12 ], [x - 1, y, 0] );\r\n let n11 = Vec.dot( __noise_grad3[ ( i + 1 + this.perm[j + 1] ) % 12 ], [x - 1, y - 1, 0] );\r\n\r\n let _fade = ( f ) => f * f * f * ( f * ( f * 6 - 15 ) + 10 );\r\n let tx = _fade( x );\r\n return Num.lerp( Num.lerp( n00, n10, tx ), Num.lerp( n01, n11, tx ), _fade( y ) );\r\n }\r\n \r\n\r\n}\r\n\r\n\r\n\r\n/**\r\n * Delaunay is a [`Group`](#link) of Pts that generates Delaunay and Voronoi tessellations. The triangulation algorithm is ported from [Pt](https://github.com/williamngan/pt). \r\n * Based on [Paul Bourke's algorithm](http://paulbourke.net/papers/triangulate/)\r\n * with reference to its [javascript implementation](https://github.com/ironwallaby/delaunay) by ironwallaby.\r\n */\r\nexport class Delaunay extends Group {\r\n\r\n private _mesh:DelaunayMesh = [];\r\n\r\n /**\r\n * Generate Delaunay triangles. This function also caches the mesh that is used to generate Voronoi tessellation in `voronoi()`. See a [Delaunay demo here](../demo/index.html?name=create.delaunay).\r\n * @param triangleOnly if true, returns an array of triangles in Groups, otherwise return the whole DelaunayShape\r\n * @returns an array of Groups or an array of DelaunayShapes `{i, j, k, triangle, circle}` which records the indices of the vertices, and the calculated triangles and circumcircles\r\n */\r\n delaunay( triangleOnly:boolean = true ):GroupLike[] | DelaunayShape[] {\r\n if ( this.length < 3 ) return [];\r\n\r\n this._mesh = [];\r\n\r\n let n = this.length;\r\n\r\n // sort the points and store the sorted index\r\n let indices:number[] = [];\r\n for ( let i = 0; i < n; i++ ) indices[i] = i;\r\n indices.sort( ( i,j ) => this[j][0] - this[i][0] );\r\n\r\n // duplicate the points list and add super triangle's points to it\r\n let pts = this.slice();\r\n let st = this._superTriangle();\r\n pts = pts.concat( st );\r\n\r\n // arrays to store edge buffer and opened triangles\r\n let opened:DelaunayShape[] = [this._circum( n, n + 1, n + 2, st )];\r\n let closed:DelaunayShape[] = [];\r\n let tris:GroupLike[] = [];\r\n\r\n // Go through each point using the sorted indices\r\n for ( let i = 0, len = indices.length; i < len; i++ ) {\r\n let c = indices[i];\r\n let edges:number[] = [];\r\n let j = opened.length;\r\n if ( !this._mesh[c] ) this._mesh[c] = {};\r\n\r\n // Go through each opened triangles\r\n while ( j-- ) {\r\n let circum:DelaunayShape = opened[j];\r\n let radius = circum.circle[1][0];\r\n let d = pts[c].$subtract( circum.circle[0] );\r\n\r\n // if point is to the right of circumcircle, add it to closed list and don't check again\r\n if ( d[0] > 0 && d[0] * d[0] > radius * radius ) {\r\n closed.push( circum );\r\n tris.push( circum.triangle );\r\n opened.splice( j, 1 );\r\n continue;\r\n }\r\n\r\n // if it's outside the circumcircle, skip\r\n if ( d[0] * d[0] + d[1] * d[1] - radius * radius > Const.epsilon ) {\r\n continue;\r\n }\r\n\r\n // otherwise it's inside the circumcircle, so we add to edge buffer and remove it from the opened list\r\n edges.push( circum.i, circum.j, circum.j, circum.k, circum.k, circum.i );\r\n opened.splice( j, 1 );\r\n }\r\n\r\n // dedup edges\r\n Delaunay._dedupe( edges );\r\n\r\n // Go through the edge buffer and create a triangle for each edge\r\n j = edges.length;\r\n while ( j > 1 ) {\r\n opened.push( this._circum( edges[--j], edges[--j], c, false, pts ) );\r\n }\r\n\r\n }\r\n\r\n for ( let i = 0, len = opened.length; i < len; i++ ) {\r\n let o = opened[i];\r\n if ( o.i < n && o.j < n && o.k < n ) {\r\n closed.push( o );\r\n tris.push( o.triangle );\r\n this._cache( o );\r\n }\r\n }\r\n\r\n return ( triangleOnly ) ? tris : closed;\r\n }\r\n\r\n\r\n /**\r\n * Generate Voronoi cells. `delaunay()` must be called before calling this function. See a [Voronoi demo here](../demo/index.html?name=create.delaunay).\r\n * @returns an array of Groups, each of which represents a Voronoi cell\r\n */\r\n voronoi():Group[] {\r\n let vs = [];\r\n let n = this._mesh;\r\n for ( let i = 0, len = n.length; i < len; i++ ) {\r\n vs.push( this.neighborPts( i, true ) );\r\n }\r\n return vs;\r\n }\r\n\r\n\r\n /**\r\n * Get the cached mesh. The mesh is an array of objects, each of which representing the enclosing triangles around a Pt in this Delaunay group.\r\n * @return an array of objects that store a series of DelaunayShapes\r\n */\r\n mesh():DelaunayMesh {\r\n return this._mesh;\r\n }\r\n\r\n\r\n /**\r\n * Given an index of a Pt in this Delaunay Group, returns its neighboring Pts in the network.\r\n * @param i index of a Pt\r\n * @param sort if true, sort the neighbors so that their edges will form a polygon\r\n * @returns an array of Pts\r\n */\r\n neighborPts( i:number, sort = false ):GroupLike {\r\n let cs = new Group();\r\n let n = this._mesh;\r\n for ( let k in n[i] ) {\r\n if ( n[i].hasOwnProperty( k ) ) cs.push( n[i][k].circle[0] );\r\n }\r\n return ( sort ) ? Geom.sortEdges( cs ) : cs;\r\n }\r\n\r\n\r\n /**\r\n * Given an index of a Pt in this Delaunay Group, returns its neighboring DelaunayShapes.\r\n * @param i index of a Pt\r\n * @returns an array of DelaunayShapes `{i, j, k, triangle, circle}`\r\n */\r\n neighbors( i:number ):DelaunayShape[] {\r\n let cs = [];\r\n let n = this._mesh;\r\n for ( let k in n[i] ) {\r\n if ( n[i].hasOwnProperty( k ) ) cs.push( n[i][k] );\r\n }\r\n return cs;\r\n }\r\n\r\n\r\n /**\r\n * Record a DelaunayShape in the mesh.\r\n * @param o DelaunayShape instance\r\n */\r\n protected _cache( o ):void {\r\n this._mesh[o.i][`${Math.min( o.j,o.k )}-${Math.max( o.j,o.k )}`] = o;\r\n this._mesh[o.j][`${Math.min( o.i,o.k )}-${Math.max( o.i,o.k )}`] = o;\r\n this._mesh[o.k][`${Math.min( o.i,o.j )}-${Math.max( o.i,o.j )}`] = o;\r\n }\r\n\r\n\r\n /**\r\n * Get the initial \"super triangle\" that contains all the points in this set.\r\n * @returns a Group representing a triangle\r\n */\r\n protected _superTriangle():Group {\r\n let minPt = this[0];\r\n let maxPt = this[0];\r\n for ( let i = 1, len = this.length; i < len; i++ ) {\r\n minPt = minPt.$min( this[i] );\r\n maxPt = maxPt.$max( this[i] );\r\n }\r\n\r\n let d = maxPt.$subtract( minPt );\r\n let mid = minPt.$add( maxPt ).divide( 2 );\r\n let dmax = Math.max( d[0], d[1] );\r\n\r\n return new Group( mid.$subtract( 20 * dmax, dmax ), mid.$add( 0, 20 * dmax ), mid.$add( 20 * dmax, -dmax ) );\r\n }\r\n\r\n\r\n /**\r\n * Get a triangle from 3 points in a list of points\r\n * @param i index 1\r\n * @param j index 2\r\n * @param k index 3\r\n * @param pts a Group of Pts\r\n */\r\n protected _triangle( i:number, j:number, k:number, pts:GroupLike = this ):Group {\r\n return new Group( pts[i], pts[j], pts[k] );\r\n }\r\n\r\n\r\n /**\r\n * Get a circumcircle and triangle from 3 points in a list of points\r\n * @param i index 1\r\n * @param j index 2\r\n * @param k index 3\r\n * @param tri a Group representing a triangle, or `false` to create it from indices\r\n * @param pts a Group of Pts\r\n */\r\n protected _circum( i:number, j:number, k:number, tri:GroupLike | false, pts:GroupLike = this ):DelaunayShape {\r\n let t = tri || this._triangle( i, j, k, pts );\r\n return {\r\n i: i,\r\n j: j,\r\n k: k,\r\n triangle: t,\r\n circle: Triangle.circumcircle( t )\r\n };\r\n }\r\n\r\n\r\n /**\r\n * Dedupe the edges array\r\n * @param edges \r\n */\r\n protected static _dedupe( edges:number[] ):number[] {\r\n let j = edges.length;\r\n\r\n while ( j > 1 ) {\r\n let b = edges[--j];\r\n let a = edges[--j];\r\n let i = j;\r\n\r\n while ( i > 1 ) {\r\n let n = edges[--i];\r\n let m = edges[--i];\r\n\r\n if ( ( a == m && b == n ) || ( a == n && b == m ) ) {\r\n edges.splice( j, 2 );\r\n edges.splice( i, 2 );\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return edges;\r\n }\r\n\r\n\r\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Pt, Group} from \"./Pt\";\nimport {Util} from \"./Util\";\nimport {Num, Geom} from \"./Num\";\nimport {PtLike, ColorType} from \"./Types\";\n\n\n/**\n * Color is a subclass of Pt. Since a color in a color space is analogous to a point or vector in a space, you can apply all Pt operations to colors too. The Color class provides support for many color spaces like HSL and LAB.\n */\nexport class Color extends Pt {\n\n // XYZ property for Standard Observer 2deg, Daylight/sRGB illuminant D65\n private static D65:PtLike = new Pt( 95.047, 100, 108.883, 1 );\n\n protected _mode:ColorType = \"rgb\";\n private _isNorm:boolean = false;\n\n /**\n * Value range for each color space\n */\n static ranges:{ [name: string]: Group } = {\n rgb: new Group( new Pt( 0,255 ), new Pt( 0,255 ), new Pt( 0,255 ) ),\n hsl: new Group( new Pt( 0,360 ), new Pt( 0,1 ), new Pt( 0,1 ) ),\n hsb: new Group( new Pt( 0,360 ), new Pt( 0,1 ), new Pt( 0,1 ) ),\n lab: new Group( new Pt( 0,100 ), new Pt( -128,127 ), new Pt( -128, 127 ) ),\n lch: new Group( new Pt( 0,100 ), new Pt( 0,100 ), new Pt( 0,360 ) ),\n luv: new Group( new Pt( 0,100 ), new Pt( -134,220 ), new Pt( -140,122 ) ),\n xyz: new Group( new Pt( 0,100 ), new Pt( 0,100 ), new Pt( 0,100 ) )\n };\n\n /**\n * Create a Color. Same as creating a Pt. Optionally you may use [`Color.from`](#link) to create a color.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\n */\n constructor( ...args ) {\n super( ...args );\n }\n\n\n /**\n * Create a Color object with 4 default dimensional values (1,1,1,1).\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\n */\n static from( ...args ):Color {\n const p = [1,1,1,1];\n const c = Util.getArgs( args );\n for ( let i = 0, len = p.length; i < len; i++ ) {\n if ( i < c.length ) p[i] = c[i];\n }\n return new Color( p );\n }\n\n\n /**\n * Convert a rgb hex string like `\"#FF0000\"` or `\"#F00\"` to a Color object.\n * @param hex a hex string, with optional '#' prefix\n */\n static fromHex( hex:string ):Color {\n\n if ( hex[0] == \"#\" ) hex = hex.substr( 1 ); // remove '#' if needed\n if ( hex.length <= 3 ) {\n const fn = ( i ) => hex[i] || \"F\";\n hex = `${fn( 0 )}${fn( 0 )}${fn( 1 )}${fn( 1 )}${fn( 2 )}${fn( 2 )}`;\n }\n\n let alpha = 1;\n if ( hex.length === 8 ) {\n alpha = hex.substr( 6 ) && 0xFF / 255;\n hex = hex.substring( 0, 6 );\n }\n\n const hexVal = parseInt( hex, 16 );\n return new Color( hexVal >> 16, hexVal >> 8 & 0xFF, hexVal & 0xFF, alpha );\n\n }\n\n\n /**\n * Create RGB Color. RGB color ranges are (0...255, 0...255, 0...255) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static rgb( ...args ):Color { return Color.from( ...args ).toMode( \"rgb\" ); }\n \n /**\n * Create HSL Color. HSL color ranges are (0...360, 0...1, 0...1) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static hsl( ...args ):Color { return Color.from( ...args ).toMode( \"hsl\" ); }\n\n /**\n * Create HSB Color. HSB color ranges are (0...360, 0...1, 0...1) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static hsb( ...args ):Color { return Color.from( ...args ).toMode( \"hsb\" ); }\n \n /**\n * Create LAB Color. LAB color ranges are (0...100, -128...127, -128...127) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static lab( ...args ):Color { return Color.from( ...args ).toMode( \"lab\" ); }\n\n /**\n * Create LCH Color. LCH color ranges are (0...100, 0...100, 0...360) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static lch( ...args ):Color { return Color.from( ...args ).toMode( \"lch\" ); }\n\n /**\n * Create LUV Color. LUV color ranges are (0...100, -134...220, -140...122) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static luv( ...args ):Color { return Color.from( ...args ).toMode( \"luv\" ); }\n\n /**\n * Create XYZ Color. XYZ color ranges are (0...100, 0...100, 0...100) respectively. You may use [`Color.normalize`](#link) to convert the ranges to 0...1.\n * @param args Pt-like parameters which can be a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties.\n */\n static xyz( ...args ):Color { return Color.from( ...args ).toMode( \"xyz\" ); }\n\n\n /**\n * Get a Color object whose values are the maximum of its mode.\n * @param mode a mode string such as \"rgb\" or \"lab\"\n * @example Color.maxValue(\"rgb\") will return a rgb Color object with values (255,255,255)\n */\n static maxValues( mode:string ):Pt { return Color.ranges[mode].zipSlice( 1 ).$take( [0,1,2] ); }\n\n\n /**\n * Get a hex string such as \"#FF0000\". Same as `toString(\"hex\")`.\n */\n public get hex():string { return this.toString( \"hex\" ); }\n \n /**\n * Get a rgb string such as \"rgb(255,0,0)\". Same as `toString(\"rgb\")`.\n */\n public get rgb():string { return this.toString( \"rgb\" ); }\n\n /**\n * Get a rgba string such as \"rgb(255,0,0,0.5)\". Same as `toString(\"rgba\")`.\n */\n public get rgba():string { return this.toString( \"rgba\" ); }\n \n\n /**\n * Clone this Color.\n */\n clone():Color {\n const c = new Color( this );\n c.toMode( this._mode );\n return c;\n }\n\n /**\n * Convert this color from current color space to another color space.\n * @param mode a ColorType string: \"rgb\" \"hsl\" \"hsb\" \"lab\" \"lch\" \"luv\" \"xyz\";\n * @param convert if `true`, convert this Color to the new color space specified in `mode`. Default is `false`, which only sets the color mode without converting color values.\n */\n toMode( mode:ColorType, convert:boolean = false ):this { \n \n if ( convert ) {\n const fname = this._mode.toUpperCase() + \"to\" + mode.toUpperCase(); \n if ( Color[fname] ) {\n this.to( Color[fname]( this, this._isNorm, this._isNorm ) );\n } else {\n throw new Error( \"Cannot convert color with \" + fname );\n }\n }\n\n this._mode = mode; \n return this;\n }\n\n\n /**\n * Get this Color's mode.\n */\n get mode():ColorType { return this._mode; }\n\n\n // rgb\n /**\n * the `r` value in RGB color mode. Same as `x`.\n */\n get r():number { return this[0]; }\n set r( n:number ) { this[0] = n; }\n\n /**\n * the `g` value in RGB color mode. Same as `y`.\n */\n get g():number { return this[1]; }\n set g( n:number ) { this[1] = n; }\n\n /**\n * the `b` value in RGB/LAB/HSB color mode. Same as `z`.\n */\n get b():number { return this[2]; }\n set b( n:number ) { this[2] = n; }\n\n // hsl, hsb\n /**\n * the `h` value in HSL/HSB or LCH color mode. Same as either `x` or `z` depending on current color mode.\n */\n get h():number { return ( this._mode == \"lch\" ) ? this[2] : this[0]; }\n set h( n:number ) { \n const i = ( this._mode == \"lch\" ) ? 2 : 0; \n this[i] = n;\n }\n\n /**\n * the `s` value in HSL/HSB color mode. Same as `y`.\n */\n get s():number { return this[1]; }\n set s( n:number ) { this[1] = n; }\n\n /**\n * the `l` value in HSL or LCH/LAB color mode. Same as either `x` or `z` depending on current color mode.\n */\n get l():number { return ( this._mode == \"hsl\" ) ? this[2] : this[0]; }\n set l( n:number ) { \n const i = ( this._mode == \"hsl\" ) ? 2 : 0; \n this[i] = n;\n }\n\n // lab, lch, luv\n /**\n * the `a` value in LAB color mode. Same as `y`.\n */\n get a():number { return this[1]; }\n set a( n:number ) { this[1] = n; }\n\n /**\n * the `c` value in LCH color mode. Same as `y`.\n */\n get c():number { return this[1]; }\n set c( n:number ) { this[1] = n; }\n\n /**\n * the `u` value in LUV color mode. Same as `y`.\n */\n get u():number { return this[1]; }\n set u( n:number ) { this[1] = n; }\n\n /**\n * the `v` value in LUV color mode. Same as `z`.\n */\n get v():number { return this[2]; }\n set v( n:number ) { this[2] = n; }\n\n\n /**\n * Get alpha value\n */\n set alpha( n:number ) { if ( this.length > 3 ) this[3] = n; }\n get alpha():number { return ( this.length > 3 ) ? this[3] : 1; }\n\n /**\n * Check if color values are normalized (between 0 to 1). If conversion is needed, use [`Color.normalize`](#link) function.\n */\n get normalized():boolean { return this._isNorm; }\n set normalized( b:boolean ) { this._isNorm = b; }\n\n\n /**\n * Normalize the color values to between 0 to 1, or revert it back to the min/max values in current color mode.\n * @param toNorm a boolean value specifying whether to normalize (`true`) or revert (`false`)\n */\n normalize( toNorm:boolean = true ):Color {\n if ( this._isNorm == toNorm ) return this;\n\n const ranges = Color.ranges[ this._mode ];\n \n for ( let i = 0; i < 3; i++ ) {\n this[i] = ( !toNorm ) \n ? Num.mapToRange( this[i], 0, 1, ranges[i][0], ranges[i][1] ) \n : Num.mapToRange( this[i], ranges[i][0], ranges[i][1], 0, 1 );\n }\n \n this._isNorm = toNorm;\n\n return this;\n }\n\n\n /**\n * Like `normalize()` but returns a new Color.\n * @param toNorm a boolean value specifying whether to normalize (`true`) or revert (`false`)\n * @returns new Color\n */\n $normalize( toNorm:boolean = true ):Color { return this.clone().normalize( toNorm ); }\n\n\n /**\n * Convert this Color to a string. It can be used to get a hex or rgb string for use in rendering.\n * @param format \"hex\", \"rgb\", \"rgba\", or \"mode\" which means using current color mode label. Default is \"mode\".\n */\n toString( format:( \"hex\" | \"rgb\" | \"rgba\" | \"mode\" ) = \"mode\" ):string {\n if ( format == \"hex\" ) {\n const _hex = ( n:number ) => {\n const s = Math.floor( n ).toString( 16 );\n return ( s.length < 2 ) ? '0' + s : s;\n };\n return `#${_hex( this[0] )}${_hex( this[1] )}${_hex( this[2] )}`;\n\n } else if ( format == \"rgba\" ) {\n return `rgba(${Math.floor( this[0] )},${Math.floor( this[1] )},${Math.floor( this[2] )},${this.alpha})`;\n\n } else if ( format == \"rgb\" ) { \n return `rgb(${Math.floor( this[0] )},${Math.floor( this[1] )},${Math.floor( this[2] )})`;\n\n } else {\n return `${this._mode}(${this[0]},${this[1]},${this[2]},${this.alpha})`;\n }\n }\n\n\n /**\n * A static function to convert RGB to HSL.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new HSL Color\n */\n static RGBtoHSL( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const [r,g,b] = ( !normalizedInput ) ? rgb.$normalize() : rgb;\n\n const max = Math.max( r, g, b );\n const min = Math.min( r, g, b );\n let h = ( max + min ) / 2;\n let s = h;\n const l = h;\n\n if ( max == min ) {\n h = 0;\n s = 0; // achromatic\n } else {\n const d = max - min;\n s = ( l > 0.5 ) ? d / ( 2 - max - min ) : d / ( max + min );\n\n h = 0;\n if ( max === r ) {\n h = ( g - b ) / d + ( ( g < b ) ? 6 : 0 );\n } else if ( max === g ) {\n h = ( b - r ) / d + 2;\n } else if ( max === b ) {\n h = ( r - g ) / d + 4;\n }\n }\n\n return Color.hsl( ( ( normalizedOutput ) ? h / 60 : h * 60 ), s, l, rgb.alpha );\n }\n\n /**\n * A static function to convert HSL to RGB.\n * @param hsl a HSL Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static HSLtoRGB( hsl:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n let [h, s, l] = hsl;\n if ( !normalizedInput ) h = h / 360;\n \n if ( s == 0 ) return Color.rgb( l * 255, l * 255, l * 255, hsl.alpha );\n\n const q = ( l <= 0.5 ) ? l * ( 1 + s ) : l + s - ( l * s );\n const p = 2 * l - q;\n\n const convert = ( t ) => {\n t = ( t < 0 ) ? t + 1 : ( t > 1 ) ? t - 1 : t;\n if ( t * 6 < 1 ) {\n return p + ( q - p ) * t * 6;\n } else if ( t * 2 < 1 ) {\n return q;\n } else if ( t * 3 < 2 ) {\n return p + ( q - p ) * ( ( 2 / 3 ) - t ) * 6;\n } else {\n return p;\n }\n };\n\n const sc = ( normalizedOutput ) ? 1 : 255; \n \n return Color.rgb( \n sc * convert( ( h + 1 / 3 ) ),\n sc * convert( h ),\n sc * convert( ( h - 1 / 3 ) ),\n hsl.alpha\n );\n\n }\n \n /**\n * A static function to convert RGB to HSB.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new HSB Color\n */\n static RGBtoHSB( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const [r,g,b] = ( !normalizedInput ) ? rgb.$normalize() : rgb;\n\n const max = Math.max( r, g, b );\n const min = Math.min( r, g, b );\n const d = max - min;\n let h = 0;\n const s = ( max === 0 ) ? 0 : d / max;\n const v = max;\n\n if ( max != min ) {\n if ( max === r ) {\n h = ( g - b ) / d + ( ( g < b ) ? 6 : 0 );\n } else if ( max === g ) {\n h = ( b - r ) / d + 2;\n } else if ( max === b ) {\n h = ( r - g ) / d + 4;\n }\n }\n\n return Color.hsb( ( ( normalizedOutput ) ? h / 60 : h * 60 ), s, v, rgb.alpha );\n }\n\n\n /**\n * A static function to convert HSB to RGB.\n * @param hsb a HSB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static HSBtoRGB( hsb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n let [h, s, v] = hsb;\n if ( !normalizedInput ) h = h / 360;\n\n const i = Math.floor( h * 6 );\n const f = h * 6 - i;\n const p = v * ( 1 - s );\n const q = v * ( 1 - f * s );\n const t = v * ( 1 - ( 1 - f ) * s );\n \n const pick = [\n [v, t, p], [q, v, p], [p, v, t],\n [p, q, v], [t, p, v], [v, p, q] \n ];\n const c = pick[ i % 6 ];\n \n const sc = ( normalizedOutput ) ? 1 : 255; \n\n return Color.rgb( \n sc * c[0],\n sc * c[1],\n sc * c[2],\n hsb.alpha\n );\n }\n\n /**\n * A static function to convert RGB to LAB.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LAB Color\n */\n static RGBtoLAB( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? rgb.$normalize( false ) : rgb;\n return Color.XYZtoLAB( Color.RGBtoXYZ( c ), false, normalizedOutput );\n }\n\n\n /**\n * A static function to convert LAB to RGB.\n * @param lab a LAB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static LABtoRGB( lab:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? lab.$normalize( false ) : lab;\n return Color.XYZtoRGB( Color.LABtoXYZ( c ), false, normalizedOutput );\n }\n\n\n /**\n * A static function to convert RGB to LCH.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LCH Color\n */\n static RGBtoLCH( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? rgb.$normalize( false ) : rgb;\n return Color.LABtoLCH( Color.RGBtoLAB( c ), false, normalizedOutput );\n }\n \n\n /**\n * A static function to convert LCH to RGB.\n * @param lch a LCH Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static LCHtoRGB( lch:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? lch.$normalize( false ) : lch;\n return Color.LABtoRGB( Color.LCHtoLAB( c ), false, normalizedOutput );\n }\n\n\n /**\n * A static function to convert RGB to LUV.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LUV Color\n */\n static RGBtoLUV( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? rgb.$normalize( false ) : rgb;\n return Color.XYZtoLUV( Color.RGBtoXYZ( c ), false, normalizedOutput );\n }\n\n\n /**\n * A static function to convert LUV to RGB.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static LUVtoRGB( luv:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? luv.$normalize( false ) : luv;\n return Color.XYZtoRGB( Color.LUVtoXYZ( c ), false, normalizedOutput );\n }\n\n\n /**\n * A static function to convert RGB to XYZ.\n * @param rgb a RGB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new XYZ Color\n */\n static RGBtoXYZ( rgb:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( !normalizedInput ) ? rgb.$normalize() : rgb.clone();\n\n for ( let i = 0; i < 3; i++ ) {\n c[i] = ( c[i] > 0.04045 ) ? Math.pow( ( c[i] + 0.055 ) / 1.055, 2.4 ) : c[i] / 12.92;\n if ( !normalizedOutput ) c[i] = c[i] * 100;\n }\n\n const cc = Color.xyz(\n c[0] * 0.4124564 + c[1] * 0.3575761 + c[2] * 0.1804375,\n c[0] * 0.2126729 + c[1] * 0.7151522 + c[2] * 0.0721750,\n c[0] * 0.0193339 + c[1] * 0.1191920 + c[2] * 0.9503041,\n rgb.alpha\n );\n\n return ( normalizedOutput ) ? cc.normalize() : cc;\n }\n\n\n /**\n * A static function to convert XYZ to RGB.\n * @param xyz a XYZ Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new RGB Color\n */\n static XYZtoRGB( xyz:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n\n const [x,y,z] = ( !normalizedInput ) ? xyz.$normalize() : xyz;\n\n const rgb = [\n x * 3.2406254773200533 + y * -1.5372079722103187 + z * -0.4986285986982479,\n x * -0.9689307147293197 + y * 1.8757560608852415 + z * 0.041517523842953964,\n x * 0.055710120445510616 + y * -0.2040210505984867 + z * 1.0569959422543882\n ];\n\n // convert xyz to rgb. Note that not all colors are visible in rgb, so here we bound rgb between 0 to 1\n for ( let i = 0; i < 3; i++ ) {\n rgb[i] = ( rgb[i] > 0.0031308 ) ? ( 1.055 * Math.pow( rgb[i], 1 / 2.4 ) - 0.055 ) : ( 12.92 * rgb[i] );\n rgb[i] = Math.max( 0, Math.min( 1, rgb[i] ) );\n if ( !normalizedOutput ) rgb[i] = Math.round( rgb[i] * 255 );\n }\n\n const cc = Color.rgb( rgb[0], rgb[1], rgb[2], xyz.alpha );\n return ( normalizedOutput ) ? cc.normalize() : cc;\n }\n\n\n /**\n * A static function to convert XYZ to LAB.\n * @param xyz a XYZ Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LAB Color\n */\n static XYZtoLAB( xyz:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? xyz.$normalize( false ) : xyz.clone();\n const eps = 0.00885645167;\n const kap = 903.296296296;\n\n // adjust for D65 \n c.divide( Color.D65 );\n\n const fn = ( n ) => ( n > eps ) ? Math.pow( n, 1 / 3 ) : ( kap * n + 16 ) / 116;\n const cy = fn( c[1] );\n\n const cc = Color.lab(\n ( 116 * cy ) - 16,\n 500 * ( fn( c[0] ) - cy ),\n 200 * ( cy - fn( c[2] ) ),\n xyz.alpha\n );\n return ( normalizedOutput ) ? cc.normalize() : cc;\n }\n\n /**\n * A static function to convert LAB to XYZ.\n * @param lab a LAB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new XYZ Color\n */\n static LABtoXYZ( lab:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n\n const c = ( normalizedInput ) ? lab.$normalize( false ) : lab;\n const y = ( c[0] + 16 ) / 116;\n const x = ( c[1] / 500 ) + y;\n const z = y - c[2] / 200;\n const eps = 0.00885645167;\n const kap = 903.296296296;\n\n const d = Color.D65;\n const xxx = Math.pow( x, 3 );\n const zzz = Math.pow( z, 3 );\n\n // adjusted\n const cc = Color.xyz(\n d[0] * ( ( xxx > eps ) ? xxx : ( 116 * x - 16 ) / kap ),\n d[1] * ( ( c[0] > kap * eps ) ? Math.pow( ( c[0] + 16 ) / 116, 3 ) : c[0] / kap ),\n d[2] * ( ( zzz > eps ) ? zzz : ( 116 * z - 16 ) / kap ),\n lab.alpha\n );\n\n return ( normalizedOutput ) ? cc.normalize() : cc;\n }\n\n\n /**\n * A static function to convert XYZ to LUV.\n * @param xyz a XYZ Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LUV Color\n */\n static XYZtoLUV( xyz:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n let [x,y,z] = ( normalizedInput ) ? xyz.$normalize( false ) : xyz;\n const u = ( 4 * x ) / ( x + ( 15 * y ) + ( 3 * z ) );\n const v = ( 9 * y ) / ( x + ( 15 * y ) + ( 3 * z ) );\n\n y = y / 100;\n y = ( y > 0.008856 ) ? Math.pow( y, 1 / 3 ) : ( 7.787 * y + 16 / 116 );\n\n const refU = ( 4 * Color.D65[0] ) / ( Color.D65[0] + ( 15 * Color.D65[1] ) + ( 3 * Color.D65[2] ) );\n const refV = ( 9 * Color.D65[1] ) / ( Color.D65[0] + ( 15 * Color.D65[1] ) + ( 3 * Color.D65[2] ) );\n\n const L = ( 116 * y ) - 16;\n return Color.luv(\n L, 13 * L * ( u - refU ), 13 * L * ( v - refV ), xyz.alpha\n );\n }\n\n\n /**\n * A static function to convert LUV to XYZ.\n * @param luv a LUV Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new XYZ Color\n */\n static LUVtoXYZ( luv:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n let [l,u,v] = ( normalizedInput ) ? luv.$normalize( false ) : luv;\n let y = ( l + 16 ) / 116;\n const cubeY = y * y * y;\n y = ( cubeY > 0.008856 ) ? cubeY : ( y - 16 / 116 ) / 7.787;\n\n const refU = ( 4 * Color.D65[0] ) / ( Color.D65[0] + ( 15 * Color.D65[1] ) + ( 3 * Color.D65[2] ) );\n const refV = ( 9 * Color.D65[1] ) / ( Color.D65[0] + ( 15 * Color.D65[1] ) + ( 3 * Color.D65[2] ) );\n\n u = u / ( 13 * l ) + refU;\n v = v / ( 13 * l ) + refV;\n\n y = y * 100;\n const x = -1 * ( 9 * y * u ) / ( ( u - 4 ) * v - u * v );\n const z = ( 9 * y - ( 15 * v * y ) - ( v * x ) ) / ( 3 * v );\n\n return Color.xyz( x, y, z, luv.alpha );\n }\n\n\n /**\n * A static function to convert LAB to LCH.\n * @param lab a LAB Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LCH Color\n */\n static LABtoLCH( lab:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? lab.$normalize( false ) : lab;\n const h = Geom.toDegree( Geom.boundRadian( Math.atan2( c[2], c[1] ) ) ); // 0 to 360 degrees\n return Color.lch(\n c[0], Math.sqrt( c[1] * c[1] + c[2] * c[2] ), h, lab.alpha\n );\n }\n\n\n /**\n * A static function to convert LCH to LAB.\n * @param lch a LCH Color\n * @param normalizedInput a boolean specifying whether input color is normalized. Default is not normalized: `false`.\n * @param normalizedOutput a boolean specifying whether output color shoud be normalized. Default is not normalized: `false`.\n * @returns a new LAB Color\n */\n static LCHtoLAB( lch:Color, normalizedInput:boolean = false, normalizedOutput:boolean = false ):Color {\n const c = ( normalizedInput ) ? lch.$normalize( false ) : lch;\n const rad = Geom.toRadian( c[2] );\n return Color.lab(\n c[0], Math.cos( rad ) * c[1], Math.sin( rad ) * c[1], lch.alpha\n );\n }\n\n\n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {MultiTouchSpace} from './Space';\nimport {Form, VisualForm, Font} from \"./Form\";\nimport {Util} from './Util';\nimport {Pt, Bound} from './Pt';\nimport {PtLike, GroupLike, IPlayer, DOMFormContext, PtLikeIterable} from \"./Types\";\n\n\n\n/**\n * DOMSpace is a space for DOM elements. Usually its subclasses such as [`HTMLSpace`](#link) and [`#SVGSpace`](#link) should be used instead. \n * Learn more about spaces in [this guide](../guide/space-0500).\n */\nexport class DOMSpace extends MultiTouchSpace {\n \n protected _canvas:HTMLElement | SVGElement;\n protected _container:Element;\n \n id: string = \"domspace\";\n protected _autoResize = true;\n protected _bgcolor = \"#e1e9f0\";\n protected _css = {};\n \n \n /**\n * Create a DOMSpace for HTML DOM elements\n * @param elem Specify an element by its \"id\" attribute as string, or by the element object itself. Use css to customize its appearance if needed.\n * @param callback an optional callback `function(boundingBox, spaceElement)` to be called when element is appended and ready. Alternatively, a \"ready\" event will also be fired from the element when it's appended, which can be traced with `spaceInstance.element.addEventListener(\"ready\")`\n * @example `new DOMSpace( \"#myElementID\" )`\n */\n constructor( elem:string | Element, callback?:Function ) {\n super();\n \n let _selector:Element = null;\n let _existed = false;\n this.id = \"pts\";\n \n // check element or element id string\n if ( elem instanceof Element ) {\n _selector = elem;\n this.id = \"pts_existing_space\";\n } else {\n _selector = document.querySelector( <string>elem );\n _existed = true;\n this.id = elem.substr( 1 );\n }\n \n // if selector is not defined, create a canvas\n if ( !_selector ) { \n this._container = DOMSpace.createElement( \"div\", \"pts_container\" );\n this._canvas = DOMSpace.createElement( \"div\", \"pts_element\" ) as HTMLElement;\n this._container.appendChild( this._canvas );\n document.body.appendChild( this._container );\n _existed = false;\n \n } else {\n this._canvas = _selector as HTMLElement;\n this._container = _selector.parentElement;\n }\n \n // no mutation observer, so we set a timeout for ready event\n setTimeout( this._ready.bind( this, callback ), 50 );\n\n }\n \n \n /**\n * Helper function to create a DOM element.\n * @param elem element tag name\n * @param id element id attribute\n * @param appendTo Optional, if specified, the created element will be appended to this element\n */\n static createElement( elem:string = \"div\", id:string, appendTo?:Element ):Element {\n let d = document.createElement( elem );\n if ( id ) d.setAttribute( \"id\", id );\n if ( appendTo && appendTo.appendChild ) appendTo.appendChild( d );\n return d;\n \n }\n \n \n /**\n * Handle callbacks after element is mounted in DOM.\n * @param callback \n */\n private _ready( callback:Function ) {\n if ( !this._container ) throw new Error( `Cannot initiate #${this.id} element` );\n \n this._isReady = true;\n \n this._resizeHandler( null );\n this.clear( this._bgcolor );\n this._canvas.dispatchEvent( new Event( \"ready\" ) );\n \n \n for ( let k in this.players ) {\n if ( this.players.hasOwnProperty( k ) ) {\n if ( this.players[k].start ) this.players[k].start( this.bound.clone(), this );\n }\n }\n \n this._pointer = this.center;\n\n this.refresh( false ); // No need to clear and redraw for every frame in DOM\n \n if ( callback ) callback( this.bound, this._canvas );\n }\n \n \n /**\n * Set up various options for DOMSpace. This is usually set during instantiation, eg `new DOMSpace(...).setup( {opt} )`.\n * @param opt an object with these optional properties: **bgcolor** is a hex or rgba string to set initial background color of the canvas, or use `false` or \"transparent\" to set a transparent background; **resize** a boolean to set whether `<canvas>` size should auto resize to match its container's size, which can also be set using `autoSize()`.\n * @example `space.setup({ bgcolor: \"#f00\", resize: true })`\n */\n setup( opt:{bgcolor?:string, resize?:boolean} ):this {\n if ( opt.bgcolor ) {\n this._bgcolor = opt.bgcolor;\n }\n \n this.autoResize = ( opt.resize != undefined ) ? opt.resize : false;\n \n return this;\n }\n \n\n /**\n * Not implemented. See SVGSpace and HTMLSpace for implementation.\n */\n getForm():Form {\n return null;\n }\n \n /**\n * Set whether the canvas element should resize when its container is resized. \n * @param auto a boolean value indicating if auto size is set\n */\n set autoResize( auto:boolean ) {\n this._autoResize = auto;\n if ( auto ) {\n window.addEventListener( 'resize', this._resizeHandler.bind( this ) );\n } else {\n delete this._css['width'];\n delete this._css['height'];\n window.removeEventListener( 'resize', this._resizeHandler.bind( this ) );\n }\n }\n get autoResize(): boolean { return this._autoResize; }\n \n \n /**\n * This overrides Space's `resize` function. It's used as a callback function for window's resize event and not usually called directly. You can keep track of resize events with `resize: (bound, evt)` callback in your player objects (See [`Space.add`](#link) function). \n * @param b a Bound object to resize to\n * @param evt Optionally pass a resize event\n */\n resize( b:Bound, evt?:Event ):this {\n \n this.bound = b;\n this.styles( {width: `${b.width}px`, height: `${b.height}px`}, true );\n\n for ( let k in this.players ) {\n if ( this.players.hasOwnProperty( k ) ) {\n let p = this.players[k];\n if ( p.resize ) p.resize( this.bound, evt );\n }\n }\n \n return this;\n }\n \n \n /**\n * Window resize handling.\n * @param evt \n */\n protected _resizeHandler( evt:Event ) {\n \n let b = Bound.fromBoundingRect( this._container.getBoundingClientRect() );\n\n if ( this._autoResize ) {\n this.styles( {width: \"100%\", height: \"100%\"}, true );\n } else {\n this.styles( {width: `${b.width}px`, height: `${b.height}px`}, true );\n }\n\n this.resize( b, evt );\n \n }\n \n \n /**\n * Get this DOM element.\n */\n get element():Element {\n return this._canvas;\n }\n \n \n /**\n * Get the parent DOM element that contains this DOM element.\n */\n get parent():Element {\n return this._container;\n }\n \n \n /**\n * A property to indicate if the Space is ready.\n */\n get ready():boolean { return this._isReady; }\n \n \n /**\n * Clear the element's contents, and optionally set a new background color. This overrides Space's `clear` function.\n * @param bg Optionally specify a custom background color in hex or rgba string, or \"transparent\". If not defined, it will use its `bgcolor` property as background color to clear the canvas.\n */\n clear( bg?:string ):this {\n if ( bg ) this.background = bg;\n this._canvas.innerHTML = \"\";\n return this;\n } \n \n \n /**\n * Set a background color on the container element.\n @param bg background color as hex or rgba string\n */\n set background( bg:string ) {\n this._bgcolor = bg;\n ( this._container as HTMLElement ).style.backgroundColor = this._bgcolor;\n }\n get background():string { return this._bgcolor; }\n \n \n /**\n * Add or update a style definition, and optionally update that style in the Element.\n * @param key style name\n * @param val style value\n * @param update a boolean to update the element's style immediately if set to `true`. Default is `false`.\n */\n style( key:string, val:string, update:boolean = false ):this {\n this._css[key] = val;\n if ( update ) this._canvas.style[key] = val;\n return this;\n }\n \n \n /**\n * Add of update a list of style definitions, and optionally update those styles in the Element.\n * @param styles a key-value objects of style definitions \n * @param update a boolean to update the element's style immediately if set to `true`. Default is `false`.\n * @return this\n */\n styles( styles:object, update:boolean = false ):this {\n for ( let k in styles ) {\n if ( styles.hasOwnProperty( k ) ) this.style( k, styles[k], update );\n }\n return this;\n }\n \n \n /**\n * A static helper function to add or update Element attributes.\n * @param elem Element to update\n * @param data an object with key-value pairs\n * @returns this DOM element \n */\n static setAttr( elem:Element, data:object ):Element {\n for ( let k in data ) {\n if ( data.hasOwnProperty( k ) ) {\n elem.setAttribute( k, data[k] );\n }\n }\n return elem;\n }\n \n \n /**\n * A static helper function to compose an inline style string from a object of styles.\n * @param elem Element to update\n * @param data an object with key-value pairs\n * @exmaple `DOMSpace.getInlineStyles( {width: \"100px\", \"font-size\": \"10px\"} )`\n */\n static getInlineStyles( data:object ):string {\n let str = \"\";\n for ( let k in data ) {\n if ( data.hasOwnProperty( k ) ) {\n if ( data[k] ) str += `${k}: ${data[k]}; `;\n }\n }\n return str;\n }\n \n \n /**\n * Dispose of browser resources held by this space and remove all players. Call this before unmounting the DOM.\n */\n dispose():this {\n // remove event listeners\n window.removeEventListener( 'resize', this._resizeHandler.bind( this ) );\n // stop animation loop\n this.stop();\n // remove players from space\n this.removeAll();\n\n return this;\n }\n \n}\n\n\n/**\n * **[Experimental]** HTMLSpace is a subclass of DOMSpace that works with HTML elements. Note that this is currently experimental and may change in future. See [a demo here](../demo/index.html?name=htmlform.scope).\n */\nexport class HTMLSpace extends DOMSpace {\n\n /**\n * Get a new `HTMLForm` which provides visualization functions in html elements. \n * @see `HTMLForm`\n */\n getForm():Form {\n return new HTMLForm( this );\n }\n\n /**\n * A static function to add a DOM element inside a node. Usually you don't need to use this directly. See methods in [`HTMLForm`](#link) instead.\n * @param parent the parent element, or `null` to use current `<svg>` as parent.\n * @param name a string of element name, such as `rect` or `circle`\n * @param id id attribute of the new element\n * @param autoClass add a class based on the id (from char 0 to index of \"-\"). Default is true.\n */\n static htmlElement( parent:Element, name:string, id?:string, autoClass:boolean = true ):HTMLElement {\n \n if ( !parent || !parent.appendChild ) throw new Error( \"parent is not a valid DOM element\" );\n \n let elem = document.querySelector( `#${id}` );\n if ( !elem ) {\n elem = document.createElement( name );\n elem.setAttribute( \"id\", id );\n \n if ( autoClass ) elem.setAttribute( \"class\",id.substring( 0, id.indexOf( \"-\" ) ) );\n parent.appendChild( elem );\n }\n return elem as HTMLElement;\n }\n\n\n /**\n * Remove an item from this space.\n * @param item a player item with an auto-assigned `animateID` property\n */\n remove( player:IPlayer ):this {\n let temp = this._container.querySelectorAll( \".\" + HTMLForm.scopeID( player ) );\n \n temp.forEach( ( el:Element ) => { \n el.parentNode.removeChild( el );\n } );\n \n return super.remove( player );\n }\n \n \n /**\n * Remove all items from this space.\n */\n removeAll():this {\n this._container.innerHTML = \"\";\n return super.removeAll();\n }\n}\n\n\n/**\n * **[Experimental]** HTMLForm is an implementation of abstract class [`VisualForm`](#link). It provide methods to express Pts on [`HTMLSpace`](#link). Note that this is currently experimental and may change in future.\n */\nexport class HTMLForm extends VisualForm {\n\n /** \n * store common styles so that they can be restored to canvas context when using multiple forms. See `reset()`.\n */\n protected _style = {\n \"filled\": true,\n \"stroked\": true,\n \"background\": \"#f03\",\n \"border-color\": \"#fff\",\n \"color\": \"#000\",\n \"border-width\": \"1px\",\n \"border-radius\": \"0\",\n \"border-style\": \"solid\",\n \"opacity\": 1,\n \"position\": \"absolute\",\n \"top\": 0,\n \"left\": 0,\n \"width\": 0,\n \"height\": 0\n };\n\n protected _ctx:DOMFormContext = {\n group: null,\n groupID: \"pts\",\n groupCount: 0,\n currentID: \"pts0\",\n currentClass: \"\",\n style: {},\n };\n\n static groupID:number = 0;\n static domID:number = 0;\n \n protected _space:HTMLSpace;\n protected _ready:boolean = false;\n \n /**\n * Create a new `HTMLForm`. Alternatively, you can use [`HTMLSpace.getForm`](#link) function to get an instance of HTMLForm.\n * @param space the space to use\n */\n constructor( space:HTMLSpace ) {\n super();\n this._space = space;\n \n this._space.add( { start: () => {\n this._ctx.group = this._space.element;\n this._ctx.groupID = \"pts_dom_\" + ( HTMLForm.groupID++ );\n this._ctx.style = Object.assign( {}, this._style );\n this._ready = true;\n }} );\n }\n \n /**\n * Get the corresponding space for this form\n */\n get space():HTMLSpace { return this._space; }\n\n\n /**\n * Usually not used directly. This updates a style in `_ctx` context or throw an Error if the style doesn't exist.\n * @param k style key\n * @param v style value\n * @param unit Optional unit like 'px' to append to value\n */\n protected styleTo( k, v, unit:string = '' ) { \n if ( this._ctx.style[k] === undefined ) throw new Error( `${k} style property doesn't exist` );\n this._ctx.style[k] = `${v}${unit}`; \n }\n \n \n /**\n * Set current alpha value.\n * @example `form.alpha(0.6)`\n * @param a alpha value between 0 and 1\n */\n alpha( a:number ):this {\n this.styleTo( \"opacity\", a );\n return this;\n }\n\n\n /**\n * Set current fill style. Provide a valid color string or `false` to specify no fill color.\n * @example `form.fill(\"#F90\")`, `form.fill(\"rgba(0,0,0,.5\")`, `form.fill(false)`\n * @param c fill color\n */\n fill( c:string | boolean ):this {\n if ( typeof c == \"boolean\" ) {\n this.styleTo( \"filled\", c );\n if ( !c ) this.styleTo( \"background\", \"transparent\" );\n } else {\n this.styleTo( \"filled\", true );\n this.styleTo( \"background\", c );\n }\n return this;\n }\n\n /**\n * Set current stroke style. Provide a valid color string or `false` to specify no stroke color.\n * @example `form.stroke(\"#F90\")`, `form.stroke(\"rgba(0,0,0,.5\")`, `form.stroke(false)`, `form.stroke(\"#000\", 0.5, 'round', 'square')`\n * @param c stroke color which can be as color, gradient, or pattern. (See [canvas documentation](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle))\n * @param width Optional value (can be floating point) to set line width\n * @param linejoin not implemented in HTMLForm\n * @param linecap not implemented in HTMLForm\n */\n stroke( c:string | boolean, width?:number, linejoin?:string, linecap?:string ):this {\n if ( typeof c == \"boolean\" ) {\n this.styleTo( \"stroked\", c );\n if ( !c ) this.styleTo( \"border-width\", 0 );\n } else {\n this.styleTo( \"stroked\", true );\n this.styleTo( \"border-color\", c );\n this.styleTo( \"border-width\", ( width || 1 ) + \"px\" );\n }\n return this;\n }\n\n\n /**\n * Set current text color style. Provide a valid color string.\n * @example `form.fill(\"#F90\")`, `form.fill(\"rgba(0,0,0,.5\")`, `form.fill(false)`\n * @param c fill color\n */\n fillText( c:string ):this {\n this.styleTo( \"color\", c );\n return this;\n }\n\n\n /**\n * Add custom class to the created element.\n * @param c custom class name or `false` to reset it\n * @example `form.fill(\"#f00\").cls(\"myClass\").rects(r)` `form.cls(false).circles(c)`\n */\n cls( c:string | boolean ) {\n if ( typeof c == \"boolean\" ) {\n this._ctx.currentClass = \"\";\n } else {\n this._ctx.currentClass = c;\n }\n return this;\n }\n \n\n /**\n * Set the current font.\n * @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties\n * @param weight Optional font-weight string such as \"bold\"\n * @param style Optional font-style string such as \"italic\"\n * @param lineHeight Optional line-height number suchas 1.5\n * @param family Optional font-family such as \"Helvetica, sans-serif\"\n * @example `form.font( myFont )`, `form.font(14, \"bold\")`\n */\n font( sizeOrFont:number | Font, weight?:string, style?:string, lineHeight?:number, family?:string ):this {\n if ( typeof sizeOrFont == \"number\" ) {\n \n this._font.size = sizeOrFont;\n if ( family ) this._font.face = family;\n if ( weight ) this._font.weight = weight;\n if ( style ) this._font.style = style;\n if ( lineHeight ) this._font.lineHeight = lineHeight;\n\n } else {\n this._font = sizeOrFont;\n }\n\n this._ctx.style['font'] = this._font.value;\n\n return this;\n }\n\n /**\n * Reset the context's common styles to this form's styles. This supports using multiple forms on the same canvas context.\n */\n reset():this {\n this._ctx.style = Object.assign( {}, this._style );\n\n this._font = new Font( 10, \"sans-serif\" );\n this._ctx.style['font'] = this._font.value;\n\n return this;\n }\n\n /**\n * Set this form's group scope by an ID, and optionally define the group's parent element. A group scope keeps track of elements by their generated IDs, and updates their properties as needed. See also `scope()`.\n * @param group_id a string to use as prefix for the group's id. For example, group_id \"hello\" will create elements with id like \"hello-1\", \"hello-2\", etc\n * @param group Optional DOM element to define this group's parent element\n * @returns this form's context\n */\n updateScope( group_id:string, group?:Element ):object {\n this._ctx.group = group;\n this._ctx.groupID = group_id;\n this._ctx.groupCount = 0;\n this.nextID();\n return this._ctx;\n }\n \n\n /**\n * Set the current group scope to an item added into space, in order to keep track of any point, circle, etc created within it. The item must have an `animateID` property, so that elements created within the item will have generated IDs like \"item-{animateID}-{count}\".\n * @param item a \"player\" item that's added to space (see `space.add(...)`) and has an `animateID` property\n * @returns this form's context\n */\n scope( item:IPlayer ) {\n if ( !item || item.animateID == null ) throw new Error( \"item not defined or not yet added to Space\" );\n return this.updateScope( HTMLForm.scopeID( item ), this.space.element );\n }\n \n \n /**\n * Get next available id in the current group.\n * @returns an id string\n */\n nextID():string {\n this._ctx.groupCount++;\n this._ctx.currentID = `${this._ctx.groupID}-${this._ctx.groupCount}`;\n return this._ctx.currentID;\n }\n \n\n /**\n * A static function to generate an ID string based on a context object.\n * @param ctx a context object for an HTMLForm\n */\n static getID( ctx ):string {\n return ctx.currentID || `p-${HTMLForm.domID++}`;\n }\n\n\n /**\n * A static function to generate an ID string for a scope, based on a \"player\" item in the Space.\n * @param item a \"player\" item that's added to space (see `space.add(...)`) and has an `animateID` property\n */\n static scopeID( item:IPlayer ):string {\n return `item-${item.animateID}`;\n }\n \n \n /**\n * A static function to help adding style object to an element. This put all styles into `style` attribute instead of individual attributes, so that the styles can be parsed by Adobe Illustrator.\n * @param elem A DOM element to add to\n * @param styles an object of style properties\n * @example `HTMLForm.style(elem, {fill: \"#f90\", stroke: false})`\n * @returns DOM element \n */\n static style( elem:Element, styles:object ):Element {\n let st = [];\n\n if ( !styles[\"filled\"] ) st.push( \"background: none\" );\n if ( !styles[\"stroked\"] ) st.push( \"border: none\" );\n \n for ( let k in styles ) {\n if ( styles.hasOwnProperty( k ) && k != \"filled\" && k != \"stroked\" ) {\n let v = styles[k];\n if ( v ) {\n if ( !styles[\"filled\"] && k.indexOf( 'background' ) === 0 ) {\n continue;\n } else if ( !styles[\"stroked\"] && k.indexOf( 'border-width' ) === 0 ) {\n continue;\n } else {\n st.push( `${k}: ${v}` );\n }\n }\n }\n }\n \n return HTMLSpace.setAttr( elem, {style: st.join( \";\" )} );\n }\n\n /**\n * A helper function to set top, left, width, height of DOM element.\n * @param x left position\n * @param y top position\n * @param w width\n * @param h height\n */\n static rectStyle( ctx:DOMFormContext, pt:PtLike, size:PtLike ):DOMFormContext {\n ctx.style[\"left\"] = pt[0] + \"px\"; \n ctx.style[\"top\"] = pt[1] + \"px\"; \n ctx.style[\"width\"] = size[0] + \"px\"; \n ctx.style[\"height\"] = size[1] + \"px\"; \n return ctx;\n }\n \n /**\n * A helper function to set the top and left position styling of text DOM context.\n * @param ctx context to add style to\n * @param pt a Pt object or numeric array determining the top-left position of the text\n */\n static textStyle( ctx:DOMFormContext, pt:PtLike ):DOMFormContext {\n ctx.style[\"left\"] = pt[0] + \"px\"; \n ctx.style[\"top\"] = pt[1] + \"px\"; \n return ctx;\n }\n\n /**\n * A static function to draws a point.\n * @param ctx a context object of HTMLForm\n * @param pt a Pt object or numeric array\n * @param radius radius of the point. Default is 5.\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\n * @example `HTMLForm.point( p )`, `HTMLForm.point( p, 10, \"circle\" )`\n */\n static point( ctx:DOMFormContext, pt:PtLike, radius:number = 5, shape:string = \"square\" ):Element {\n if ( shape === \"circle\" ) {\n return HTMLForm.circle( ctx, pt, radius );\n } else {\n return HTMLForm.square( ctx, pt, radius );\n }\n }\n\n\n /**\n * Draws a point.\n * @param p a Pt object\n * @param radius radius of the point. Default is 5.\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\n * @example `form.point( p )`, `form.point( p, 10, \"circle\" )`\n */\n point( pt:PtLike, radius:number = 5, shape:string = \"square\" ):this {\n this.nextID();\n if ( shape == \"circle\" ) this.styleTo( \"border-radius\", \"100%\" );\n HTMLForm.point( this._ctx, pt, radius, shape );\n return this;\n }\n\n \n /**\n * A static function to draw a circle.\n * @param ctx a context object of HTMLForm\n * @param pt center position of the circle\n * @param radius radius of the circle\n */\n static circle( ctx:DOMFormContext, pt:PtLike, radius:number = 10 ):Element {\n let elem = HTMLSpace.htmlElement( ctx.group, \"div\", HTMLForm.getID( ctx ) );\n HTMLSpace.setAttr( elem, {class: `pts-form pts-circle ${ctx.currentClass}` } );\n HTMLForm.rectStyle( ctx, new Pt( pt ).$subtract( radius ), new Pt( radius * 2, radius * 2 ) );\n HTMLForm.style( elem, ctx.style );\n return elem;\n } \n\n\n /**\n * Draw a circle.\n * @param pts usually a Group of 2 Pts, but it can also take an array of two numeric arrays [ [position], [size] ]\n * @see [`Circle.fromCenter`](./?p=Op_Circle#function_fromCenter)\n */\n circle( pts:GroupLike | number[][] ):this {\n this.nextID();\n this.styleTo( \"border-radius\", \"100%\" );\n HTMLForm.circle( this._ctx, pts[0], pts[1][0] );\n return this;\n }\n\n\n /**\n * A static function to draw a square.\n * @param ctx a context object of HTMLForm\n * @param pt center position of the square\n * @param halfsize half size of the square\n */\n static square( ctx:DOMFormContext, pt:PtLike, halfsize:number ) {\n let elem = HTMLSpace.htmlElement( ctx.group, \"div\", HTMLForm.getID( ctx ) );\n HTMLSpace.setAttr( elem, {class: `pts-form pts-square ${ctx.currentClass}` } );\n HTMLForm.rectStyle( ctx, new Pt( pt ).$subtract( halfsize ), new Pt( halfsize * 2, halfsize * 2 ) );\n HTMLForm.style( elem, ctx.style );\n return elem;\n }\n \n\n /**\n * Draw a square, given a center and its half-size.\n * @param pt center Pt\n * @param halfsize half-size\n */\n square( pt:PtLike, halfsize:number ):this {\n this.nextID();\n HTMLForm.square( this._ctx, pt, halfsize );\n return this;\n } \n\n\n /**\n * A static function to draw a rectangle.\n * @param ctx a context object of HTMLForm\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.\n */\n static rect( ctx:DOMFormContext, pts:PtLikeIterable ):Element {\n let p = Util.iterToArray( pts );\n if ( !Util.arrayCheck( p ) ) return;\n\n let elem = HTMLSpace.htmlElement( ctx.group, \"div\", HTMLForm.getID( ctx ) ); \n HTMLSpace.setAttr( elem, { class: `pts-form pts-rect ${ctx.currentClass}` } );\n HTMLForm.rectStyle( ctx, p[0], p[1] );\n HTMLForm.style( elem, ctx.style );\n return elem;\n }\n\n\n /**\n * Draw a rectangle.\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions.\n */\n rect( pts:PtLikeIterable ):this {\n this.nextID();\n this.styleTo( \"border-radius\", \"0\" );\n HTMLForm.rect( this._ctx, pts );\n return this;\n }\n\n\n /**\n * A static function to draw text.\n * @param ctx a context object of HTMLForm\n * @param `pt` a Point object to specify the anchor point\n * @param `txt` a string of text to draw\n * @param `maxWidth` specify a maximum width per line\n */\n static text( ctx:DOMFormContext, pt:PtLike, txt:string ):Element {\n let elem = HTMLSpace.htmlElement( ctx.group, \"div\", HTMLForm.getID( ctx ) );\n \n HTMLSpace.setAttr( elem, { class: `pts-form pts-text ${ctx.currentClass}` } );\n \n elem.textContent = txt;\n HTMLForm.textStyle( ctx, pt );\n HTMLForm.style( elem, ctx.style );\n \n return elem;\n }\n\n /**\n * Draw text on canvas.\n * @param `pt` a Pt or numeric array to specify the anchor point\n * @param `txt` text\n * @param `maxWidth` specify a maximum width per line\n */\n text( pt:PtLike, txt:string ): this {\n this.nextID();\n HTMLForm.text( this._ctx, pt, txt );\n return this;\n }\n \n\n /**\n * A convenient way to draw some text on canvas for logging or debugging. It'll be draw on the top-left of the canvas as an overlay.\n * @param txt text\n */\n log( txt ):this {\n this.fill( \"#000\" ).stroke( \"#fff\", 0.5 ).text( [10,14], txt ); \n return this;\n }\n \n\n /**\n * Arc is not implemented in HTMLForm.\n */\n arc( pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ):this {\n Util.warn( \"arc is not implemented in HTMLForm\" );\n return this;\n }\n\n\n /**\n * Line is not implemented in HTMLForm.\n */\n line( pts:GroupLike | number[][] ):this {\n Util.warn( \"line is not implemented in HTMLForm\" );\n return this;\n }\n\n\n /**\n * Polygon is not implemented in HTMLForm.\n * @param pts \n */\n polygon( pts:GroupLike | number[][] ):this {\n Util.warn( \"polygon is not implemented in HTMLForm\" );\n return this;\n }\n}\n\n\n","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {VisualForm, Font} from \"./Form\";\nimport {Geom} from './Num';\nimport {Const, Util} from './Util';\nimport {Pt, Group, Bound} from './Pt';\nimport {Rectangle} from \"./Op\";\nimport {DOMSpace} from \"./Dom\";\nimport {PtLike, PtLikeIterable, IPlayer, DOMFormContext} from \"./Types\";\n\n\n\n/**\n * **[Experimental]** SVGSpace extends [`DOMSpace`](#link) to support SVG elements. Use it with [`SVGForm`](#link) to express Pts in svg. \n * You may easily switch between html canvas and svg renderings with minimal code changes. Check out the [Space guide](../guide/Space-0500.html) for details, and see [a demo here](../demo/index.html?name=svgform.scope).\n */\nexport class SVGSpace extends DOMSpace {\n \n protected _bgcolor:string = \"#999\";\n\n \n /**\n * Create a SVGSpace which represents a Space for SVG elements.\n * @param elem Specify an element by its \"id\" attribute as string, or by the element object itself. An element can be an existing `<svg>`, or a `<div>` container in which a new `<svg>` will be created. If left empty, a `<div id=\"pt_container\"><svg id=\"pt\" /></div>` will be added to DOM. Use css to customize its appearance if needed.\n * @param callback an optional callback `function(boundingBox, spaceElement)` to be called when canvas is appended and ready. Alternatively, a \"ready\" event will also be fired from the `<svg>` element when it's appended, which can be traced with `spaceInstance.canvas.addEventListener(\"ready\")`\n * @example `new SVGSpace( \"#myElementID\" )`\n */\n constructor( elem:string | Element, callback?:Function ) {\n super( elem, callback );\n \n if ( this._canvas.nodeName.toLowerCase() != \"svg\" ) {\n let s = SVGSpace.svgElement( this._canvas, \"svg\", `${this.id}_svg` );\n this._container = this._canvas;\n this._canvas = s as SVGElement;\n }\n }\n \n\n /**\n * Get a new [`SVGForm`](#link) for drawing.\n * @see `SVGForm`\n */\n getForm():SVGForm { return new SVGForm( this ); }\n \n\n /**\n * Get the DOM element.\n */\n get element():Element {\n return this._canvas;\n }\n\n /**\n * This overrides Space's `resize` function. It's used as a callback function for window's resize event and not usually called directly. \n * You can keep track of resize events with `resize: (bound ,evt)` callback in your [`IPlayer`](#link) objects (See [`Space.add`](#link)). \n * @param b a Bound object to resize to\n * @param evt Optionally pass a resize event\n */\n resize( b:Bound, evt?:Event ):this {\n super.resize( b, evt );\n SVGSpace.setAttr( this.element, {\n \"viewBox\": `0 0 ${this.bound.width} ${this.bound.height}`,\n \"width\": `${this.bound.width}`,\n \"height\": `${this.bound.height}`,\n \"xmlns\": \"http://www.w3.org/2000/svg\",\n \"version\": \"1.1\"\n } );\n return this;\n }\n \n\n /**\n * A static function to add a svg element inside a node. Usually you don't need to call this directly. See methods in [`SVGForm`](#link) instead.\n * @param parent the parent element, or `null` to use current `<svg>` as parent.\n * @param name a string of element name, such as `rect` or `circle`\n * @param id id attribute of the new element\n */\n static svgElement( parent:Element, name:string, id?:string ):SVGElement {\n if ( !parent || !parent.appendChild ) throw new Error( \"parent is not a valid DOM element\" );\n \n let elem = document.querySelector( `#${id}` );\n\n if ( !elem ) {\n elem = document.createElementNS( \"http://www.w3.org/2000/svg\", name );\n elem.setAttribute( \"id\", id );\n \n parent.appendChild( elem );\n }\n return elem as SVGElement;\n }\n \n \n \n /**\n * Remove an item from this Space.\n * @param item a player item with an auto-assigned `animateID` property\n */\n remove( player:IPlayer ):this {\n let temp = this._container.querySelectorAll( \".\" + SVGForm.scopeID( player ) );\n \n temp.forEach( ( el:Element ) => { \n el.parentNode.removeChild( el );\n } );\n \n return super.remove( player );\n }\n \n \n /**\n * Remove all items from this Space.\n */\n removeAll():this {\n this._container.innerHTML = \"\";\n return super.removeAll();\n }\n \n}\n\n\n/**\n* **[Experimental]** SVGForm is an implementation of abstract class [`VisualForm`](#link). It provide methods to express Pts in [`SVGSpace`](#link). \n* You may extend SVGForm to implement your own expressions for SVGSpace. See out the [Space guide](../guide/Space-0500.html) for details.\n*/\nexport class SVGForm extends VisualForm {\n\n protected _style = {\n \"filled\": true,\n \"stroked\": true,\n \"fill\": \"#f03\",\n \"stroke\": \"#fff\",\n \"stroke-width\": 1,\n \"stroke-linejoin\": \"bevel\",\n \"stroke-linecap\": \"sqaure\",\n \"opacity\": 1\n };\n \n protected _ctx:DOMFormContext = {\n group: null,\n groupID: \"pts\",\n groupCount: 0,\n currentID: \"pts0\",\n currentClass: \"\",\n style: {},\n };\n \n static groupID:number = 0;\n static domID:number = 0;\n \n protected _space:SVGSpace;\n protected _ready:boolean = false;\n \n\n /**\n * Create a new SVGForm. You may also use [`SVGSpace.getForm`](#link) to get a default form directly.\n * @param space an instance of SVGSpace\n */\n constructor( space:SVGSpace ) {\n super();\n this._space = space;\n \n this._space.add( { start: () => {\n this._ctx.group = this._space.element;\n this._ctx.groupID = \"pts_svg_\" + ( SVGForm.groupID++ );\n this._ctx.style = Object.assign( {}, this._style );\n this._ready = true;\n }} );\n }\n \n\n /**\n * Get the [`SVGSpace`](#link) instance that this form is associated with.\n */\n get space():SVGSpace { return this._space; }\n \n \n /**\n * Update a style in current context. It will throw an Erorr if the style doesn't exist.\n * @param k style key\n * @param v style value\n */\n styleTo( k, v ) { \n if ( this._ctx.style[k] === undefined ) throw new Error( `${k} style property doesn't exist` );\n this._ctx.style[k] = v; \n }\n \n \n /**\n * Set current alpha value.\n * @example `form.alpha(0.6)`\n * @param a alpha value between 0 and 1\n */\n alpha( a:number ):this {\n this.styleTo( \"opacity\", a );\n return this;\n }\n \n\n /**\n * Set current fill style. Provide a valid color string or `false` to specify no fill color.\n * @example `form.fill(\"#F90\")`, `form.fill(\"rgba(0,0,0,.5\")`, `form.fill(false)`\n * @param c a valid color string or `false` to specify no fill color.\n */\n fill( c:string | boolean ):this {\n if ( typeof c == \"boolean\" ) {\n this.styleTo( \"filled\", c );\n } else {\n this.styleTo( \"filled\", true );\n this.styleTo( \"fill\", c );\n }\n return this;\n }\n \n\n /**\n * Set current stroke style. Provide a valid color string or `false` to specify no stroke color.\n * @example `form.stroke(\"#F90\")`, `form.stroke(\"rgba(0,0,0,.5\")`, `form.stroke(false)`, `form.stroke(\"#000\", 0.5, 'round', 'square')`\n * @param c a valid color string or `false` to specify no stroke color.\n * @param width Optional value (can be floating point) to set line width\n * @param linejoin Optional string to set line joint style. Can be \"miter\", \"bevel\", or \"round\".\n * @param linecap Optional string to set line cap style. Can be \"butt\", \"round\", or \"square\".\n */\n stroke( c:string | boolean, width?:number, linejoin?:string, linecap?:string ):this {\n if ( typeof c == \"boolean\" ) {\n this.styleTo( \"stroked\", c );\n } else {\n this.styleTo( \"stroked\", true );\n this.styleTo( \"stroke\", c );\n if ( width ) this.styleTo( \"stroke-width\", width );\n if ( linejoin ) this.styleTo( \"stroke-linejoin\", linejoin );\n if ( linecap ) this.styleTo( \"stroke-linecap\", linecap );\n }\n return this;\n }\n\n\n /**\n * Add custom class to the created element.\n * @param c custom class name or `false` to reset it\n * @example `form.fill(\"#f00\").cls(\"myClass\").rects(r)` `form.cls(false).circles(c)`\n */\n cls( c:string | boolean ) {\n if ( typeof c == \"boolean\" ) {\n this._ctx.currentClass = \"\";\n } else {\n this._ctx.currentClass = c;\n }\n return this;\n }\n \n \n /**\n * Set the current font.\n * @param sizeOrFont either a number to specify font-size, or a `Font` object to specify all font properties\n * @param weight Optional font-weight string such as \"bold\"\n * @param style Optional font-style string such as \"italic\"\n * @param lineHeight Optional line-height number suchas 1.5\n * @param family Optional font-family such as \"Helvetica, sans-serif\"\n * @example `form.font( myFont )`, `form.font(14, \"bold\")`\n */\n font( sizeOrFont:number | Font, weight?:string, style?:string, lineHeight?:number, family?:string ):this {\n if ( typeof sizeOrFont == \"number\" ) {\n \n this._font.size = sizeOrFont;\n if ( family ) this._font.face = family;\n if ( weight ) this._font.weight = weight;\n if ( style ) this._font.style = style;\n if ( lineHeight ) this._font.lineHeight = lineHeight;\n \n } else {\n this._font = sizeOrFont;\n }\n\n this._ctx.style['font'] = this._font.value;\n\n return this;\n }\n \n\n /**\n * Reset the context's common styles to this form's styles. This supports using multiple forms in the same space.\n */\n reset():this {\n this._ctx.style = Object.assign( {}, this._style );\n\n this._font = new Font( 10, \"sans-serif\" );\n this._ctx.style['font'] = this._font.value;\n\n return this;\n }\n\n \n /**\n * Set this form's group scope by an ID, and optionally define the group's parent element. A group scope keeps track of elements by their generated IDs, and updates their properties as needed. See also [`SVGForm.scope`](#link).\n * @param group_id a string to use as prefix for the group's id. For example, group_id \"hello\" will create elements with id like \"hello-1\", \"hello-2\", etc\n * @param group Optional DOM or SVG element to define this group's parent element\n * @returns this form's context\n */\n updateScope( group_id:string, group?:Element ):object {\n this._ctx.group = group;\n this._ctx.groupID = group_id;\n this._ctx.groupCount = 0;\n this.nextID();\n return this._ctx;\n }\n \n\n /**\n * Set the current group scope to an item added into space, in order to keep track of any point, circle, etc created within it in the DOM. \n * The item must have an `animateID` property, so that elements created within the item will have generated IDs like \"item-{animateID}-{count}\". \n * See the svg section in [`Space guide`](../guide/Space-0500.html) to learn more about scope.\n * @param item a [`IPlayer`](#link) object that's added to space (see [`Space.add`](#link)) and has an `animateID` property\n * @returns this form's context\n */\n scope( item:IPlayer ) {\n if ( !item || item.animateID == null ) throw new Error( \"item not defined or not yet added to Space\" );\n return this.updateScope( SVGForm.scopeID( item ), this.space.element );\n }\n \n \n /**\n * Get next available id in the current group.\n * @returns an id string\n */\n nextID():string {\n this._ctx.groupCount++;\n this._ctx.currentID = `${this._ctx.groupID}-${this._ctx.groupCount}`;\n return this._ctx.currentID;\n }\n \n\n /**\n * A static function to generate an ID string based on a context object.\n * @param ctx a context object for an SVGForm\n */\n static getID( ctx ):string {\n return ctx.currentID || `p-${SVGForm.domID++}`;\n }\n\n\n /**\n * A static function to generate an ID string for a scope, based on an [`IPlayer`](#link) object in the Space.\n * @param item a [`IPlayer`](#link) object that's added to space (see [`Space.add`](#link)) and has an `animateID` property\n */\n static scopeID( item:IPlayer ):string {\n return `item-${item.animateID}`;\n }\n \n\n /**\n * A static function to help adding style object to an element. \n * Note that this put all styles into `style` attribute instead of individual svg attributes, so that the styles can be parsed by Adobe Illustrator.\n * @param elem A DOM element to add to\n * @param styles an object of style properties\n * @example `SVGForm.style(elem, {fill: \"#f90\", stroke: false})`\n * @returns this DOM element \n */\n static style( elem:SVGElement, styles:object ) {\n let st = [];\n\n if ( !styles[\"filled\"] ) st.push( \"fill: none\" );\n if ( !styles[\"stroked\"] ) st.push( \"stroke: none\" );\n \n for ( let k in styles ) {\n if ( styles.hasOwnProperty( k ) && k != \"filled\" && k != \"stroked\" ) {\n let v = styles[k];\n if ( v ) {\n if ( !styles[\"filled\"] && k.indexOf( 'fill' ) === 0 ) {\n continue;\n } else if ( !styles[\"stroked\"] && k.indexOf( 'stroke' ) === 0 ) {\n continue;\n } else {\n st.push( `${k}: ${v}` );\n }\n }\n }\n }\n \n return DOMSpace.setAttr( elem, {style: st.join( \";\" )} );\n }\n \n \n /**\n * A static function to draw a point.\n * @param ctx a context object of SVGForm\n * @param pt a Pt object or numeric array\n * @param radius radius of the point. Default is 5.\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\n * @example `SVGForm.point( p )`, `SVGForm.point( p, 10, \"circle\" )`\n */\n static point( ctx:DOMFormContext, pt:PtLike, radius:number = 5, shape:string = \"square\" ):SVGElement {\n if ( shape === \"circle\" ) {\n return SVGForm.circle( ctx, pt, radius );\n } else {\n return SVGForm.square( ctx, pt, radius );\n }\n }\n \n \n /**\n * Draws a point.\n * @param p a Pt object\n * @param radius radius of the point. Default is 5.\n * @param shape The shape of the point. Defaults to \"square\", but it can be \"circle\" or a custom shape function in your own implementation.\n * @example `form.point( p )`, `form.point( p, 10, \"circle\" )`\n */\n point( pt:PtLike, radius:number = 5, shape:string = \"square\" ):this {\n this.nextID();\n SVGForm.point( this._ctx, pt, radius, shape );\n return this;\n }\n \n\n /**\n * A static function to draw a circle.\n * @param ctx a context object of SVGForm\n * @param pt center position of the circle\n * @param radius radius of the circle\n */\n static circle( ctx:DOMFormContext, pt:PtLike, radius:number = 10 ):SVGElement {\n let elem = SVGSpace.svgElement( ctx.group, \"circle\", SVGForm.getID( ctx ) );\n \n DOMSpace.setAttr( elem, {\n cx: pt[0],\n cy: pt[1],\n r: radius,\n 'class': `pts-svgform pts-circle ${ctx.currentClass}`,\n } );\n \n SVGForm.style( elem, ctx.style );\n return elem;\n }\n \n\n /**\n * Draw a circle.\n * @param pts a Group or an Iterable<PtLike> representing a circle with `[[position], [size]]`\n * @see [`Circle.fromCenter`](./?p=Op_Circle#function_fromCenter)\n */\n circle( pts:PtLikeIterable ):this {\n this.nextID();\n let p = Util.iterToArray( pts );\n SVGForm.circle( this._ctx, p[0], p[1][0] );\n return this;\n }\n \n\n /**\n * A static function to draw an arc.\n * @param ctx a context object of SVGForm\n * @param pt center position \n * @param radius radius of the arc circle\n * @param startAngle start angle of the arc\n * @param endAngle end angle of the arc\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\n */\n static arc( ctx:DOMFormContext, pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ):SVGElement {\n let elem = SVGSpace.svgElement( ctx.group, \"path\", SVGForm.getID( ctx ) );\n \n const start = new Pt( pt ).toAngle( startAngle, radius, true );\n const end = new Pt( pt ).toAngle( endAngle, radius, true );\n const diff = Geom.boundAngle( endAngle ) - Geom.boundAngle( startAngle );\n let largeArc = ( diff > Const.pi ) ? true : false;\n if ( cc ) largeArc = !largeArc;\n const sweep = ( cc ) ? \"0\" : \"1\";\n \n const d = `M ${start[0]} ${start[1]} A ${radius} ${radius} 0 ${largeArc ? \"1\" : \"0\"} ${sweep} ${end[0]} ${end[1]}`;\n \n DOMSpace.setAttr( elem, { \n d: d,\n 'class': `pts-svgform pts-arc ${ctx.currentClass}`,\n } );\n SVGForm.style( elem, ctx.style );\n return elem;\n }\n \n\n /**\n * Draw an arc.\n * @param pt center position\n * @param radius radius of the arc circle\n * @param startAngle start angle of the arc\n * @param endAngle end angle of the arc\n * @param cc an optional boolean value to specify if it should be drawn clockwise (`false`) or counter-clockwise (`true`). Default is clockwise.\n */\n arc( pt:PtLike, radius:number, startAngle:number, endAngle:number, cc?:boolean ):this {\n this.nextID();\n SVGForm.arc( this._ctx, pt, radius, startAngle, endAngle, cc );\n return this;\n }\n \n\n /**\n * A static function to draw a square.\n * @param ctx a context object of SVGForm\n * @param pt center position of the square\n * @param halfsize half size of the square\n */\n static square( ctx:DOMFormContext, pt:PtLike, halfsize:number ) {\n let elem = SVGSpace.svgElement( ctx.group, \"rect\", SVGForm.getID( ctx ) );\n DOMSpace.setAttr( elem, {\n x: pt[0] - halfsize, \n y:pt[1] - halfsize, \n width: halfsize * 2, \n height: halfsize * 2,\n 'class': `pts-svgform pts-square ${ctx.currentClass}`,\n } );\n SVGForm.style( elem, ctx.style );\n return elem;\n }\n \n\n /**\n * Draw a square, given a center and its half-size.\n * @param pt center Pt\n * @param halfsize half-size\n */\n square( pt:PtLike, halfsize:number ):this {\n this.nextID();\n SVGForm.square( this._ctx, pt, halfsize );\n return this;\n } \n \n\n /**\n * A static function to draw a line or polyline.\n * @param ctx a context object of SVGForm\n * @param pts a Group or an Iterable<PtLike>\n */\n static line( ctx:DOMFormContext, pts:PtLikeIterable ):SVGElement {\n let points = SVGForm.pointsString( pts );\n if ( points.count < 2 ) return;\n \n // if count > 2, treat it as poly-line\n if ( points.count > 2 ) return SVGForm._poly( ctx, points.string, false );\n \n // if count == 2, treat it as line\n let elem = SVGSpace.svgElement( ctx.group, \"line\", SVGForm.getID( ctx ) );\n let p = Util.iterToArray( pts );\n \n DOMSpace.setAttr( elem, {\n x1: p[0][0],\n y1: p[0][1],\n x2: p[1][0],\n y2: p[1][1],\n 'class': `pts-svgform pts-line ${ctx.currentClass}`,\n } );\n \n SVGForm.style( elem, ctx.style );\n return elem;\n }\n \n\n /**\n * Draw a line or polyline.\n * @param pts a Group or an Iterable<PtLike> \n */\n line( pts:PtLikeIterable ):this {\n this.nextID();\n SVGForm.line( this._ctx, pts );\n return this;\n }\n \n \n /**\n * A static helper function to draw polyline or polygon.\n * @param ctx a context object of SVGForm\n * @param points a string of points' positions. See `SVGForm.pointsString` for conversion.\n * @param closePath a boolean to specify if the polygon path should be closed\n */\n protected static _poly( ctx:DOMFormContext, points:string, closePath:boolean = true ) {\n \n let elem = SVGSpace.svgElement( ctx.group, ( ( closePath ) ? \"polygon\" : \"polyline\" ), SVGForm.getID( ctx ) );\n \n DOMSpace.setAttr( elem, {\n points: points,\n 'class': `pts-svgform pts-polygon ${ctx.currentClass}`,\n } ); \n SVGForm.style( elem, ctx.style );\n return elem;\n }\n\n\n /**\n * Given a list of points, return a space-separated string\n * @param pts a Group or an Iterable<PtLike> \n * @returns an object of {string, count}\n */\n protected static pointsString( pts: PtLikeIterable ):{string:string, count:number} {\n let points:string = \"\";\n let count = 0;\n for ( let p of pts ) {\n points += `${p[0]},${p[1]} `;\n count++;\n }\n return {string:points, count:count};\n }\n \n \n /**\n * A static function to draw polygon.\n * @param ctx a context object of SVGForm\n * @param pts a Group or an Iterable<PtLike> representing a polygon\n */\n static polygon( ctx:DOMFormContext, pts:PtLikeIterable ):SVGElement {\n let points = SVGForm.pointsString( pts );\n return SVGForm._poly( ctx, points.string, true );\n }\n \n\n /**\n * Draw a polygon.\n * @param pts a Group or an Iterable<PtLike> representing a polygon\n */\n polygon( pts:PtLikeIterable ):this {\n this.nextID();\n SVGForm.polygon( this._ctx, pts );\n return this;\n }\n \n \n /**\n * A static function to draw a rectangle.\n * @param ctx a context object of SVGForm\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions. \n */\n static rect( ctx:DOMFormContext, pts:PtLikeIterable ):SVGElement {\n if ( !Util.arrayCheck( pts ) ) return;\n \n let elem = SVGSpace.svgElement( ctx.group, \"rect\", SVGForm.getID( ctx ) );\n let bound = Group.fromArray( pts ).boundingBox();\n let size = Rectangle.size( bound );\n \n DOMSpace.setAttr( elem, {\n x: bound[0][0],\n y: bound[0][1],\n width: size[0],\n height: size[1],\n 'class': `pts-svgform pts-rect ${ctx.currentClass}`,\n } );\n \n SVGForm.style( elem, ctx.style );\n return elem;\n }\n \n \n /**\n * Draw a rectangle.\n * @param pts a Group or an Iterable<PtLike> with 2 Pt specifying the top-left and bottom-right positions. \n */\n rect( pts:PtLikeIterable ):this {\n this.nextID();\n SVGForm.rect( this._ctx, pts );\n return this;\n }\n \n \n /**\n * A static function to draw text.\n * @param ctx a context object of SVGForm\n * @param `pt` a Point object to specify the anchor point\n * @param `txt` a string of text to draw\n * @param `maxWidth` specify a maximum width per line\n */\n static text( ctx:DOMFormContext, pt:PtLike, txt:string ):SVGElement {\n let elem = SVGSpace.svgElement( ctx.group, \"text\", SVGForm.getID( ctx ) );\n \n DOMSpace.setAttr( elem, {\n \"pointer-events\": \"none\",\n x: pt[0],\n y: pt[1],\n dx: 0, dy: 0,\n 'class': `pts-svgform pts-text ${ctx.currentClass}`,\n } );\n \n elem.textContent = txt;\n \n SVGForm.style( elem, ctx.style );\n \n return elem;\n }\n \n\n /**\n * Draw text on canvas.\n * @param `pt` a Pt or numeric array to specify the anchor point\n * @param `txt` text\n * @param `maxWidth` specify a maximum width per line\n */\n text( pt:PtLike, txt:string ): this {\n this.nextID();\n SVGForm.text( this._ctx, pt, txt );\n return this;\n }\n \n\n /**\n * A convenient way to draw some text on canvas for logging or debugging. It'll be draw on the top-left of the canvas as an overlay.\n * @param txt text\n */\n log( txt ):this {\n this.fill( \"#000\" ).stroke( \"#fff\", 0.5 ).text( [10,14], txt ); \n return this;\n }\n \n \n}","/*! Pts.js is licensed under Apache License 2.0. Copyright © 2017-current William Ngan and contributors. (https://github.com/williamngan/pts) */\n\nimport {Pt, Group, Bound} from \"./Pt\";\nimport { Polygon, Circle } from \"./Op\";\nimport { Geom } from \"./Num\";\nimport {PtLike, GroupLike, PtIterable} from \"./Types\";\n\n/**\n * A `World` stores and manages [`Body`](#link) and [`Particle`](#link) for 2D physics simulation. \n * See a [Particle demo](../demo/index.html?name=physics.particles) and a [Body demo](../demo/index.html?name=physics.shapes) on the demo page.\n */\nexport class World {\n\n private _lastTime:number = null;\n\n protected _gravity:Pt = new Pt();\n protected _friction:number = 1; // general friction\n protected _damping:number = 0.75; // collision damping\n protected _iterations:number = 1; // number of iterations to solve edge constraint \n protected _bound:Bound;\n \n protected _particles:Particle[] = [];\n protected _bodies:Body[] = [];\n protected _pnames:string[] = []; // particle name index\n protected _bnames:string[] = []; // body name index\n\n protected _drawParticles:( p:Particle, i:number ) => void;\n protected _drawBodies:( p:Body, i:number ) => void;\n\n\n /**\n * Create a `World` for 2D physics simulation.\n * @param bound a Group or an Iterable<Pt> representing a rectangular bounding box\n * @param friction a value between 0 to 1, where 1 means no friction. Default is 1\n * @param gravity a number of a Pt to define gravitational force. A number is a shorthand to set `new Pt(0, n)`. Default is 0.\n */\n constructor( bound:PtIterable, friction:number = 1, gravity:PtLike | number = 0 ) {\n this._bound = Bound.fromGroup( bound );\n this._friction = friction;\n this._gravity = ( typeof gravity === \"number\" ) ? new Pt( 0, gravity ) : new Pt( gravity );\n return this;\n }\n\n\n /**\n * Current bound in this `World`.\n */\n get bound():Bound { return this._bound; }\n set bound( bound:Bound ) { this._bound = bound; }\n\n /**\n * Current gravity in this `World`.\n */\n get gravity():Pt { return this._gravity; }\n set gravity( g:Pt ) { this._gravity = g; }\n\n /**\n * Current friction in this `World`.\n */\n get friction():number { return this._friction; }\n set friction( f:number ) { this._friction = f; }\n\n /**\n * Current damping in this `World`.\n */\n get damping():number { return this._damping; }\n set damping( f:number ) { this._damping = f; }\n\n /**\n * constraint solver iterations.\n */\n get iterations():number { return this._iterations; }\n set iterations( f:number ) { this._iterations = f; }\n\n /**\n * Get the number of bodies.\n */\n get bodyCount():number { return this._bodies.length; }\n\n /**\n * Get the number of particles.\n */\n get particleCount():number { return this._particles.length; }\n\n\n /**\n * Get a body in this world by index or string id.\n * @param id numeric index of the body, or a string id that associates with it.\n * @returns a Body, or undefined if not found\n */\n body( id:number | string ) {\n if ( typeof id === \"string\" && id.length > 0 ) {\n return this._bodies[this._bnames.indexOf( id )];\n }\n return ( typeof id === \"number\" && id >= 0 ) ? this._bodies[id] : undefined;\n }\n\n\n /**\n * Get a particle in this world by index or string id.\n * @param id numeric index of the particle, or a string id that associates with it. \n * @returns a Particle, or undefined if not found\n */\n particle( id:number | string ) { \n if ( typeof id === \"string\" && id.length > 0 ) {\n return this._particles[this._pnames.indexOf( id )];\n }\n return ( typeof id === \"number\" && id >= 0 ) ? this._particles[id] : undefined;\n }\n\n\n /**\n * Given a body's name, return its index in the bodies array, or -1 if not found.\n * @param name name of the body\n * @returns index number, or -1 if not found\n */\n bodyIndex( name:string ):number {\n return this._bnames.indexOf( name );\n }\n\n\n /**\n * Given a particle's name, return its index in the particles array, or -1 if not found.\n * @param name name of the particle\n * @returns index number, or -1 if not found\n */\n particleIndex( name:string ):number {\n return this._pnames.indexOf( name );\n }\n\n\n /**\n * Update this world by one time-step.\n * @param ms change in time in milliseconds\n */\n update( ms:number ) {\n let dt = ms / 1000;\n this._updateParticles( dt );\n this._updateBodies( dt );\n }\n\n\n /**\n * Draw particles using the provided function.\n * @param fn a function that draws a particle passed in the parameters `(particle, index)`.\n */\n drawParticles( fn:( p:Particle, i:number ) => void ):void {\n this._drawParticles = fn;\n }\n\n\n /**\n * Draw bodies using the provided function.\n * @param fn a function that draws a body passed in the parameters `(body, index)`.\n */\n drawBodies( fn:( p:Body, i:number ) => void ):void {\n this._drawBodies = fn;\n }\n\n\n /**\n * Add a particle or body to this world.\n * @param p `Particle` or `Body` instance\n * @param name optional name, which can be referenced in `body()` or `particle()` function to retrieve this back.\n */\n add( p:Particle | Body, name:string = '' ):this {\n if ( p instanceof Body ) {\n this._bodies.push( <Body>p );\n this._bnames.push( name );\n } else {\n this._particles.push( <Particle>p );\n this._pnames.push( name );\n }\n return this;\n }\n\n\n private _index( fn:( string )=>number, id:string | number ):number {\n let index = 0;\n if ( typeof id === \"string\" ) {\n index = fn( id );\n if ( index < 0 ) throw new Error( `Cannot find index of ${id}. You can use particleIndex() or bodyIndex() function to check existence by name.` );\n } else {\n index = id;\n }\n return index;\n }\n\n\n /**\n * Remove bodies from this world. Support removing a range and negative index.\n * @param from Start index, which can be negative (where -1 is at index 0, -2 at index 1, etc) \n * @param count Number of items to remove. Default is 1.\n */\n removeBody( from:number | string, count:number = 1 ):this {\n const index = this._index( this.bodyIndex.bind( this ), from );\n const param = ( index < 0 ) ? [index * -1 - 1, count] : [index, count];\n this._bodies.splice( param[0], param[1] );\n this._bnames.splice( param[0], param[1] );\n return this;\n }\n\n\n /**\n * Remove particles from this world. Support removing a range and negative index.\n * @param from Start index, which can be negative (where -1 is at index 0, -2 at index 1, etc) \n * @param count Number of items to remove. Default is 1.\n */\n removeParticle( from:number | string, count:number = 1 ):this {\n const index = this._index( this.particleIndex.bind( this ), from );\n const param = ( index < 0 ) ? [index * -1 - 1, count] : [index, count];\n this._particles.splice( param[0], param[1] );\n this._pnames.splice( param[0], param[1] );\n return this;\n }\n\n \n /**\n * Static function to calculate edge constraints between 2 particles.\n * @param p1 particle 1\n * @param p2 particle 1\n * @param dist distance between particles\n * @param stiff stiffness between 0 to 1.\n * @param precise use precise distance calculation. Default is `false`.\n */\n static edgeConstraint( p1:Particle, p2:Particle, dist:number, stiff:number = 1, precise:boolean = false ) {\n const m1 = 1 / ( p1.mass || 1 );\n const m2 = 1 / ( p2.mass || 1 );\n const mm = m1 + m2;\n\n let delta = p2.$subtract( p1 );\n let distSq = dist * dist;\n let d = ( precise ) ? ( dist / delta.magnitude() - 1 ) : ( distSq / ( delta.dot( delta ) + distSq ) - 0.5 ); // approx square root\n let f = delta.$multiply( d * stiff );\n\n p1.subtract( f.$multiply( m1 / mm ) );\n p2.add( f.$multiply( m2 / mm ) );\n \n return p1;\n }\n\n\n /**\n * Static function to calculate bounding box constraints.\n * @param p particle\n * @param rect a Group or an Iterable<Pt> representing a bounding box\n * @param damping damping between 0 to 1, where 1 means no damping. Default is 0.75.\n */\n static boundConstraint( p:Particle, rect:PtIterable, damping:number = 0.75 ) {\n let bound = Geom.boundingBox( rect );\n let np = p.$min( bound[1].subtract( p.radius ) ).$max( bound[0].add( p.radius ) );\n \n if ( np[0] === bound[0][0] || np[0] === bound[1][0] ) { // hit vertical walls\n let c = p.changed.$multiply( damping );\n p.previous = np.$subtract( new Pt( -c[0], c[1] ) );\n } else if ( np[1] === bound[0][1] || np[1] === bound[1][1] ) { // hit horizontal walls\n let c = p.changed.$multiply( damping );\n p.previous = np.$subtract( new Pt( c[0], -c[1] ) );\n }\n \n p.to( np );\n\n }\n\n\n /**\n * Internal integrate function\n * @param p particle\n * @param dt time changed\n * @param prevDt previous change in time, optional\n */\n protected integrate( p:Particle, dt:number, prevDt?:number ):Particle {\n p.addForce( this._gravity );\n p.verlet( dt, this._friction, prevDt );\n return p;\n }\n\n\n /**\n * Internal function to update particles\n */\n protected _updateParticles( dt:number ) {\n \n for ( let i = 0, len = this._particles.length; i < len; i++ ) {\n let p = this._particles[i];\n\n // force and integrate\n this.integrate( p, dt, this._lastTime );\n\n // constraints\n World.boundConstraint( p, this._bound, this._damping );\n\n // collisions\n for ( let k = i + 1; k < len; k++ ) {\n if ( i !== k ) {\n let p2 = this._particles[k];\n p.collide( p2, this._damping );\n }\n }\n \n // render\n if ( this._drawParticles ) this._drawParticles( p, i );\n }\n\n this._lastTime = dt;\n }\n\n\n /**\n * Internal function to update bodies\n */\n protected _updateBodies( dt:number ) {\n for ( let i = 0, len = this._bodies.length; i < len; i++ ) {\n let bds = this._bodies[i];\n\n if ( bds ) {\n // integrate\n for ( let k = 0, klen = bds.length; k < klen; k++ ) {\n let bk = bds[k] as Particle;\n World.boundConstraint( bk, this._bound, this._damping );\n this.integrate( bk, dt, this._lastTime );\n }\n \n for ( let k = i + 1; k < len; k++ ) {\n bds.processBody( this._bodies[k] );\n }\n\n for ( let m = 0, mlen = this._particles.length; m < mlen; m++ ) {\n bds.processParticle( this._particles[m] );\n }\n\n // constraints\n for ( let i = 0; i < this._iterations; i++ ) {\n bds.processEdges();\n }\n \n // render\n if ( this._drawBodies ) this._drawBodies( bds, i );\n }\n }\n } \n\n \n}\n\n\n\n/**\n * Particle is a subclass of [`Pt`](#link) that has radius and mass. It's usually added into [`World`](#link) to create physics simulations. \n * See [a demo here](../demo/index.html?name=physics.particles).\n */\nexport class Particle extends Pt {\n\n protected _mass:number = 1;\n protected _radius:number = 0;\n protected _force:Pt = new Pt();\n protected _prev:Pt = new Pt();\n \n protected _body:Body;\n protected _lock:boolean = false;\n protected _lockPt:Pt;\n\n\n /**\n * Create a particle. Once a particle is created, you can set its mass and radius via the corresponding accessors.\n * @param args a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\n */\n constructor( ...args ) {\n super( ...args );\n this._prev = this.clone();\n }\n\n /**\n * Mass of this particle.\n */\n get mass():number { return this._mass; }\n set mass( m:number ) { this._mass = m; }\n\n /**\n * Radius of this particle.\n */\n get radius():number { return this._radius; }\n set radius( f:number ) { this._radius = f; }\n\n /**\n * Get this particle's previous position.\n */\n get previous():Pt { return this._prev; }\n set previous( p:Pt ) { this._prev = p; }\n\n /**\n * Get current accumulated force.\n */\n get force():Pt { return this._force; }\n set force( g:Pt ) { this._force = g; }\n\n /**\n * Get the body of this particle, if any.\n */\n get body():Body { return this._body; }\n set body( b:Body ) { this._body = b; }\n\n /**\n * Lock this particle in current position.\n */\n get lock():boolean { return this._lock; }\n set lock( b:boolean ) { \n this._lock = b; \n this._lockPt = new Pt( this );\n }\n\n /**\n * Get the change in position since last time step.\n */\n get changed():Pt { return this.$subtract( this._prev ); }\n\n\n /**\n * Set a new position, and update previous and lock states if needed.\n */\n set position( p:Pt ) {\n this.previous.to( this );\n if ( this._lock ) this._lockPt = p;\n this.to( p );\n }\n\n \n /**\n * Set the size of this particle. This sets both the radius and the mass.\n * @param r `radius` value, and also set `mass` to the same value.\n */\n size( r:number ):this {\n this._mass = r;\n this._radius = r;\n return this;\n }\n\n\n /**\n * Add to the accumulated force.\n * @param args a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\n */\n addForce( ...args ):Pt {\n this._force.add( ...args );\n return this._force;\n }\n\n\n /**\n * Verlet integration. \n * @param dt change in time \n * @param friction friction from 0 to 1, where 1 means no friction\n * @param lastDt optional last change in time \n */\n verlet( dt:number, friction:number, lastDt?:number ):this {\n // Positional verlet: curr + (curr - prev) + a * dt * dt\n\n if ( this._lock ) {\n this.to( this._lockPt );\n // this._prev.to( this._lockPt );\n } else {\n\n // time corrected (https://en.wikipedia.org/wiki/Verlet_integration#Non-constant_time_differences)\n let lt = ( lastDt ) ? lastDt : dt; \n let a = this._force.multiply( dt * ( dt + lt ) / 2 );\n let v = this.changed.multiply( friction * dt / lt ).add( a );\n\n this._prev = this.clone();\n this.add( v );\n \n this._force = new Pt();\n }\n return this;\n }\n\n\n /**\n * Hit this particle with an impulse.\n * @param args an impulse vector defined by either a list of numeric parameters, an array of numbers, or an object with {x,y,z,w} properties\n * @example `hit(10, 20)`, `hit( new Pt(5, 9) )`\n */\n hit( ...args ):this {\n this._prev.subtract( new Pt( ...args ).$divide( Math.sqrt( this._mass ) ) );\n return this;\n }\n\n\n /**\n * Check and respoond to collisions between this and another particle.\n * @param p2 another particle\n * @param damp damping value between 0 to 1, where 1 means no damping.\n */\n collide( p2:Particle, damp:number = 1 ):void {\n // reference: http://codeflow.org/entries/2010/nov/29/verlet-collision-with-impulse-preservation\n // simultaneous collision not yet resolved. Possible solutions in this paper: https://www2.msm.ctw.utwente.nl/sluding/PAPERS/dem07.pdf \n\n let p1 = this;\n let dp = p1.$subtract( p2 );\n let distSq = dp.magnitudeSq();\n let dr = p1.radius + p2.radius;\n \n if ( distSq < dr * dr ) {\n\n let c1 = p1.changed;\n let c2 = p2.changed;\n\n let dist = Math.sqrt( distSq );\n let d = dp.$multiply( ( ( dist - dr ) / dist ) / 2 );\n\n let np1 = p1.$subtract( d );\n let np2 = p2.$add( d );\n\n p1.to( np1 );\n p2.to( np2 );\n \n let f1 = damp * dp.dot( c1 ) / distSq;\n let f2 = damp * dp.dot( c2 ) / distSq;\n\n let dm1 = p1.mass / ( p1.mass + p2.mass );\n let dm2 = p2.mass / ( p1.mass + p2.mass );\n\n c1.add( new Pt( f2 * dp[0] - f1 * dp[0], f2 * dp[1] - f1 * dp[1] ).$multiply( dm2 ) );\n c2.add( new Pt( f1 * dp[0] - f2 * dp[0], f1 * dp[1] - f2 * dp[1] ).$multiply( dm1 ) );\n\n p1.previous = p1.$subtract( c1 ); \n p2.previous = p2.$subtract( c2 ); \n\n }\n }\n \n\n /**\n * Get a string representation of this particle\n */\n toString():string {\n return `Particle: ${this[0]} ${this[1]} | previous ${this._prev[0]} ${this._prev[1]} | mass ${this._mass}`;\n }\n\n}\n\n\n/**\n * Body is a subclass of [`Group`](#link) that stores a set of [`Particle`](#link)s and edge constraints. It is usually added into a [`World`](#link) to create physics simulations. \n * See [a demo here](../demo/index.html?name=physics.shapes).\n */\nexport class Body extends Group {\n\n protected _cs:Array<number[]> = [];\n protected _stiff:number = 1;\n protected _locks:{ [index:string]: Particle } = {};\n protected _mass:number = 1;\n\n /**\n * Create an empty Body, this is usually followed by [`Body.init`](#link) to populate the Body. Alternatively, use static function [`Body.fromGroup`](#link) to create and initate a body directly.\n */\n constructor() {\n super();\n }\n\n \n /**\n * Create and populate a body.\n * @param body a Group or an Iterable<Pt> to define the body\n * @param stiff stiffness value from 0 to 1, where 1 is the most stiff. Default is 1.\n * @param autoLink Automatically create links between the Pts. This usually works for regular convex polygons. Default is true.\n * @param autoMass Automatically calculate the mass based on the area of the polygon. Default is true.\n */\n static fromGroup( body:PtIterable, stiff:number = 1, autoLink:boolean = true, autoMass:boolean = true ):Body {\n let b = new Body().init( body );\n if ( autoLink ) b.linkAll( stiff );\n if ( autoMass ) b.autoMass();\n return b;\n }\n\n\n /**\n * Initiate a body.\n * @param body a Group or an Iterable<Pt> to define a body\n * @param stiff stiffness value from 0 to 1, where 1 is the most stiff. Default is 1.\n */\n init( body:PtIterable, stiff:number = 1 ):this {\n let c = new Pt();\n for ( let li of body ) {\n let p = new Particle( li );\n p.body = this;\n c.add( li );\n this.push( p );\n }\n\n this._stiff = stiff;\n \n return this;\n } \n\n\n /**\n * Get mass of this body. \n */\n get mass():number { return this._mass; }\n set mass( m:number ) { \n this._mass = m; \n for ( let i = 0, len = this.length; i < len; i++ ) {\n ( this[i] as Particle ).mass = this._mass;\n }\n }\n\n\n /**\n * Automatically calculate a body's `mass` based on the area of the polygon.\n */\n autoMass():this {\n this.mass = Math.sqrt( Polygon.area( this ) ) / 10;\n return this;\n }\n\n\n /**\n * Create a linked edge between two points.\n * @param index1 first point by index\n * @param index2 first point by index\n * @param stiff optionally stiffness value between 0 to 1, where 1 is the most stiff.\n */\n link( index1:number, index2:number, stiff?:number ):this {\n if ( index1 < 0 || index1 >= this.length ) throw new Error( \"index1 is not in the Group's indices\" );\n if ( index2 < 0 || index2 >= this.length ) throw new Error( \"index1 is not in the Group's indices\" );\n\n let d = this[index1].$subtract( this[index2] ).magnitude();\n this._cs.push( [index1, index2, d, stiff || this._stiff] );\n return this;\n }\n\n\n\n /**\n * Automatically create links for all the points to preserve the initial body shape. This usually works for regular convex polygon.\n * @param stiff optionally stiffness value between 0 to 1, where 1 is the most stiff.\n */\n linkAll( stiff:number ):void {\n let half = this.length / 2;\n\n for ( let i = 0, len = this.length; i < len; i++ ) {\n let n = ( i >= len - 1 ) ? 0 : i + 1;\n this.link( i, n, stiff ); \n\n if ( len > 4 ) {\n let nd = ( Math.floor( half / 2 ) ) + 1;\n let n2 = ( i >= len - nd ) ? i % len : i + nd;\n this.link( i, n2, stiff ); \n }\n\n if ( i <= half - 1 ) {\n this.link( i, Math.min( this.length - 1, i + Math.floor( half ) ) );\n }\n }\n }\n\n\n /**\n * Return a list of all the linked edges as line segments.\n * @returns an array of Groups, each of which represents an edge\n */\n linksToLines():Group[] {\n let gs = [];\n for ( let i = 0, len = this._cs.length; i < len; i++ ) {\n let ln = this._cs[i];\n gs.push( new Group( this[ ln[0] ], this[ ln[1] ] ) );\n }\n return gs;\n }\n \n\n /**\n * Recalculate all edge constraints.\n */\n processEdges():void {\n for ( let i = 0, len = this._cs.length; i < len; i++ ) {\n let [m, n, d, s] = this._cs[i];\n World.edgeConstraint( this[m] as Particle, this[n] as Particle, d, s );\n }\n }\n\n\n /**\n * Check and respond to collisions between two bodies.\n * @param b another body\n */\n processBody( b:Body ):void {\n\n let b1 = this;\n let b2 = b;\n\n let hit = Polygon.hasIntersectPolygon( b1, b2 );\n\n if ( hit ) {\n let cv = hit.normal.$multiply( hit.dist );\n \n let t; \n let eg = hit.edge;\n if ( Math.abs( eg[0][0] - eg[1][0] ) > Math.abs( eg[0][1] - eg[1][1] ) ) {\n t = ( hit.vertex[0] - cv[0] - eg[0][0] ) / ( eg[1][0] - eg[0][0] );\n } else {\n t = ( hit.vertex[1] - cv[1] - eg[0][1] ) / ( eg[1][1] - eg[0][1] );\n }\n\n let lambda = 1 / ( t * t + ( 1 - t ) * ( 1 - t ) );\n\n let m0 = ( hit.vertex as Particle ).body.mass || 1;\n let m1 = ( hit.edge[0] as Particle ).body.mass || 1;\n let mr0 = m0 / ( m0 + m1 );\n let mr1 = m1 / ( m0 + m1 );\n\n eg[0].subtract( cv.$multiply( mr0 * ( 1 - t ) * lambda / 2 ) );\n eg[1].subtract( cv.$multiply( mr0 * t * lambda / 2 ) );\n\n hit.vertex.add( cv.$multiply( mr1 ) );\n }\n\n }\n\n\n /**\n * Check and respond to collisions between this body and a particle.\n * @param b a particle\n */\n processParticle( b:Particle ):void {\n\n let b1 = this;\n let b2 = b;\n\n let hit = Polygon.hasIntersectCircle( b1, Circle.fromCenter( b, b.radius ) );\n\n if ( hit ) {\n let cv = hit.normal.$multiply( hit.dist );\n \n let t; \n let eg = hit.edge;\n if ( Math.abs( eg[0][0] - eg[1][0] ) > Math.abs( eg[0][1] - eg[1][1] ) ) {\n t = ( hit.vertex[0] - cv[0] - eg[0][0] ) / ( eg[1][0] - eg[0][0] );\n } else {\n t = ( hit.vertex[1] - cv[1] - eg[0][1] ) / ( eg[1][1] - eg[0][1] );\n }\n\n let lambda = 1 / ( t * t + ( 1 - t ) * ( 1 - t ) );\n let m0 = ( hit.vertex as Particle ).mass || b2.mass || 1;\n let m1 = ( hit.edge[0] as Particle ).body.mass || 1;\n\n let mr0 = m0 / ( m0 + m1 );\n let mr1 = m1 / ( m0 + m1 );\n\n eg[0].subtract( cv.$multiply( mr0 * ( 1 - t ) * lambda / 2 ) );\n eg[1].subtract( cv.$multiply( mr0 * t * lambda / 2 ) );\n\n let c1 = b.changed.add( cv.$multiply( mr1 ) );\n b.previous = b.$subtract( c1 );\n\n // let c2 = b2.changed.add( cv.$multiply(mr0) );\n // b2.previous = b2.$subtract( c2 );\n }\n \n }\n\n}","import {Pt, Group, Bound} from \"./Pt\";\nimport {Num} from \"./Num\";\nimport {ITempoListener, ITempoStartFn, ITempoProgressFn, ITempoResponses} from \"./Types\";\nimport {ISoundAnalyzer, SoundType, PtLike, IPlayer} from \"./Types\";\n\n/**\n * Tempo helps you create synchronized and rhythmic animations.\n */\nexport class Tempo implements IPlayer {\n\n protected _bpm: number; // beat per minute\n protected _ms: number; // millis per beat\n\n protected _listeners:{ [key:string]:ITempoListener } = {};\n protected _listenerInc:number = 0;\n public animateID:string;\n\n /**\n * Construct a new Tempo instance by beats-per-minute. Alternatively, you can use [`Tempo.fromBeat`](#link) to create from milliseconds.\n * @param bpm beats per minute\n */\n constructor( bpm:number ) {\n this.bpm = bpm;\n }\n\n /**\n * Create a new Tempo instance by specifying milliseconds-per-beat.\n * @param ms milliseconds per beat\n */\n static fromBeat( ms:number ):Tempo {\n return new Tempo( 60000 / ms );\n }\n\n /**\n * Beats-per-minute value\n */\n get bpm():number { return this._bpm; }\n set bpm( n:number ) {\n this._bpm = n;\n this._ms = 60000 / this._bpm;\n }\n\n /**\n * Milliseconds per beat (Note that this is derived from the bpm value).\n */\n get ms():number { return this._ms; }\n set ms( n:number ) {\n this._bpm = Math.floor( 60000 / n );\n this._ms = 60000 / this._bpm;\n }\n\n\n // Get a listener unique id\n protected _createID( listener:ITempoListener | Function ):string {\n let id:string = '';\n if ( typeof listener === 'function' ) {\n id = '_b' + ( this._listenerInc++ );\n } else {\n id = listener.name || '_b' + ( this._listenerInc++ );\n }\n return id;\n }\n\n\n /**\n * This is a core function that let you specify a rhythm and then define responses by calling the `start` and `progress` functions from the returned object. See [Animation guide](../guide/Animation-0700.html) for more details.\n * The `start` function lets you set a callback on every start. It takes a function ([`ITempoStartFn`](#link)).\n * The `progress` function lets you set a callback during progress. It takes a function ([`ITempoProgressFn`](#link)). Both functions let you optionally specify a time offset and a custom name.\n * See [Animation guide](../guide/animation-0700.html) for more details.\n * @param beats a rhythm in beats as a number or an array of numbers\n * @example `tempo.every(2).start( (count) => ... )`, `tempo.every([2,4,6]).progress( (count, t) => ... )`\n * @returns an object with chainable functions\n */\n every( beats:number | number[] ):ITempoResponses {\n const self = this;\n const p = Array.isArray( beats ) ? beats[0] : beats;\n\n return {\n start: function ( fn:ITempoStartFn, offset:number = 0, name?:string ): string {\n const id = name || self._createID( fn );\n self._listeners[id] = { name: id, beats: beats, period: p, index: 0, offset: offset, duration: -1, continuous: false, fn: fn };\n return this;\n },\n\n progress: function ( fn:ITempoProgressFn, offset:number = 0, name?:string ): string {\n const id = name || self._createID( fn );\n self._listeners[id] = { name: id, beats: beats, period: p, index: 0, offset: offset, duration: -1, continuous: true, fn: fn };\n return this;\n }\n };\n }\n\n\n /**\n * Usually you can add a tempo instance to a space via [`Space.add`](#link) and it will track time automatically.\n * But if necessary, you can track time manually via this function.\n * @param time current time in milliseconds\n */\n track( time ) {\n for ( const k in this._listeners ) {\n if ( this._listeners.hasOwnProperty( k ) ) {\n\n const li = this._listeners[k];\n const _t = ( li.offset ) ? time + li.offset : time;\n const ms = li.period * this._ms; // time per period\n let isStart = false;\n\n if ( _t > li.duration + ms ) {\n li.duration = _t - ( _t % this._ms ); // update\n if ( Array.isArray( li.beats ) ) { // find next period from array\n li.index = ( li.index + 1 ) % li.beats.length;\n li.period = li.beats[ li.index ];\n }\n isStart = true;\n }\n\n const count = Math.max( 0, Math.ceil( Math.floor( li.duration / this._ms ) / li.period ) );\n const params = ( li.continuous ) ? [count, Num.clamp( ( _t - li.duration ) / ms, 0, 1 ), _t, isStart] : [count];\n if ( li.continuous || isStart ) {\n const done = li.fn.apply( li, params );\n if ( done ) delete this._listeners[ li.name ];\n }\n }\n }\n }\n\n\n /**\n * Remove a `start` or `progress` callback function from the list of callbacks. See [`Tempo.every`](#link) for details\n * @param name a name string specified when creating the callback function.\n */\n stop( name:string ):void {\n if ( this._listeners[name] ) delete this._listeners[name];\n }\n\n\n /**\n * IPlayer interface. Internal implementation that calls `track( time )`.\n */\n animate( time, ftime ) {\n this.track( time );\n }\n\n /**\n * IPlayer interface. Not implementated.\n */\n resize( bound:Bound, evt?:Event ) {\n return; // not implemented in IPlayer\n }\n\n /**\n * IPlayer interface. Not implementated.\n */\n action( type:string, px:number, py:number, evt:Event ) {\n return;\n }\n\n}\n\n\n\n/**\n * Sound class simplifies common tasks like audio inputs and visualizations using a subset of Web Audio API. It can be used with other audio libraries like tone.js, and extended to support additional web audio functions. See [the guide](../guide/Sound-0800.html) to get started.\n */\nexport class Sound {\n\n private _type:SoundType;\n\n /** The audio context */\n _ctx:AudioContext;\n\n /** The audio node, which is usually a subclass liked OscillatorNode */\n _node:AudioNode;\n\n /**\n * The audio node to be connected to AudioContext when playing, if different that _node\n * This is usefull when using the connect() function to filter, as typically the output would\n * come from the filtering nodes\n */\n _outputNode:AudioNode;\n\n /** The audio stream when streaming from input device */\n _stream:MediaStream;\n\n /** Audio src when loading from file */\n _source:HTMLMediaElement;\n\n /* Audio buffer when using AudioBufferSourceNode */\n _buffer:AudioBuffer;\n\n /** Analyzer if any */\n analyzer:ISoundAnalyzer;\n\n protected _playing:boolean = false;\n\n protected _timestamp:number; // Tracking play time against ctx.currentTime\n\n /**\n * Construct a `Sound` instance. Usually, it's more convenient to use one of the static methods like [`Sound.load`](#function_load) or [`Sound.from`](#function_from).\n * @param type a `SoundType` string: \"file\", \"input\", or \"gen\"\n */\n constructor( type:SoundType ) {\n this._type = type;\n this._createAudioContext();\n }\n\n /**\n * Create an AudioContext instance. This is called internally only.\n */\n protected _createAudioContext() {\n const _ctx = window.AudioContext;\n if ( !_ctx ) throw( new Error( \"Your browser doesn't support Web Audio. (No AudioContext)\" ) );\n this._ctx = ( _ctx ) ? new _ctx() : undefined;\n }\n\n /**\n * Create a `Sound` given an [AudioNode](https://developer.mozilla.org/en-US/docs/Web/API/AudioNode) and an [AudioContext](https://developer.mozilla.org/en-US/docs/Web/API/AudioContext) from Web Audio API. See also [this example](../guide/js/examples/tone.html) using tone.js in the [guide](../guide/Sound-0800.html).\n * @param node an AudioNode instance\n * @param ctx an AudioContext instance\n * @param type a string representing a type of input source: either \"file\", \"input\", or \"gen\".\n * @param stream Optionally include a MediaStream, if the type is \"input\"\n * @returns a `Sound` instance\n */\n static from( node:AudioNode, ctx:AudioContext, type:SoundType = \"gen\", stream?:MediaStream ) {\n const s = new Sound( type );\n s._node = node;\n s._ctx = ctx;\n if ( stream ) s._stream = stream;\n return s;\n }\n\n\n /**\n * Create a `Sound` by loading from a sound file or an audio element.\n * @param source either an url string to load a sound file, or an audio element.\n * @param crossOrigin whether to support loading cross-origin. Default is \"anonymous\".\n * @returns a `Sound` instance\n * @example `Sound.load( '/path/to/file.mp3' )`\n */\n static load( source:HTMLMediaElement | string, crossOrigin:string = \"anonymous\" ):Promise<Sound> {\n return new Promise( ( resolve, reject ) => {\n const s = new Sound( \"file\" );\n s._source = ( typeof source === 'string' ) ? new Audio( source ) : source;\n s._source.autoplay = false;\n ( s._source as HTMLMediaElement ).crossOrigin = crossOrigin;\n s._source.addEventListener( \"ended\", function () { s._playing = false; } );\n s._source.addEventListener( 'error', function () { reject( \"Error loading sound\" ); } );\n s._source.addEventListener( 'canplaythrough', function () {\n if ( !s._node ) {\n s._node = s._ctx.createMediaElementSource( s._source );\n }\n resolve( s );\n } );\n } );\n\n }\n\n\n /**\n * Create a `Sound` by loading from a sound file url as `AudioBufferSourceNode`. This method is cumbersome since it can only be played once.\n * Use this method for now if you need to visualize sound in Safari and iOS. Once Apple has full support for FFT with streaming `HTMLMediaElement`, this method will likely be deprecated.\n * @param url an url to the sound file\n */\n static loadAsBuffer( url:string ):Promise<Sound> {\n return new Promise( ( resolve, reject ) => {\n const request = new XMLHttpRequest();\n request.open( 'GET', url, true );\n request.responseType = 'arraybuffer';\n\n const s = new Sound( \"file\" );\n request.onload = function() {\n s._ctx.decodeAudioData( request.response, function( buffer ) { // Decode asynchronously\n s.createBuffer( buffer );\n resolve( s );\n }, ( err ) => reject( \"Error decoding audio\" ) );\n };\n request.send();\n } );\n }\n\n\n /**\n * Create or re-use an AudioBuffer. Only needed if you are using `Sound.loadAsBuffer`.\n * @param buf an AudioBuffer. Optionally, you can call this without parameters to re-use existing buffer.\n */\n protected createBuffer( buf:AudioBuffer ):this {\n this._node = this._ctx.createBufferSource();\n if ( buf !== undefined ) this._buffer = buf;\n\n ( this._node as AudioBufferSourceNode ).buffer = this._buffer; // apply or re-use buffer\n ( this._node as AudioBufferSourceNode ).onended = () => { this._playing = false; };\n return this;\n }\n\n\n /**\n * Create a `Sound` by generating a waveform using [OscillatorNode](https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode).\n * @param type a string representing the waveform type: \"sine\", \"square\", \"sawtooth\", \"triangle\", \"custom\"\n * @param val the frequency value in Hz to play, or a PeriodicWave instance if type is \"custom\".\n * @returns a `Sound` instance\n * @example `Sound.generate( 'sine', 120 )`\n */\n static generate( type:OscillatorType, val:number | PeriodicWave ):Sound {\n const s = new Sound( \"gen\" );\n return s._gen( type, val );\n }\n\n\n // Create the oscillator\n protected _gen( type:OscillatorType, val:number | PeriodicWave ):Sound {\n this._node = this._ctx.createOscillator();\n const osc = ( this._node as OscillatorNode );\n osc.type = type;\n if ( type === 'custom' ) {\n osc.setPeriodicWave( val as PeriodicWave );\n } else {\n osc.frequency.value = val as number;\n }\n return this;\n }\n\n\n /**\n * Create a `Sound` by streaming from an input device like microphone. Note that this function returns a Promise which resolves to a Sound instance.\n * @param constraint @param constraint Optional constraints which can be used to select a specific input device. For example, you may use [`enumerateDevices`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/enumerateDevices) to find a specific deviceId;\n * @returns a `Promise` which resolves to `Sound` instance\n * @example `Sound.input().then( s => sound = s );`\n */\n static async input( constraint?:MediaStreamConstraints ):Promise<Sound> {\n try {\n const s = new Sound( \"input\" );\n if ( !s ) return undefined;\n const c = constraint ? constraint : { audio: true, video: false };\n s._stream = await navigator.mediaDevices.getUserMedia( c );\n s._node = s._ctx.createMediaStreamSource( s._stream );\n return s;\n } catch ( e ) {\n console.error( \"Cannot get audio from input device.\" );\n return Promise.resolve( null );\n }\n }\n\n\n /**\n * Get this Sound's AudioContext instance for advanced use-cases.\n */\n get ctx():AudioContext { return this._ctx; }\n\n\n /**\n * Get this Sound's AudioNode subclass instance for advanced use-cases.\n */\n get node():AudioNode { return this._node; }\n\n /**\n * Get this Sound's Output node AudioNode instance for advanced use-cases.\n */\n get outputNode():AudioNode { return this._outputNode; }\n\n /**\n * Get this Sound's MediaStream (eg, from microphone, if in use) instance for advanced use-cases. See [`Sound.input`](#link)\n */\n get stream():MediaStream { return this._stream; }\n\n\n /**\n * Get this Sound's Audio element (if used) instance for advanced use-cases. See [`Sound.load`](#link).\n */\n get source():HTMLMediaElement { return this._source; }\n\n\n /**\n * Get this Sound's AudioBuffer (if any) instance for advanced use-cases. See [`Sound.loadAsBuffer`](#link).\n */\n get buffer():AudioBuffer { return this._buffer; }\n set buffer( b:AudioBuffer ) { this._buffer = b; }\n\n\n /**\n * Get the type of input for this Sound instance. Either \"file\", \"input\", or \"gen\"\n */\n get type():SoundType { return this._type; }\n\n\n /**\n * Indicate whether the sound is currently playing.\n */\n get playing():boolean { return this._playing; }\n\n\n /**\n * A value between 0 to 1 to indicate playback progress.\n */\n get progress():number {\n let dur = 0;\n let curr = 0;\n if ( this._buffer ) {\n dur = this._buffer.duration;\n curr = ( this._timestamp ) ? this._ctx.currentTime - this._timestamp : 0;\n } else {\n dur = this._source.duration;\n curr = this._source.currentTime;\n }\n return curr / dur;\n }\n\n\n /**\n * Indicate whether the sound is ready to play. When loading from a file, this corresponds to a [\"canplaythrough\"](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState) event.\n * You can also use `this.source.addEventListener( 'canplaythrough', ...)` if needed. See also [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canplaythrough_event).\n */\n get playable():boolean {\n return ( this._type === \"input\" ) ? this._node !== undefined : ( !!this._buffer || this._source.readyState === 4 );\n }\n\n\n /**\n * If an analyzer is added (see [`analyze`](##unction_analyze) function), get the number of frequency bins in the analyzer.\n */\n get binSize():number {\n return this.analyzer.size;\n }\n\n\n /**\n * Get the sample rate of the audio, for example, at 44100 hz.\n */\n get sampleRate():number {\n return this._ctx.sampleRate;\n }\n\n\n /**\n * If the sound is generated, this sets and gets the frequency of the tone.\n */\n get frequency():number {\n return ( this._type === \"gen\" ) ? ( this._node as OscillatorNode ).frequency.value : 0;\n }\n set frequency( f:number ) {\n if ( this._type === \"gen\" ) ( this._node as OscillatorNode ).frequency.value = f;\n }\n\n\n /**\n * Connect another AudioNode to this `Sound` instance's AudioNode. Using this function, you can extend the capabilities of this `Sound` instance for advanced use cases such as filtering.\n * @param node another AudioNode\n */\n connect( node:AudioNode ):this {\n this._node.connect( node );\n return this;\n }\n\n /**\n * Sets the 'output' node for this Sound\n * This would typically be used after Sound.connect, if you are adding nodes\n * in your chain for filtering purposes.\n * @param outputNode The AudioNode that should connect to the AudioContext\n */\n setOutputNode( outputNode: AudioNode ):this {\n this._outputNode = outputNode;\n return this;\n }\n\n\n /**\n * Removes the 'output' node added from setOuputNode\n * Note: if you start the Sound after calling this, it will play via the default node\n */\n removeOutputNode():this {\n this._outputNode = null;\n return this;\n }\n\n\n /**\n * Add an analyzer to this `Sound`. Call this once only.\n * @param size the number of frequency bins\n * @param minDb Optional minimum decibels (corresponds to `AnalyserNode.minDecibels`)\n * @param maxDb Optional maximum decibels (corresponds to `AnalyserNode.maxDecibels`)\n * @param smooth Optional smoothing value (corresponds to `AnalyserNode.smoothingTimeConstant`)\n */\n analyze( size:number = 256, minDb:number = -100, maxDb:number = -30, smooth:number = 0.8 ) {\n const a = this._ctx.createAnalyser();\n a.fftSize = size * 2;\n a.minDecibels = minDb;\n a.maxDecibels = maxDb;\n a.smoothingTimeConstant = smooth;\n this.analyzer = {\n node: a,\n size: a.frequencyBinCount,\n data: new Uint8Array( a.frequencyBinCount )\n };\n this._node.connect( this.analyzer.node );\n return this;\n }\n\n\n // Get either time-domain or frequency domain\n protected _domain( time:boolean ):Uint8Array {\n if ( this.analyzer ) {\n if ( time ) {\n this.analyzer.node.getByteTimeDomainData( this.analyzer.data );\n } else {\n this.analyzer.node.getByteFrequencyData( this.analyzer.data );\n }\n return this.analyzer.data;\n }\n return new Uint8Array( 0 );\n }\n\n\n // Map domain data to another range\n protected _domainTo( time:boolean, size:PtLike, position:PtLike = [0,0], trim = [0,0] ):Group {\n const data = ( time ) ? this.timeDomain() : this.freqDomain() ;\n const g = new Group();\n for ( let i = trim[0], len = data.length - trim[1]; i < len; i++ ) {\n g.push( new Pt( position[0] + size[0] * i / len, position[1] + size[1] * data[i] / 255 ) );\n }\n return g;\n }\n\n\n /**\n * Get the raw time-domain data from analyzer as unsigned 8-bit integers. An analyzer must be added before calling this function (See [analyze](#function_analyze) function).\n */\n timeDomain():Uint8Array {\n return this._domain( true );\n }\n\n\n /**\n * Map the time-domain data from analyzer to a range. An analyzer must be added before calling this function (See [analyze](#function_analyze) function).\n * @param size map each data point `[index, value]` to `[width, height]`\n * @param position Optionally, set a starting `[x, y]` position. Default is `[0, 0]`\n * @param trim Optionally, trim the start and end values by `[startTrim, data.length-endTrim]`\n * @returns a Group containing the mapped values\n * @example form.point( s.timeDomainTo( space.size ) )\n */\n timeDomainTo( size:PtLike, position:PtLike = [0,0], trim = [0,0] ):Group {\n return this._domainTo( true, size, position, trim );\n }\n\n\n /**\n * Get the raw frequency-domain data from analyzer as unsigned 8-bit integers. An analyzer must be added before calling this function (See [analyze](#function_analyze) function).\n */\n freqDomain():Uint8Array {\n return this._domain( false );\n }\n\n\n /**\n * Map the frequency-domain data from analyzer to a range. An analyzer must be added before calling this function (See [analyze](#function_analyze) function).\n * @param size map each data point `[index, value]` to `[width, height]`\n * @param position Optionally, set a starting `[x, y]` position. Default is `[0, 0]`\n * @param trim Optionally, trim the start and end values by `[startTrim, data.length-endTrim]`\n * @returns a Group containing the mapped values\n * @example `form.point( s.freqDomainTo( space.size ) )`\n */\n freqDomainTo( size:PtLike, position:PtLike = [0,0], trim = [0,0] ):Group {\n return this._domainTo( false, size, position, trim );\n }\n\n\n /**\n * Stop playing and disconnect the AudioNode.\n */\n reset():this {\n this.stop();\n this._node.disconnect();\n return this;\n }\n\n\n /**\n * Start playing. Internally this connects the `AudioNode` to `AudioContext`'s destination.\n * @param timeAt optional parameter to play from a specific time\n */\n start( timeAt:number = 0 ):this {\n if ( !this._ctx ) {\n this._createAudioContext();\n } else if ( this._ctx.state === 'suspended' ) {\n this._ctx.resume();\n }\n\n if ( this._type === \"file\" ) {\n if ( this._buffer ) {\n ( this._node as AudioBufferSourceNode ).start( timeAt );\n this._timestamp = this._ctx.currentTime + timeAt;\n } else {\n this._source.play();\n if ( timeAt > 0 ) this._source.currentTime = timeAt;\n }\n } else if ( this._type === \"gen\" ) {\n this._gen( ( this._node as OscillatorNode ).type, ( this._node as OscillatorNode ).frequency.value );\n ( this._node as OscillatorNode ).start();\n if ( this.analyzer ) this._node.connect( this.analyzer.node );\n }\n\n ( this._outputNode || this._node ).connect( this._ctx.destination );\n this._playing = true;\n return this;\n }\n\n\n /**\n * Stop playing. Internally this also disconnects the `AudioNode` from `AudioContext`'s destination.\n */\n stop():this {\n\n if ( this._playing ) ( this._outputNode || this._node ).disconnect( this._ctx.destination );\n\n if ( this._type === \"file\" ) {\n if ( this._buffer ) {\n // Safari throws InvalidState error if stop() is called after finished playing\n if ( this.progress < 1 ) ( this._node as AudioBufferSourceNode ).stop();\n } else {\n this._source.pause();\n }\n\n } else if ( this._type === \"gen\" ) {\n ( this._node as OscillatorNode ).stop();\n\n } else if ( this._type === \"input\" ) {\n this._stream.getAudioTracks().forEach( track => track.stop() );\n }\n\n this._playing = false;\n return this;\n }\n\n\n /**\n * Toggle between `start` and `stop`. This won't work if using [`Sound.loadAsBuffer`](#link), since `AudioBuffer` can only be played once. (See [`Sound.createBuffer`](#link) to reset buffer for replay).\n */\n toggle():this {\n if ( this._playing ) {\n this.stop();\n } else {\n this.start();\n }\n return this;\n }\n\n\n}\n","import * as Canvas from \"./Canvas\";\nimport * as Create from \"./Create\";\nimport * as Form from \"./Form\";\nimport * as LinearAlgebra from \"./LinearAlgebra\";\nimport * as Num from \"./Num\";\nimport * as Op from \"./Op\";\nimport * as Pt from \"./Pt\";\nimport * as Space from \"./Space\";\nimport * as Color from \"./Color\";\nimport * as Util from \"./Util\";\nimport * as Dom from \"./Dom\";\nimport * as Svg from \"./Svg\";\nimport * as Typography from \"./Typography\";\nimport * as Physics from \"./Physics\";\nimport * as UI from \"./UI\";\nimport * as Play from \"./Play\";\nimport * as Image from \"./Image\";\nimport * as Types from \"./Types\";\n\nglobalThis.Pts = {\n ...Canvas, ...Create, ...Form,\n ...LinearAlgebra, ...Num, ...Op,\n ...Pt, ...Space, ...Color,\n ...Util, ...Dom, ...Svg,\n ...Typography, ...Physics, ...UI,\n ...Play, ...Image\n};\n\n// A function to switch scope for Pts library. eg, Pts.namespace( window );\nglobalThis.Pts.namespace = ( scope:any ) => {\n let lib = globalThis.Pts;\n for ( let k in lib ) {\n if ( k != \"namespace\" ) {\n scope[k] = lib[k];\n }\n }\n};\n\nglobalThis.Pts.quickStart = ( id:string, bg:string = \"#9ab\" ) => {\n if ( !window ) return;\n \n let s:any = globalThis;\n globalThis.Pts.namespace( s );\n \n s.space = new Canvas.CanvasSpace( id ).setup( {bgcolor: bg, resize: true, retina: true} );\n s.form = s.space.getForm();\n\n return function( animate = null, start = null, action = null, resize = null ) {\n s.space.add( {\n start: start,\n animate: animate,\n resize: resize,\n action: action,\n } );\n\n s.space.bindMouse().bindTouch().play();\n };\n\n};"],"mappings":"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","names":["Canvas_exports","__export","CanvasForm","CanvasSpace","Space_exports","__export","MultiTouchSpace","Space","Pt_exports","__export","Bound","Group","Pt","Util_exports","__export","Const","Util","Num_exports","__export","Geom","Num","Range","Shaping","Op_exports","__export","Circle","Curve","Line","Polygon","Rectangle","Triangle","LinearAlgebra_exports","__export","Mat","Vec","Vec","_Vec","a","b","i","len","d","Pt","magnitude","m","index","s","fn","Mat","_Mat","val","at","ang","g","Group","isNum","transposed","elementwise","ai","alen","p","bi","blen","defaultValue","z","useLongest","ps","pt","x","y","cosA","sinA","tanX","tanY","sx","sy","p1","p2","intercept","Line","yi","ang2","_errorLength","obj","param","Util","_errorOutofBound","Line","_Line","anchor","angle","magnitude","g","Group","Pt","p1","p2","m","c","line","pt","_line","p3","threshold","a","b","asProjection","proj","projectionVector","la","lb","_la","_lb","pa","pb","y1","px","py","Geom","ray","_ray","lineOrRay","poly","sourceIsRay","_lineOrRay","_poly","fn","pts","i","len","next","d","lines1","lines2","isRay","group","l1","l2","_ip","gridPt","t","gg","rect","_rect","box","Rectangle","num","size","index","cropAsCircle","ls","sides","sideIdx","graphic","atTail","h","unit","ps","_Rectangle","topLeft","widthOrSize","height","center","half","within","Circle","enclose","_pts","s","p","min","max","p0","rects","_rects","merged","k","corners","_center","ratio","asRows","mid","Num","rect1","rect2","resetBoundingBox","_rect1","_rect2","_Circle","r","Triangle","radius","circle","f","q","disc","discSqrt","t1","t2","circle1","circle2","_circle","dv","dr2","dr","ar","br","ar2","br2","ang","inc","_Triangle","top","left","tri","Polygon","opp","area","perim","md","_Polygon","closePath","sp","gs","right","lines","mag","det","sorted","dq","bot","hull","originIndex","_near","_item","unitAxis","dot","n","poly1","poly2","ln","info","minDist","edge","axis","dist","_poly1","_poly2","plen","b1","b2","c1","c2","smallest","lp","ins","polys","boxes","Curve","_Curve","steps","ts","copyStart","_index","ctrls","params","x","y","z","cp","step","Mat","tension","h2","h3","Mash","n","data","i","h","uheprng_default","seed","o","c","p","s","j","k","mash","initState","cleanString","inStr","hashString","t","Num","_Num","a","b","threshold","t","val","min","max","len","p","r","Pt","range","Vec","start","i","n","pts","_pts","Util","c","method","Shaping","currA","currB","targetA","targetB","seed","uheprng_default","Geom","_Geom","angle","radian","Const","minPt","maxPt","Group","ptOrIndex","direction","d","pt","axis","y","x","pa","pb","p1","p2","boundPt1","boundPt2","bounds","center","fn","da","db","det","ps","scale","anchor","scs","k","lenP","Mat","cos","sin","tanx","tany","line","_line","mat","rad","_Shaping","dt","t2","t4","t6","s","A","B","C","om2a","curve","Curve","steps","args","tt","Range","g","dims","mag","exclude","target","update","count","Const","_Util","lv","args","pos","isArray","a","p","i","message","defaultReturn","range","start","Num","pts","size","stride","loopBack","matchSize","chunks","part","st","index","k","flattenAsGroup","arr","Group","b","op","result","len","lenB","arrays","z","max","min","callback","c","fn","step","temp","url","request","space","filename","filetype","quality","ftype","blob","link","avgFrames","last","avg","now","minRequired","it","Util","Pt","_Pt","args","params","Util","dimensions","defaultValue","randomize","p","i","len","Num","s","n","threshold","radian","magnitude","anchorFromPt","m","change","fn","self","fns","_ops","axis","Vec","Const","Geom","scale","anchor","angle","line","Group","Bound","_Group","group","list","g","li","chunkSize","stride","loopBack","pts","index","count","param","pts_per_segment","ptOrIndex","t","chunk","tc","idx","d","dim","desc","a","b","ptFn","Mat","transposed","elementwise","useLongest","c","_Bound","rect","_g","half","w","h","UI_exports","__export","UI","UIButton","UIDragger","UIPointerActions","UIShape","UIShape","UIPointerActions","_UI","group","shape","states","id","Group","ui","d","key","value","type","fn","which","p","evt","newKey","uis","i","len","Rectangle","Circle","Polygon","fns","target","pt","index","temp","UI","UIButton","UA","_capID","t","enter","leave","ids","enterID","leaveID","s","UIDragger","Pt","endDrag","Space","Bound","Pt","b","ms","p","player","k","pid","time","err","toggle","t","duration","context","f","MultiTouchSpace","evt","callback","options","customTarget","bind","passive","which","ts","i","type","px","py","v","c","touch","UIPointerActions","Form_exports","__export","Font","Form","VisualForm","b","groups","shape","rest","i","len","a","c","width","linejoin","linecap","pts","radius","size","face","weight","style","lineHeight","Typography_exports","__export","Typography","Typography","fn","samples","distribution","m","avg","Pt","str","width","tail","trim","box","ratio","byHeight","bound","Bound","h","f","box2","bound2","nh","threshold","direction","defaultSize","val","d","Image_exports","__export","Img","Img","_Img","editable","space","crossOrigin","src","ready","img","res","__async","repeat","size","scale","s","resolve","reject","evt","canvasScale","nw","nh","width","height","cms","w","h","reptition","dynamic","b","p","rescale","imgData","no","Pt","d","sizeOrScale","asScale","box","css","blob","url","data","cv","CanvasForm","Mat","CanvasSpace","MultiTouchSpace","elem","callback","_selector","_existed","id","d","k","opt","r1","r2","auto","b","evt","p","box","Bound","bg","CanvasForm","lastColor","px","time","downloadOrCallback","filetype","bitrate","stream","recorder","url","a","_CanvasForm","VisualForm","space","_setup","ctx","off","clear","offset","c","width","linejoin","linecap","filled","stroked","strokeWidth","stops","vals","len","t","v","area1","area2","grad","i","mode","segments","sizeOrFont","weight","style","lineHeight","family","estimate","Typography","str","tail","vertical","center","_box","Util","Rectangle","py","Pt","Font","radius","shape","pt","Const","pts","rotation","startAngle","endAngle","cc","halfsize","x1","y1","x2","y2","it","ptOrRect","img","orig","pos","o","Img","txt","maxWidth","verticalAlign","overrideBaseline","size","crop","lstep","nextLine","sub","buffer","newln","dt","line","lines","lsize","lbox","lpad","Group","alignment","baseline","w","Create_exports","__export","Create","Delaunay","Noise","Create","bound","count","dimensions","pts","Group","i","p","Num","Pt","line","_line","Util","ln","Line","columns","rows","orientation","unit","offset","g","r","c","center","radius","angleOffset","Const","a","dx","dy","seed","np","Noise","Delaunay","__noise_grad3","__noise_permTable","args","x","y","s","v","j","n00","Vec","n01","n10","n11","_fade","f","tx","_Delaunay","triangleOnly","n","indices","st","opened","closed","tris","len","edges","circum","d","o","vs","sort","cs","k","Geom","minPt","maxPt","mid","dmax","tri","t","Triangle","b","m","Color_exports","__export","Color","_Color","Pt","args","p","c","Util","i","len","hex","fn","alpha","hexVal","mode","convert","fname","n","b","toNorm","ranges","Num","format","_hex","s","rgb","normalizedInput","normalizedOutput","r","g","max","min","h","l","d","hsl","q","t","sc","v","hsb","f","lab","lch","luv","cc","xyz","x","y","z","eps","kap","cy","xxx","zzz","u","refU","refV","L","cubeY","Geom","rad","Group","Color","Dom_exports","__export","DOMSpace","HTMLForm","HTMLSpace","DOMSpace","_DOMSpace","MultiTouchSpace","elem","callback","_selector","_existed","id","appendTo","d","k","opt","auto","b","evt","p","Bound","bg","key","val","update","styles","data","str","HTMLSpace","HTMLForm","parent","name","autoClass","player","el","_HTMLForm","VisualForm","space","v","unit","a","c","width","linejoin","linecap","sizeOrFont","weight","style","lineHeight","family","Font","group_id","group","item","ctx","st","pt","size","radius","shape","Pt","pts","halfsize","Util","txt","startAngle","endAngle","cc","Svg_exports","__export","SVGForm","SVGSpace","SVGSpace","_SVGSpace","DOMSpace","elem","callback","s","SVGForm","b","evt","parent","name","id","player","el","_SVGForm","VisualForm","space","k","v","a","c","width","linejoin","linecap","sizeOrFont","weight","style","lineHeight","family","Font","group_id","group","item","ctx","styles","st","pt","radius","shape","pts","p","Util","startAngle","endAngle","cc","start","Pt","end","largeArc","Geom","Const","sweep","d","halfsize","points","closePath","count","bound","Group","size","Rectangle","txt","Physics_exports","__export","Body","Particle","World","World","_World","bound","friction","gravity","Pt","Bound","g","f","id","name","ms","dt","fn","p","Body","index","from","count","param","p1","p2","dist","stiff","precise","m1","m2","mm","delta","distSq","d","rect","damping","Geom","np","c","prevDt","i","len","k","bds","klen","bk","m","mlen","Particle","args","b","r","lastDt","lt","a","v","damp","dp","dr","c1","c2","np1","np2","f1","f2","dm1","dm2","_Body","Group","body","autoLink","autoMass","li","Polygon","index1","index2","half","n","nd","n2","gs","ln","s","b1","b2","hit","cv","t","eg","lambda","m0","mr0","mr1","Circle","Play_exports","__export","Sound","Tempo","Tempo","_Tempo","bpm","ms","n","listener","id","beats","self","p","fn","offset","name","time","k","li","_t","isStart","count","params","Num","ftime","bound","evt","type","px","py","Sound","_Sound","_ctx","node","ctx","stream","s","source","crossOrigin","resolve","reject","url","request","buffer","err","buf","val","osc","constraint","__async","c","e","b","dur","curr","f","outputNode","size","minDb","maxDb","smooth","a","position","trim","data","g","Group","i","len","Pt","timeAt","track","__spreadValues","Canvas_exports","Create_exports","Form_exports","LinearAlgebra_exports","Num_exports","Op_exports","Pt_exports","Space_exports","Color_exports","Util_exports","Dom_exports","Svg_exports","Typography_exports","Physics_exports","UI_exports","Play_exports","Image_exports","scope","lib","k","id","bg","s","CanvasSpace","animate","start","action","resize"]}