lr-core
Version:
Line Rider core library
193 lines (161 loc) • 4.89 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ddaCells = ddaCells;
exports.classicCells = classicCells;
exports.legacyCells = legacyCells;
var _hashNumberPair = require('../../utils/hashNumberPair.js');
var _dda = require('../../utils/dda.js');
var _dda2 = _interopRequireDefault(_dda);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ddaCells({ p1, p2 }, gridSize) {
return (0, _dda2.default)(p1.x / gridSize, p1.y / gridSize, p2.x / gridSize, p2.y / gridSize).map(({ x, y }) => (0, _hashNumberPair.hashIntPair)(x, y));
}
// 6.2
function classicCells(line, gridSize) {
let cellsPos = ClassicCells.getCellsPos(line, gridSize);
return cellsPos.map(({ x, y }) => (0, _hashNumberPair.hashIntPair)(x, y));
}
// 6.1
function legacyCells(line, gridSize) {
return LegacyCells.getCellsPos(line, gridSize).map(({ x, y }) => (0, _hashNumberPair.hashIntPair)(x, y));
}
class ClassicCells {
static getCellsPos(line, gridSize) {
var cellsPos = [];
let cellPosStart = getCellPosAndOffset(line.p1.x, line.p1.y, gridSize);
let cellPosEnd = getCellPosAndOffset(line.p2.x, line.p2.y, gridSize);
cellsPos.push(cellPosStart);
if (line.c.vec.x === 0 && line.c.vec.y === 0 || cellPosStart.x === cellPosEnd.x && cellPosStart.y === cellPosEnd.y) {
return cellsPos; // done
}
let box = getBox(cellPosStart.x, cellPosStart.y, cellPosEnd.x, cellPosEnd.y);
let getNextPos;
if (line.c.vec.x === 0) {
getNextPos = (l, x, y, dx, dy) => {
return { x: x, y: y + dy };
};
} else if (line.c.vec.y === 0) {
getNextPos = (l, x, y, dx, dy) => {
return { x: x + dx, y: y };
};
} else {
getNextPos = this.getNextPos;
}
let cellPos = cellPosStart;
let pos = { x: line.p1.x, y: line.p1.y };
while (cellPos != null) {
let d = this.getDelta(line, cellPos, gridSize);
let nextPos = getNextPos(line, pos.x, pos.y, d.x, d.y);
let nextCellPos = getCellPosAndOffset(nextPos.x, nextPos.y, gridSize);
if (inBounds(nextCellPos, box)) {
cellsPos.push(nextCellPos);
cellPos = nextCellPos;
pos = nextPos;
} else {
cellPos = null;
}
}
return cellsPos;
}
static getNextPos(line, x, y, dx, dy) {
let slope = line.c.vec.y / line.c.vec.x;
let yNext = y + slope * dx;
if (Math.abs(yNext - y) < Math.abs(dy)) {
return {
x: x + dx,
y: yNext
};
}
if (Math.abs(yNext - y) === Math.abs(dy)) {
return {
x: x + dx,
y: y + dy
};
}
return {
x: x + line.c.vec.x * dy / line.c.vec.y,
y: y + dy
};
}
static getDelta(line, cellPos, gridSize) {
let dx, dy;
if (cellPos.x < 0) {
dx = (gridSize + cellPos.gx) * (line.c.vec.x > 0 ? 1 : -1);
} else {
dx = -cellPos.gx + (line.c.vec.x > 0 ? gridSize : -1);
}
if (cellPos.y < 0) {
dy = (gridSize + cellPos.gy) * (line.c.vec.y > 0 ? 1 : -1);
} else {
dy = -cellPos.gy + (line.c.vec.y > 0 ? gridSize : -1);
}
return { x: dx, y: dy };
}
}
class LegacyCells extends ClassicCells {
static getDelta(line, cellPos, gridSize) {
return {
x: -cellPos.gx + (line.c.vec.x > 0 ? gridSize : -1),
y: -cellPos.gy + (line.c.vec.y > 0 ? gridSize : -1)
};
}
static getNextPos(line, x, y, dx, dy) {
let slope = line.c.vec.y / line.c.vec.x;
let yIsThisBelowActualY0 = line.p1.y - slope * line.p1.x;
let yDoesThisEvenWork = Math.round(slope * (x + dx) + yIsThisBelowActualY0);
if (Math.abs(yDoesThisEvenWork - y) < Math.abs(dy)) {
return {
x: x + dx,
y: yDoesThisEvenWork
};
}
if (Math.abs(yDoesThisEvenWork - y) === Math.abs(dy)) {
return {
x: x + dx,
y: y + dy
};
}
return {
x: Math.round((y + dy - yIsThisBelowActualY0) / slope),
y: y + dy
};
}
}
function getCellPosAndOffset(px, py, gridSize) {
let { x, y } = getCellPos(px, py, gridSize);
return {
x: x,
y: y,
gx: px - gridSize * x,
gy: py - gridSize * y
};
}
function getCellPos(x, y, gridSize) {
return {
x: getCellCor(x, gridSize),
y: getCellCor(y, gridSize)
};
}
function getCellCor(x, gridSize) {
return Math.floor(x / gridSize);
}
function getBox(x1, y1, x2, y2) {
let left = Math.min(x1, x2);
let right = Math.max(x1, x2);
let top = Math.min(y1, y2);
let bottom = Math.max(y1, y2);
return {
left: left,
right: right,
top: top,
bottom: bottom,
corners: [[left, top], [left, bottom], [right, top], [right, bottom]].map(c => {
return { x: c[0], y: c[1] };
})
};
}
function inBounds(p, box) {
return p.x >= box.left && p.x <= box.right && p.y >= box.top && p.y <= box.bottom;
}