Difference between revisions of "Camera View, Rotate, Trim and Pad a Map in Dart"

From RogueBasin
Jump to navigation Jump to search
(initial)
(No difference)

Revision as of 13:26, 16 October 2023

Dart Implementation of Map Transformations

The code below is versatile in that it is map engine agnostic.

It will trim, pad, copy and rotate about any list-of-lists.

Usage

Rotate Right

final map = '''
##########
###....###
###....###
###....###
###....###
###....###
######.###
######▒▒▒#''';

List<List<String>> mapList =
    map.trim().split('\n').map((row) => row.split('')).toList();

List<List<dynamic>> result = Transform.rotateRight(mapList);

String mapString = result.map((e) => e.join('')).join('\n');

print(mapString);

// ########
// ########
// ########
// ##.....#
// ##.....#
// ##.....#
// ▒......#
// ▒#######
// ▒#######
// ########

Pad

final map = '''
##########
###....###
###....###
###....###
###....###
###....###
######.###
######▒▒▒#''';

List<List<String>> mapList =
    map.trim().split('\n').map((row) => row.split('')).toList();

String getWall() => '#';

List<List<dynamic>> result = Transform.pad(mapList, 2, getWall);

String mapString = result.map((e) => e.join('')).join('\n');

print(mapString);

// ##############
// ##############
// ##############
// #####....#####
// #####....#####
// #####....#####
// #####....#####
// #####....#####
// ########.#####
// ########▒▒▒###
// ##############
// ##############

Trim

final map = '''
##############
##############
##############
#####....#####
#####....#####
#####....#####
#####....#####
#####....#####
########.#####
########▒▒▒###
##############
##############''';

List<List<String>> mapList =
    map.trim().split('\n').map((row) => row.split('')).toList();

bool isOuterWall(dynamic str) => str == '#';

List<List<dynamic>> result = Transform.trim(mapListPadded, isOuterWall);

String mapString = result.map((e) => e.join('')).join('\n');

print(mapString);

// ########
// #....###
// #....###
// #....###
// #....###
// #....###
// ####.###
// ####▒▒▒#
// ########

Copy

final map = '''
##########
###....###
###....###
###....###
###....###
###....###
######.###
######▒▒▒#''';

List<List<String>> mapList =
    map.trim().split('\n').map((row) => row.split('')).toList();

List<List<dynamic>> result = Transform.copy(mapList, 0, 0, 5, 5);

String mapString = result.map((e) => e.join('')).join('\n');

print(mapString);

// ######
// ###...
// ###...
// ###...
// ###...
// ###...

Dart Implementation

class Transform {
  // -----------------------------------------------------------------------
  // ROTATE
  // -----------------------------------------------------------------------

  /// Rotates to the right.
  static List<List<dynamic>> rotateRight(List<List<dynamic>> target) {
    List<List<dynamic>> rotatedList = [];
    final width = target.first.length;
    final height = target.length - 1;

    for (int column = 0; column < width; column++) {
      final List<dynamic> lineNew = [];

      for (int row = height; row >= 0; row--) {
        lineNew.add(target[row][column]);
      }

      rotatedList.add(lineNew);
    }

    return rotatedList;
  }

  // -----------------------------------------------------------------------
  // PAD
  // -----------------------------------------------------------------------

  /// Pads with WALL tiles returned by [getWall].
  static List<List<dynamic>> pad(
      List<List<dynamic>> mapShape, int padding, dynamic Function() getWall) {
    List<List<dynamic>> padded = _padTop(mapShape, padding, getWall);
    padded = rotateRight(padded);
    padded = _padTop(padded, padding, getWall);
    padded = rotateRight(padded);
    padded = _padTop(padded, padding, getWall);
    padded = rotateRight(padded);
    padded = _padTop(padded, padding, getWall);
    padded = rotateRight(padded);

    return padded;
  }

  /// Pads a WALL at the top
  static List<List<dynamic>> _padTop(
      List<List<dynamic>> other, int padding, dynamic Function() getWall) {
    final width = other.first.length;

    final List<List<dynamic>> mapNew = [];
    mapNew.addAll(List<List<dynamic>>.generate(padding, (index) {
      return List<dynamic>.generate(width, (index) => getWall.call());
    }));
    mapNew.addAll(other);

    return mapNew;
  }

  // -----------------------------------------------------------------------
  // TRIM
  // -----------------------------------------------------------------------

  /// Trims all outer WALLS down to a single outer wall.
  static List<List<dynamic>> trim(
      List<List<dynamic>> mapShape, bool Function(dynamic e) isOuterWall) {
    List<List<dynamic>> trimmed = _trimTopInternal(mapShape, isOuterWall);
    trimmed = rotateRight(trimmed);
    trimmed = _trimTopInternal(trimmed, isOuterWall);
    trimmed = rotateRight(trimmed);
    trimmed = _trimTopInternal(trimmed, isOuterWall);
    trimmed = rotateRight(trimmed);
    trimmed = _trimTopInternal(trimmed, isOuterWall);
    trimmed = rotateRight(trimmed);

    return trimmed;
  }

  /// Trims WALL tiles from the top of the other elements, leaves ony one WALL.
  static List<List<dynamic>> _trimTopInternal(
      List<List<dynamic>> other, bool Function(dynamic e) isOuterWall) {
    final List<List<dynamic>> rows = [];

    int trimTop = 0;
    for (int row = 0; row < other.length; row++) {
      final List<dynamic> line = other.elementAt(row);

      final isOnlyWallsInternal =
          line.where((dynamic e) => isOuterWall.call(e)).length == line.length;

      if (isOnlyWallsInternal == false) {
        break;
      }
      trimTop = row;
    }

    rows.addAll(other.getRange(trimTop, other.length));
    return rows;
  }

// -----------------------------------------------------------------------
// COPY
// -----------------------------------------------------------------------

  /// Copies the given coordinates.
  ///
  /// `x1` and `y1` are inclusive.
  static List<List<dynamic>> copy(
      List<List<dynamic>> target, int x0, int y0, int x1, int y1) {
    assert(x0 >= 0 && x1 < target.first.length);
    assert(y0 >= 0 && y1 < target.length);

    final List<List<dynamic>> copy = [];

    for (int y = y0; y <= y1; y++) {
      final List<dynamic> copyRow = [];
      for (int x = x0; x <= x1; x++) {
        copyRow.add(target[y][x]);
      }
      copy.add(copyRow);
    }

    return copy;
  }
}