import { ProgressTracker } from '../../utils/progressTracker' ; import { ImageQuantizerYieldValue } from '../imageQuantizerYieldValue' ; enum Direction { NONE = 0 , UP , LEFT , RIGHT , DOWN } interface Data { x : number ; y : number ; width : number ; height : number ; level : number ; index : number ; tracker : ProgressTracker ; callback ( x , y ) : void ; } export function * hilbertCurve ( width , height , callback ) { const maxBound = Math . max ( width , height ) ; const level = Math . floor ( Math . log ( maxBound ) / Math . log ( 2 ) + 1 ) ; const tracker = new ProgressTracker ( width * height , 99 ) ; const data = { width , height , level , callback , tracker , index : 0 , x : 0 , y : 0 , } ; yield * walkHilbert ( data , Direction . UP ) ; visit ( data , Direction . NONE ) ; } function * walkHilbert ( data , direction ) { if ( data . level < 1 ) return ; if ( data . tracker . shouldNotify ( data . index ) ) { yield { progress : data . tracker . progress } ; } data . level -- ; switch ( direction ) { case Direction . LEFT : yield * walkHilbert ( data , Direction . UP ) ; visit ( data , Direction . RIGHT ) ; yield * walkHilbert ( data , Direction . LEFT ) ; visit ( data , Direction . DOWN ) ; yield * walkHilbert ( data , Direction . LEFT ) ; visit ( data , Direction . LEFT ) ; yield * walkHilbert ( data , Direction . DOWN ) ; break ; case Direction . RIGHT : yield * walkHilbert ( data , Direction . DOWN ) ; visit ( data , Direction . LEFT ) ; yield * walkHilbert ( data , Direction . RIGHT ) ; visit ( data , Direction . UP ) ; yield * walkHilbert ( data , Direction . RIGHT ) ; visit ( data , Direction . RIGHT ) ; yield * walkHilbert ( data , Direction . UP ) ; break ; case Direction . UP : yield * walkHilbert ( data , Direction . LEFT ) ; visit ( data , Direction . DOWN ) ; yield * walkHilbert ( data , Direction . UP ) ; visit ( data , Direction . RIGHT ) ; yield * walkHilbert ( data , Direction . UP ) ; visit ( data , Direction . UP ) ; yield * walkHilbert ( data , Direction . RIGHT ) ; break ; case Direction . DOWN : yield * walkHilbert ( data , Direction . RIGHT ) ; visit ( data , Direction . UP ) ; yield * walkHilbert ( data , Direction . DOWN ) ; visit ( data , Direction . LEFT ) ; yield * walkHilbert ( data , Direction . DOWN ) ; visit ( data , Direction . DOWN ) ; yield * walkHilbert ( data , Direction . LEFT ) ; break ; default : break ; } data . level ++ ; } function visit ( data , direction ) { if ( data . x >= 0 && data . x < data . width && data . y >= 0 && data . y < data . height ) { data . callback ( data . x , data . y ) ; data . index ++ ; } switch ( direction ) { case Direction . LEFT : data . x -- ; break ; case Direction . RIGHT : data . x ++ ; break ; case Direction . UP : data . y -- ; break ; case Direction . DOWN : data . y ++ ; break ; } }