import { SimpleTileLayer } from '../simple-tile-layer' ; import { Point } from '../../../../models/cross-code-map' ; import { NodeTracer } from './node-grid' ; import { BoundaryTracer } from './boundary-tracer' ; describe ( 'boundary tracing' , ( ) => { let tracer ; beforeEach ( ( ) => { } ) ; beforeEach ( ( ) => { tracer = new NodeTracer ( ) ; } ) ; it ( 'simple rectangle without holes' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 2 , y : 2 } , { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 3 , y : 4 } , { x : 4 , y : 4 } , { x : 5 , y : 4 } , { x : 5 , y : 3 } , { x : 5 , y : 2 } , { x : 4 , y : 2 } , { x : 3 , y : 2 } , ] , holes : [ ] } ) ; } ) ; it ( 'simple with corners' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 11 , 2 , 8 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 10 , 2 , 9 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 3 , y : 1 } , { x : 2 , y : 2 } , { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 3 , y : 5 } , { x : 4 , y : 5 } , { x : 5 , y : 4 } , { x : 5 , y : 3 } , { x : 5 , y : 2 } , { x : 4 , y : 1 } , ] , holes : [ ] } ) ; } ) ; it ( '1 tile hole' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 0 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 2 , y : 5 } , { x : 2 , y : 6 } , { x : 3 , y : 6 } , { x : 4 , y : 6 } , { x : 5 , y : 6 } , { x : 5 , y : 5 } , { x : 5 , y : 4 } , { x : 5 , y : 3 } , { x : 4 , y : 3 } , { x : 3 , y : 3 } , ] , holes : [ [ { x : 3 , y : 4 } , { x : 3 , y : 5 } , { x : 4 , y : 5 } , { x : 4 , y : 4 } , ] ] } ) ; } ) ; it ( '4 tile hole' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 0 , 0 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 0 , 0 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 1 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 1 , y : 5 } , { x : 1 , y : 6 } , { x : 1 , y : 7 } , { x : 2 , y : 7 } , { x : 3 , y : 7 } , { x : 4 , y : 7 } , { x : 5 , y : 7 } , { x : 6 , y : 7 } , { x : 7 , y : 7 } , { x : 7 , y : 6 } , { x : 7 , y : 5 } , { x : 7 , y : 4 } , { x : 7 , y : 3 } , { x : 7 , y : 2 } , { x : 7 , y : 1 } , { x : 6 , y : 1 } , { x : 5 , y : 1 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , { x : 2 , y : 1 } , ] , holes : [ [ { x : 3 , y : 3 } , { x : 3 , y : 4 } , { x : 3 , y : 5 } , { x : 4 , y : 5 } , { x : 5 , y : 5 } , { x : 5 , y : 4 } , { x : 5 , y : 3 } , { x : 4 , y : 3 } , ] ] } ) ; } ) ; it ( 'hole with diagonals' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 0 , 0 ] , [ 0 , 2 , 9 , 0 , 10 , 2 , 0 , 0 ] , [ 0 , 2 , 0 , 0 , 0 , 2 , 0 , 0 ] , [ 0 , 2 , 2 , 8 , 11 , 2 , 0 , 0 ] , [ 0 , 2 , 2 , 2 , 2 , 2 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 1 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 1 , y : 5 } , { x : 1 , y : 6 } , { x : 2 , y : 6 } , { x : 3 , y : 6 } , { x : 4 , y : 6 } , { x : 5 , y : 6 } , { x : 6 , y : 6 } , { x : 6 , y : 5 } , { x : 6 , y : 4 } , { x : 6 , y : 3 } , { x : 6 , y : 2 } , { x : 6 , y : 1 } , { x : 5 , y : 1 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , { x : 2 , y : 1 } , ] , holes : [ [ { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 3 , y : 4 } , { x : 4 , y : 5 } , { x : 5 , y : 4 } , { x : 5 , y : 3 } , { x : 4 , y : 2 } , { x : 3 , y : 2 } , ] ] } ) ; } ) ; describe ( 'crash tests' , ( ) => { it ( 'weird shape' , ( ) => { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 9 , 10 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 8 , 11 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] ) ; const traceObj = tracer . getContour ( layer ) ; console . log ( traceObj ) ; } ) ; it ( '?!' , ( ) => { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( [ [ 0 , 10 , 2 , 10 , 10 , 8 , 8 , 8 ] , [ 0 , 9 , 10 , 10 , 10 , 8 , 10 , 8 ] , [ 2 , 9 , 10 , 0 , 2 , 0 , 2 , 8 ] , [ 11 , 9 , 10 , 2 , 10 , 8 , 2 , 0 ] , [ 0 , 2 , 8 , 8 , 9 , 8 , 8 , 0 ] , [ 10 , 9 , 8 , 8 , 11 , 9 , 8 , 0 ] , [ 2 , 8 , 11 , 8 , 10 , 11 , 0 , 0 ] , [ 10 , 8 , 8 , 8 , 2 , 0 , 0 , 0 ] ] ) ; const traceObj = tracer . getContour ( layer ) ; console . log ( traceObj ) ; } ) ; it ( '?!²' , ( ) => { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 10 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 11 , 0 , 11 , 8 , 8 , 0 , 0 ] , [ 0 , 0 , 0 , 10 , 0 , 0 , 0 , 0 , 2 , 0 , 2 , 2 , 11 , 8 , 10 , 8 , 11 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 10 , 0 , 0 , 10 , 2 , 8 , 9 , 9 , 8 , 10 , 11 , 10 , 8 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 2 , 9 , 0 , 10 , 10 , 9 , 10 , 10 , 10 , 10 , 11 , 0 , 10 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 8 , 10 , 9 , 11 , 11 , 11 , 8 , 11 , 2 , 2 , 10 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 9 , 8 , 2 , 2 , 2 , 9 , 11 , 10 , 8 , 9 , 10 , 11 , 2 , 8 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 9 , 8 , 2 , 10 , 11 , 9 , 9 , 10 , 9 , 2 , 10 , 11 , 8 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 9 , 8 , 9 , 0 , 2 , 10 , 9 , 11 , 11 , 11 , 0 , 8 , 10 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 8 , 8 , 0 , 9 , 11 , 9 , 0 , 11 , 8 , 11 , 0 , 0 , 10 , 2 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 8 , 0 , 8 , 8 , 9 , 8 , 11 , 11 , 11 , 10 , 0 , 10 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 11 , 9 , 9 , 9 , 9 , 9 , 9 , 10 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 0 , 11 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 11 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] ) ; const result = tracer . getContour ( layer ) ; console . log ( result ) ; } ) ; it ( 'evil pattern' , ( ) => { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( [ [ 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 2 , 0 , 0 ] , [ 0 , 0 , 11 , 0 , 0 , 0 ] , [ 0 , 0 , 2 , 0 , 0 , 0 ] , [ 0 , 2 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 ] ] ) ; const result = tracer . getContour ( layer ) ; console . log ( result ) ; } ) ; it ( 'forest/caves/cave-013-pandza-01' , ( ) => { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( [ [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 ] , [ 2 , 0 , 0 , 0 , 2 , 2 , 2 , 2 , 0 , 2 , 2 ] , [ 2 , 0 , 0 , 2 , 9 , 0 , 0 , 10 , 0 , 2 , 2 ] , [ 2 , 2 , 9 , 0 , 0 , 0 , 0 , 0 , 10 , 2 , 2 ] , [ 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] ] ) ; const result = tracer . getContour ( layer ) ; console . log ( result ) ; } ) ; } ) ; it ( 'complex' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 11 , 8 , 0 , 0 ] , [ 0 , 11 , 2 , 2 , 9 , 10 , 2 , 0 ] , [ 0 , 2 , 9 , 0 , 0 , 0 , 2 , 0 ] , [ 0 , 2 , 0 , 11 , 2 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 0 , 0 , 2 , 0 ] , [ 0 , 10 , 2 , 2 , 8 , 0 , 2 , 0 ] , [ 0 , 0 , 0 , 10 , 2 , 2 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 2 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 1 , y : 5 } , { x : 2 , y : 6 } , { x : 3 , y : 6 } , { x : 4 , y : 7 } , { x : 5 , y : 7 } , { x : 6 , y : 7 } , { x : 7 , y : 7 } , { x : 7 , y : 6 } , { x : 7 , y : 5 } , { x : 7 , y : 4 } , { x : 7 , y : 3 } , { x : 7 , y : 2 } , { x : 7 , y : 1 } , { x : 6 , y : 1 } , { x : 5 , y : 0 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , ] , holes : [ [ { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 3 , y : 4 } , { x : 4 , y : 3 } , { x : 5 , y : 3 } , { x : 6 , y : 3 } , { x : 6 , y : 2 } , { x : 5 , y : 1 } , { x : 4 , y : 2 } , { x : 3 , y : 2 } , ] , [ { x : 4 , y : 4 } , { x : 4 , y : 5 } , { x : 5 , y : 6 } , { x : 6 , y : 6 } , { x : 6 , y : 5 } , { x : 6 , y : 4 } , { x : 5 , y : 4 } , ] ] } ) ; } ) ; it ( 'full collision' , ( ) => { compare ( 0 , { layer : [ [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] , [ 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 ] ] } , { path : [ { x : 0 , y : 0 } , { x : 0 , y : 1 } , { x : 0 , y : 2 } , { x : 0 , y : 3 } , { x : 0 , y : 4 } , { x : 0 , y : 5 } , { x : 0 , y : 6 } , { x : 0 , y : 7 } , { x : 0 , y : 8 } , { x : 0 , y : 9 } , { x : 1 , y : 9 } , { x : 2 , y : 9 } , { x : 3 , y : 9 } , { x : 4 , y : 9 } , { x : 5 , y : 9 } , { x : 6 , y : 9 } , { x : 7 , y : 9 } , { x : 8 , y : 9 } , { x : 8 , y : 8 } , { x : 8 , y : 7 } , { x : 8 , y : 6 } , { x : 8 , y : 5 } , { x : 8 , y : 4 } , { x : 8 , y : 3 } , { x : 8 , y : 2 } , { x : 8 , y : 1 } , { x : 8 , y : 0 } , { x : 7 , y : 0 } , { x : 6 , y : 0 } , { x : 5 , y : 0 } , { x : 4 , y : 0 } , { x : 3 , y : 0 } , { x : 2 , y : 0 } , { x : 1 , y : 0 } , ] , holes : [ ] } ) ; } ) ; describe ( 'inception' , ( ) => { it ( 'outer' , ( ) => { compare ( 0 , { layer : [ [ 11 , 2 , 2 , 2 , 2 , 2 , 2 , 8 ] , [ 2 , 9 , 0 , 0 , 0 , 0 , 10 , 2 ] , [ 2 , 0 , 11 , 2 , 2 , 8 , 0 , 2 ] , [ 2 , 0 , 2 , 9 , 10 , 2 , 0 , 2 ] , [ 2 , 0 , 2 , 8 , 11 , 2 , 0 , 2 ] , [ 2 , 0 , 10 , 2 , 2 , 9 , 0 , 2 ] , [ 2 , 8 , 0 , 0 , 0 , 0 , 11 , 2 ] , [ 10 , 2 , 2 , 2 , 2 , 2 , 2 , 9 ] , ] } , { path : [ { x : 1 , y : 0 } , { x : 0 , y : 1 } , { x : 0 , y : 2 } , { x : 0 , y : 3 } , { x : 0 , y : 4 } , { x : 0 , y : 5 } , { x : 0 , y : 6 } , { x : 0 , y : 7 } , { x : 1 , y : 8 } , { x : 2 , y : 8 } , { x : 3 , y : 8 } , { x : 4 , y : 8 } , { x : 5 , y : 8 } , { x : 6 , y : 8 } , { x : 7 , y : 8 } , { x : 8 , y : 7 } , { x : 8 , y : 6 } , { x : 8 , y : 5 } , { x : 8 , y : 4 } , { x : 8 , y : 3 } , { x : 8 , y : 2 } , { x : 8 , y : 1 } , { x : 7 , y : 0 } , { x : 6 , y : 0 } , { x : 5 , y : 0 } , { x : 4 , y : 0 } , { x : 3 , y : 0 } , { x : 2 , y : 0 } , ] , holes : [ [ { x : 2 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 1 , y : 5 } , { x : 1 , y : 6 } , { x : 2 , y : 7 } , { x : 3 , y : 7 } , { x : 4 , y : 7 } , { x : 5 , y : 7 } , { x : 6 , y : 7 } , { x : 7 , y : 6 } , { x : 7 , y : 5 } , { x : 7 , y : 4 } , { x : 7 , y : 3 } , { x : 7 , y : 2 } , { x : 6 , y : 1 } , { x : 5 , y : 1 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , ] ] } ) ; } ) ; it ( 'inner' , ( ) => { compare ( 1 , { layer : [ [ 11 , 2 , 2 , 2 , 2 , 2 , 2 , 8 ] , [ 2 , 9 , 0 , 0 , 0 , 0 , 10 , 2 ] , [ 2 , 0 , 11 , 2 , 2 , 8 , 0 , 2 ] , [ 2 , 0 , 2 , 9 , 10 , 2 , 0 , 2 ] , [ 2 , 0 , 2 , 8 , 11 , 2 , 0 , 2 ] , [ 2 , 0 , 10 , 2 , 2 , 9 , 0 , 2 ] , [ 2 , 8 , 0 , 0 , 0 , 0 , 11 , 2 ] , [ 10 , 2 , 2 , 2 , 2 , 2 , 2 , 9 ] , ] } , { path : [ { x : 3 , y : 2 } , { x : 2 , y : 3 } , { x : 2 , y : 4 } , { x : 2 , y : 5 } , { x : 3 , y : 6 } , { x : 4 , y : 6 } , { x : 5 , y : 6 } , { x : 6 , y : 5 } , { x : 6 , y : 4 } , { x : 6 , y : 3 } , { x : 5 , y : 2 } , { x : 4 , y : 2 } , ] , holes : [ [ { x : 3 , y : 4 } , { x : 4 , y : 5 } , { x : 5 , y : 4 } , { x : 4 , y : 3 } , ] ] } ) ; } ) ; } ) ; describe ( 'separate blocks' , ( ) => { it ( 'top left' , ( ) => { compare ( 0 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 11 , 2 , 2 , 0 , 2 , 8 , 0 ] , [ 0 , 2 , 2 , 2 , 0 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 0 , 2 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 2 , 9 , 0 ] , [ 0 , 0 , 10 , 2 , 2 , 9 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 2 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 2 , y : 4 } , { x : 3 , y : 4 } , { x : 4 , y : 4 } , { x : 4 , y : 3 } , { x : 4 , y : 2 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , ] , holes : [ ] } ) ; } ) ; it ( 'bottom right' , ( ) => { compare ( 1 , { layer : [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , [ 0 , 11 , 2 , 2 , 0 , 2 , 8 , 0 ] , [ 0 , 2 , 2 , 2 , 0 , 2 , 2 , 0 ] , [ 0 , 2 , 2 , 2 , 0 , 2 , 2 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 2 , 2 , 0 ] , [ 0 , 0 , 2 , 2 , 2 , 2 , 9 , 0 ] , [ 0 , 0 , 10 , 2 , 2 , 9 , 0 , 0 ] , [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] } , { path : [ { x : 5 , y : 1 } , { x : 5 , y : 2 } , { x : 5 , y : 3 } , { x : 5 , y : 4 } , { x : 5 , y : 5 } , { x : 4 , y : 5 } , { x : 3 , y : 5 } , { x : 2 , y : 5 } , { x : 2 , y : 6 } , { x : 3 , y : 7 } , { x : 4 , y : 7 } , { x : 5 , y : 7 } , { x : 6 , y : 6 } , { x : 7 , y : 5 } , { x : 7 , y : 4 } , { x : 7 , y : 3 } , { x : 7 , y : 2 } , { x : 6 , y : 1 } , ] , holes : [ ] } ) ; } ) ; } ) ; it ( 'all types of tiles' , ( ) => { compare ( 0 , { layer : [ [ 0 , 1 , 1 , 1 , 1 , 1 , 4 , 0 ] , [ 0 , 27 , 2 , 2 , 2 , 24 , 5 , 0 ] , [ 0 , 2 , 25 , 1 , 26 , 2 , 6 , 0 ] , [ 0 , 2 , 24 , 1 , 27 , 2 , 7 , 0 ] , [ 12 , 26 , 2 , 2 , 2 , 25 , 0 , 0 ] , [ 13 , 3 , 23 , 2 , 20 , 3 , 3 , 3 ] , [ 14 , 0 , 22 , 2 , 21 , 16 , 17 , 3 ] , [ 15 , 0 , 3 , 3 , 3 , 18 , 19 , 3 ] ] } , { path : [ { x : 2 , y : 1 } , { x : 1 , y : 2 } , { x : 1 , y : 3 } , { x : 1 , y : 4 } , { x : 2 , y : 5 } , { x : 3 , y : 5 } , { x : 2 , y : 6 } , { x : 3 , y : 7 } , { x : 4 , y : 7 } , { x : 5 , y : 6 } , { x : 4 , y : 5 } , { x : 5 , y : 5 } , { x : 6 , y : 4 } , { x : 6 , y : 3 } , { x : 6 , y : 2 } , { x : 5 , y : 1 } , { x : 4 , y : 1 } , { x : 3 , y : 1 } , ] , holes : [ [ { x : 3 , y : 2 } , { x : 2 , y : 3 } , { x : 3 , y : 4 } , { x : 4 , y : 4 } , { x : 5 , y : 3 } , { x : 4 , y : 2 } , ] ] } ) ; } ) ; function compare ( index , input , expected ) { const layer = new SimpleTileLayer ( ) ; layer . initSimple ( input . layer ) ; const result = tracer . getContour ( layer ) ; const traceObj = result [ index ] ; expected . path = reorder ( expected . path , traceObj . points [ 0 ] ) ; const holes = [ ] ; for ( let i = 0 ; i < expected . holes . length ; i ++ ) { const hole = expected . holes [ i ] ; holes . push ( reorder ( hole , traceObj . holes [ i ] [ 0 ] ) ) ; } expected . holes = holes ; expect ( traceObj . points . map ( p => ( { x : p . x , y : p . y } ) ) ) . toEqual ( expected . path ) ; expect ( traceObj . holes . map ( h => h . map ( p => ( { x : p . x , y : p . y } ) ) ) ) . toEqual ( expected . holes ) ; } function reorder ( path , startPoint ) { const index = path . findIndex ( p => p . x === startPoint . x && p . y === startPoint . y ) ; expect ( index ) . toBeGreaterThanOrEqual ( 0 , `path should not contain point: {${ startPoint . x }/${ startPoint . y }}` ) ; return rotate ( path , index ) ; } function rotate ( arr , n ) { return arr . slice ( n , arr . length ) . concat ( arr . slice ( 0 , n ) ) ; } } ) ;