refactor: roads generation - reduce curves on routes rendering

This commit is contained in:
max 2022-08-21 00:02:32 +03:00
parent fc3e3b844d
commit e427050369
5 changed files with 68 additions and 37 deletions

View file

@ -1,5 +1,4 @@
import * as d3 from "d3";
import {drawPoint} from "utils/debugUtils";
import {round} from "utils/stringUtils";
@ -9,35 +8,16 @@ export function drawRoutes() {
const {cells, burgs} = pack;
const lineGen = d3.line().curve(d3.curveCatmullRom.alpha(0.1));
const getBurgCoords = (burgId: number): TPoint => {
if (!burgId) throw new Error("burgId must be positive");
const burg = burgs[burgId] as IBurg;
return [burg.x, burg.y];
};
const getPathPoints = (cellIds: number[]): TPoints =>
cellIds.map(cellId => {
const burgId = cells.burg[cellId];
if (burgId) return getBurgCoords(burgId);
return cells.p[cellId];
});
const normalizePoints = (points: TPoints): TPoints =>
points.map(([x, y], index) => {
return [x, y];
if (i === 17) {
cells.forEach(cellId => drawPoint(pack.cells.p[cellId]));
}
});
const SHARP_ANGLE = 135;
const VERY_SHARP_ANGLE = 115;
const points = adjustBurgPoints(); // mutable array of points
const routePaths: Dict<string[]> = {};
for (const {i, type, cells} of pack.routes) {
const points = getPathPoints(cells);
const normalizedPoints = normalizePoints(points);
const path = round(lineGen(normalizedPoints)!, 1);
straightenPathAngles(cells); // mutates points
const pathPoints = cells.map(cellId => points[cellId]);
const path = round(lineGen(pathPoints)!, 1);
if (!routePaths[type]) routePaths[type] = [];
routePaths[type].push(`<path id="${type}${i}" d="${path}"/>`);
@ -46,4 +26,49 @@ export function drawRoutes() {
for (const type in routePaths) {
routes.select(`[data-type=${type}]`).html(routePaths[type].join(""));
}
function adjustBurgPoints() {
const points = Array.from(cells.p);
for (const burg of burgs) {
if (burg.i === 0) continue;
const {cell, x, y} = burg as IBurg;
points[cell] = [x, y];
}
return points;
}
function straightenPathAngles(cellIds: number[]) {
for (let i = 1; i < cellIds.length - 1; i++) {
const cellId = cellIds[i];
if (cells.burg[cellId]) continue;
const prev = points[cellIds[i - 1]];
const that = points[cellId];
const next = points[cellIds[i + 1]];
const dAx = prev[0] - that[0];
const dAy = prev[1] - that[1];
const dBx = next[0] - that[0];
const dBy = next[1] - that[1];
const angle = (Math.atan2(dAx * dBy - dAy * dBx, dAx * dBx + dAy * dBy) * 180) / Math.PI;
if (Math.abs(angle) < SHARP_ANGLE) {
const middleX = (prev[0] + next[0]) / 2;
const middleY = (prev[1] + next[1]) / 2;
if (Math.abs(angle) < VERY_SHARP_ANGLE) {
const newX = (that[0] + middleX * 2) / 3;
const newY = (that[1] + middleY * 2) / 3;
points[cellId] = [newX, newY];
continue;
}
const newX = (that[0] + middleX) / 2;
const newY = (that[1] + middleY) / 2;
points[cellId] = [newX, newY];
}
}
}
}