mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
refactor: drawCultures
This commit is contained in:
parent
6a3ef0f790
commit
cbe6da0949
4 changed files with 70 additions and 33 deletions
|
|
@ -1,41 +1,22 @@
|
|||
import {connectVertices} from "scripts/connectVertices";
|
||||
import * as d3 from "d3";
|
||||
|
||||
import {getPaths} from "./utilts";
|
||||
|
||||
export function drawCultures() {
|
||||
/* uses */ const {cells, vertices, cultures} = pack;
|
||||
|
||||
cults.selectAll("path").remove(); // cleanup
|
||||
const getType = (cellId: number) => cells.culture[cellId];
|
||||
const paths = getPaths(cells.c, cells.v, vertices, getType);
|
||||
|
||||
const used = new Uint8Array(cells.i.length);
|
||||
const paths = new Array(cultures.length).fill("");
|
||||
const getColor = (i: number) => i && (cultures[i] as ICulture).color;
|
||||
|
||||
for (const i of cells.i) {
|
||||
if (!cells.culture[i]) continue;
|
||||
if (used[i]) continue;
|
||||
used[i] = 1;
|
||||
const cultureId = cells.culture[i];
|
||||
const onborder = cells.c[i].some(n => cells.culture[n] !== cultureId);
|
||||
if (!onborder) continue;
|
||||
|
||||
const startingVertex = cells.v[i].find(v => vertices.c[v].some(i => cells.culture[i] !== cultureId));
|
||||
if (startingVertex === undefined)
|
||||
throw new Error(`Draw cultures: starting vertex for culture ${cultureId} is not found`);
|
||||
|
||||
const ofSameType = (cellId: number) => cells.culture[cellId] === cultureId;
|
||||
const chain = connectVertices({vertices, startingVertex, ofSameType});
|
||||
|
||||
if (chain.length < 3) continue;
|
||||
const points = chain.map(v => vertices.p[v]);
|
||||
|
||||
paths[cultureId] += "M" + points.join("L") + "Z";
|
||||
}
|
||||
|
||||
const data = paths.map((p, i) => [p, i]).filter(d => d[0].length > 10);
|
||||
cults
|
||||
d3.select("#cults")
|
||||
.selectAll("path")
|
||||
.data(data)
|
||||
.remove()
|
||||
.data(Object.entries(paths))
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("d", d => d[0])
|
||||
.attr("fill", d => cultures[d[1]].color)
|
||||
.attr("id", d => "culture" + d[1]);
|
||||
.attr("d", ([, path]) => path)
|
||||
.attr("fill", ([i]) => getColor(Number(i)))
|
||||
.attr("id", ([i]) => "culture" + i);
|
||||
}
|
||||
|
|
|
|||
40
src/layers/renderers/utilts.ts
Normal file
40
src/layers/renderers/utilts.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import {connectVertices} from "scripts/connectVertices";
|
||||
|
||||
export function getPaths(
|
||||
cellNeighbors: number[][],
|
||||
cellVertices: number[][],
|
||||
vertices: IGraphVertices,
|
||||
getType: (cellId: number) => number
|
||||
) {
|
||||
const paths: Dict<string> = {};
|
||||
|
||||
function addPath(index: number, points: TPoints) {
|
||||
if (!paths[index]) paths[index] = "";
|
||||
paths[index] += "M" + points.join("L") + "Z";
|
||||
}
|
||||
|
||||
const checkedCells = new Uint8Array(cellNeighbors.length);
|
||||
for (let cellId = 0; cellId < cellNeighbors.length; cellId++) {
|
||||
if (checkedCells[cellId]) continue;
|
||||
if (!getType(cellId)) continue;
|
||||
checkedCells[cellId] = 1;
|
||||
|
||||
const type = getType(cellId);
|
||||
const ofSameType = (cellId: number) => getType(cellId) === type;
|
||||
|
||||
const isOnborder = cellNeighbors[cellId].some(cellId => !ofSameType(cellId));
|
||||
if (!isOnborder) continue;
|
||||
|
||||
const startingVertex = cellVertices[cellId].find(v => vertices.c[v].some(cellId => !ofSameType(cellId)));
|
||||
if (startingVertex === undefined) throw new Error(`getPath: starting vertex for cell ${cellId} is not found`);
|
||||
|
||||
const chain = connectVertices({vertices, startingVertex, ofSameType, checkedCellsMutable: checkedCells});
|
||||
|
||||
if (chain.length < 3) continue;
|
||||
const points = chain.map(v => vertices.p[v]);
|
||||
|
||||
addPath(type, points);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
|
@ -94,21 +94,34 @@ const CONNECT_VERTICES_MAX_ITERATIONS = 50000;
|
|||
export function connectVertices({
|
||||
vertices,
|
||||
startingVertex,
|
||||
ofSameType
|
||||
ofSameType,
|
||||
checkedCellsMutable
|
||||
}: {
|
||||
vertices: IGraphVertices;
|
||||
startingVertex: number;
|
||||
ofSameType: (cellId: number) => boolean;
|
||||
checkedCellsMutable?: Uint8Array;
|
||||
}) {
|
||||
const chain: number[] = []; // vertices chain to form a path
|
||||
|
||||
const addToChecked = (cellIds: number[]) => {
|
||||
if (checkedCellsMutable) {
|
||||
cellIds.forEach(cellId => {
|
||||
checkedCellsMutable[cellId] = 1;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let next = startingVertex;
|
||||
for (let i = 0; i === 0 || (next !== startingVertex && i < CONNECT_VERTICES_MAX_ITERATIONS); i++) {
|
||||
const previous = chain.at(-1);
|
||||
const current = next;
|
||||
chain.push(current);
|
||||
|
||||
const [c1, c2, c3] = vertices.c[current].map(ofSameType);
|
||||
const neibCells = vertices.c[current];
|
||||
addToChecked(neibCells);
|
||||
|
||||
const [c1, c2, c3] = neibCells.map(ofSameType);
|
||||
const [v1, v2, v3] = vertices.v[current];
|
||||
|
||||
if (v1 !== previous && c1 !== c2) next = v1;
|
||||
|
|
|
|||
3
src/types/common.d.ts
vendored
3
src/types/common.d.ts
vendored
|
|
@ -6,6 +6,9 @@ interface Dict<T> {
|
|||
[key: string]: T;
|
||||
}
|
||||
|
||||
// element of Object.entries
|
||||
type ObjectEntry<T> = [string, T];
|
||||
|
||||
type UintArray = Uint8Array | Uint16Array | Uint32Array;
|
||||
type IntArray = Int8Array | Int16Array | Int32Array;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue