import { pipe } from 'fp-ts/function' ; import { Monoid , concatAll } from 'fp-ts/Monoid' ; export interface Point { readonly x : number ; readonly y : number ; } /**
 * A shape is a function that given a point
 * returns `true` if the point belongs to the shape and `false` otherwise
 */ export type Shape = ( point : Point ) => boolean ; /**
 * Crea a shape representing a circle
 */ export const disk = ( center , radius ) : Shape => ( point ) => distance ( point , center ) <= radius ; const distance = ( p1 , p2 ) => Math . sqrt ( Math . pow ( Math . abs ( p1 . x - p2 . x ) , 2 ) + Math . pow ( Math . abs ( p1 . y - p2 . y ) , 2 ) ) ; /**
 * We can define the first combinator which given a shape
 * returns its complimentary one (the negative)
 */ export const outside = ( s ) : Shape => ( point ) => ! s ( point ) ; /**
 * A monoid where `concat` represents the union of two `Shape`s
 */ export const MonoidUnion = { concat : ( first , second ) => ( point ) => first ( point ) || second ( point ) , empty : ( ) => false } ; /**
 * A monoid where `concat` represents the intersection of two `Shape`s
 */ const MonoidIntersection = { concat : ( first , second ) => ( point ) => first ( point ) && second ( point ) , empty : ( ) => true } ; /**
 * Using the combinator `outside` and `MonoidIntersection` we can
 * create a `Shape` representing a ring
 */ export const ring = ( point , bigRadius , smallRadius ) : Shape => MonoidIntersection . concat ( disk ( point , bigRadius ) , outside ( disk ( point , smallRadius ) ) ) ; export const mickeymouse = [ disk ( { x : 200 , y : 200 } , 100 ) , disk ( { x : 130 , y : 100 } , 60 ) , disk ( { x : 280 , y : 100 } , 60 ) ] ; export function draw ( shape ) { const canvas = document . getElementById ( 'canvas' ) as any ; const ctx = canvas . getContext ( '2d' ) as any ; const width = canvas . width ; const height = canvas . height ; const imagedata = ctx . createImageData ( width , height ) ; for ( let x = 0 ; x < width ; x ++ ) { for ( let y = 0 ; y < height ; y ++ ) { const point = { x , y } ; if ( shape ( point ) ) { const pixelIndex = ( point . y * width + point . x ) * 4 ; imagedata . data [ pixelIndex ] = 0 ; imagedata . data [ pixelIndex + 1 ] = 0 ; imagedata . data [ pixelIndex + 2 ] = 0 ; imagedata . data [ pixelIndex + 3 ] = 255 ; } } } ctx . putImageData ( imagedata , 0 , 0 ) ; }