Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { Point, EdgeInfo } from "../../types";
import { pointsClose, removeDuplicateEdges } from "../utils/geometry";
import { Grid } from "./grid";
import { scanCellWindow } from "./grid-scan";
import { findClosestEdgeInWindow, findClosestVertexInWindow } from "./grid-search";
export class SquareGrid implements Grid {
constructor(private scale: number) {}
pixelToCell(pixel: Point): { col: number; row: number } {
const col = Math.floor(pixel.x / this.scale);
const row = Math.floor(pixel.y / this.scale);
return { col, row };
}
cellToPixel(cell: { col: number; row: number }): Point {
return {
x: cell.col * this.scale + this.scale / 2,
y: cell.row * this.scale + this.scale / 2,
};
}
getNeighbors(cell: {
col: number;
row: number;
}): { col: number; row: number }[] {
const { col, row } = cell;
return [
{ col, row: row - 1 }, // North
{ col: col + 1, row }, // East
{ col, row: row + 1 }, // South
{ col: col - 1, row }, // West
];
}
getCellPolygon(cell: { col: number; row: number }): Point[] {
const x = cell.col * this.scale;
const y = cell.row * this.scale;
return [
{ x, y },
{ x: x + this.scale, y },
{ x: x + this.scale, y: y + this.scale },
{ x, y: y + this.scale },
];
}
getCellEdges(cell: { col: number; row: number }): EdgeInfo[] {
const poly = this.getCellPolygon(cell);
return poly.map((p, i) => ({
type: "edge",
points: [p, poly[(i + 1) % poly.length]],
}));
}
getEdgeAt(
pixel: Point,
threshold: number,
gridWidth: number,
gridHeight: number
): EdgeInfo | null {
const approxCol = Math.floor(pixel.x / this.scale);
const approxRow = Math.floor(pixel.y / this.scale);
return findClosestEdgeInWindow(
pixel,
threshold,
gridWidth,
gridHeight,
approxCol,
approxRow,
1,
1,
(cell) => this.getCellEdges(cell)
);
}
getVertexAt(
pixel: Point,
threshold: number,
gridWidth: number,
gridHeight: number
): Point | null {
const approxCol = Math.floor(pixel.x / this.scale);
const approxRow = Math.floor(pixel.y / this.scale);
return findClosestVertexInWindow(
pixel,
threshold,
gridWidth,
gridHeight,
approxCol,
approxRow,
1,
1,
(cell) => this.getCellPolygon(cell)
);
}
getEdgesAtVertex(
vertex: Point,
gridWidth: number,
gridHeight: number
): EdgeInfo[] {
const edges: EdgeInfo[] = [];
const epsilon = 0.1;
const approxCol = Math.floor(vertex.x / this.scale);
const approxRow = Math.floor(vertex.y / this.scale);
scanCellWindow(gridWidth, gridHeight, approxCol, approxRow, 1, 1, (c, r) => {
const cellEdges = this.getCellEdges({ col: c, row: r });
for (const edge of cellEdges) {
if (
pointsClose(vertex, edge.points[0], epsilon) ||
pointsClose(vertex, edge.points[1], epsilon)
) {
edges.push(edge);
}
}
});
return removeDuplicateEdges(edges);
}
}
|