|
|
@@ -0,0 +1,89 @@
|
|
|
+import GridError from "../../errors/graph/layering/grid/GridError.js";
|
|
|
+
|
|
|
+/**
|
|
|
+ * Стека для укладка графа на двумерной плоскости
|
|
|
+ */
|
|
|
+export class Grid<TElement> {
|
|
|
+ /**
|
|
|
+ * Ячейки сетки, которые могут хранить в себе элементы
|
|
|
+ * @protected
|
|
|
+ */
|
|
|
+ protected readonly _cells: (TElement | undefined)[][];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Количество элементов в каждой из строк сетки
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ private readonly width: number;
|
|
|
+ /**
|
|
|
+ * Количество элементов в каждом из столбцов сетки
|
|
|
+ * @private
|
|
|
+ */
|
|
|
+ private readonly height: number;
|
|
|
+
|
|
|
+ public constructor(width: number, height: number) {
|
|
|
+ this.width = width;
|
|
|
+ this.height = height;
|
|
|
+ this._cells = Array.from({ length: height }, () => new Array(width));
|
|
|
+ }
|
|
|
+
|
|
|
+ public set(row: number, col: number, value: TElement) : this {
|
|
|
+ this.validate(row, col);
|
|
|
+
|
|
|
+ if(row >= this._cells.length)
|
|
|
+ this._cells.length = row + 1;
|
|
|
+
|
|
|
+ if(this._cells[row] === undefined)
|
|
|
+ this._cells[row] = [];
|
|
|
+
|
|
|
+ const r = this._cells[row]!;
|
|
|
+
|
|
|
+ if(col >= r.length)
|
|
|
+ r.length = col + 1;
|
|
|
+
|
|
|
+ r[col] = value;
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public get(row: number, col: number) : TElement | undefined {
|
|
|
+ this.validate(row, col);
|
|
|
+ return this._cells[row]![col];
|
|
|
+ }
|
|
|
+
|
|
|
+ public delete(row: number, col: number) : this {
|
|
|
+ this.validate(row, col);
|
|
|
+
|
|
|
+ const r = this._cells[row];
|
|
|
+ if(!r)
|
|
|
+ return this;
|
|
|
+
|
|
|
+ delete r[col];
|
|
|
+
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public isEmpty(row: number, col: number) : boolean {
|
|
|
+ this.validate(row, col);
|
|
|
+
|
|
|
+ const r = this._cells[row];
|
|
|
+ if(!r)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return r[col] === undefined;
|
|
|
+ }
|
|
|
+
|
|
|
+ public getSize(): { width: number; height: number } {
|
|
|
+ return { width: this.width, height: this.height };
|
|
|
+ }
|
|
|
+
|
|
|
+ protected validate(row: number, col: number) : void {
|
|
|
+ if(row < 0 || row >= this._cells.length)
|
|
|
+ throw new GridError(`Row index is out of bounds [0, ${this._cells.length - 1}]: ${row}`);
|
|
|
+
|
|
|
+ const r = this._cells[row]!;
|
|
|
+
|
|
|
+ if(col < 0 || col >= r.length)
|
|
|
+ throw new GridError(`Column index is out of bounds [0, ${r.length - 1}]: ${row}`);
|
|
|
+ }
|
|
|
+}
|