import 'dart:ui' as ui; import 'package:dartterm/wfc/model.dart'; class Bitmap { final int sx; final int sy; final List data; const Bitmap(this.sx, this.sy, this.data); } class OverlappingModel extends Model { List> _patterns = []; List _colors = []; Map _colorOf = {}; OverlappingModel( Bitmap bitmap, int n, int width, int height, bool periodicInput, bool periodic, int symmetry, bool ground, Heuristic heuristic) : super(width, height, n, periodic, heuristic) { List sample = []; for (var i = 0; i < bitmap.data.length; i++) { var existing = bitmap.data[i]; var color = _colorOf[existing]; if (color == null) { color = _colors.length; _colorOf[existing] = color; _colors.add(existing); } sample[i] = color; } var c = _colors.length; List pattern(int Function(int, int) f) { return [ for (var y = 0; y < n; y++) for (var x = 0; x < n; x++) f(x, y) ]; } List rotate(List p) { return pattern((x, y) => p[n - 1 - y + x * n]); } List reflect(List p) { return pattern((x, y) => p[n - 1 - x + y * n]); } int hash(List p) { var result = 0, power = 1; for (var i = 0; i < p.length; i++) { result += p[p.length - 1 - i] * power; power *= c; } return result; } var sx = bitmap.sx; var sy = bitmap.sy; Map patternIndices = {}; List weightList = []; var xmax = periodicInput ? sx : sx - n + 1; var ymax = periodicInput ? sy : sy - n + 1; for (var y = 0; y < ymax; y++) { for (var x = 0; x < xmax; x++) { var ps = [ pattern((dx, dy) => sample[(x + dx) % sx + (y + dy) % sy * sx]) ]; ps.add(reflect(ps[0])); ps.add(rotate(ps[0])); ps.add(reflect(ps[2])); ps.add(rotate(ps[2])); ps.add(reflect(ps[4])); ps.add(rotate(ps[4])); ps.add(reflect(ps[6])); for (var k = 0; k < symmetry; k++) { var p = ps[k]; var h = hash(p); var ix = patternIndices[h]; if (ix != null) { weightList[ix] = weightList[ix] + 1; } else { patternIndices[h] = weightList.length; weightList.add(1.0); _patterns.add(p); } } } } weights = weightList; cT = weights.length; this.ground = ground; bool agrees(List p1, List p2, int dx, int dy) { int xmin = dx < 0 ? 0 : dx; int xmax = dx < 0 ? dx + n : n; int ymin = dy < 0 ? 0 : dy; int ymax = dy < 0 ? dy + n : n; for (var y = ymin; y < ymax; y++) { for (var x = xmin; x < xmax; x++) { if (p1[x + n * y] != p2[x - dx + n * (y - dy)]) { return false; } } } return true; } propagator = [ for (var d = 0; d < 4; d++) [ for (var t = 0; t < cT; t++) [ for (var t2 = 0; t2 < cT; t2++) if (agrees( _patterns[t], _patterns[t2], Model.dx[d], Model.dy[d])) t2 ] ] ]; } }