UNPKG

@logic-pad/core

Version:
58 lines (57 loc) 2.26 kB
import { normalizeShape, positionsToShape, shapeEquals, } from '../../../shapes.js'; import BTModule, { BTTile, IntArray2D, colorToBTTile, } from '../data.js'; export default class RegionShapeBTModule extends BTModule { instr; constructor(instr) { super(); this.instr = instr; } getShapeRegions(grid) { // TODO: This is extremely slow, because it doesn't check shapes when shapes are not fully enclosed const visited = IntArray2D.create(grid.width, grid.height); const regions = []; for (let y = 0; y < grid.height; y++) { for (let x = 0; x < grid.width; x++) { const tile = grid.getTile(x, y); if (tile !== colorToBTTile(this.instr.color) || visited.get(x, y)) continue; const positions = this.visitArea(grid, tile, visited, { x, y }); if (!positions) continue; const shape = normalizeShape(positionsToShape(positions, this.instr.color)); const existing = regions.find(island => shapeEquals(island.shape, shape)); if (existing) { existing.count++; } else { regions.push({ positions, shape, count: 1 }); } } } return regions; } visitArea(grid, tile, visited, pos) { const positions = [pos]; const sameTileQueue = [pos]; let incomplete = false; visited.set(pos.x, pos.y, 1); // Count same tile while (sameTileQueue.length > 0) { const curPos = sameTileQueue.pop(); for (const edge of grid.getEdges(curPos)) { if (visited.get(edge.x, edge.y)) continue; const edgeTile = grid.getTile(edge.x, edge.y); if (edgeTile === BTTile.Empty) { incomplete = true; } else if (edgeTile === tile) { positions.push(edge); sameTileQueue.push(edge); visited.set(edge.x, edge.y, 1); } } } return incomplete ? null : positions; } }