mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
Fix for drawing religions into lakes and water clipping for biomes and cultures (#376)
This commit is contained in:
parent
d1b249ae79
commit
228b4f2932
2 changed files with 28 additions and 25 deletions
|
|
@ -105,7 +105,7 @@ button, select, a {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#statesBody, #provincesBody {
|
#statesBody, #provincesBody, #relig, #biomes, #cults {
|
||||||
stroke-width: .6;
|
stroke-width: .6;
|
||||||
fill-rule: evenodd;
|
fill-rule: evenodd;
|
||||||
mask: url(#land);
|
mask: url(#land);
|
||||||
|
|
|
||||||
|
|
@ -535,8 +535,9 @@ function drawReligions() {
|
||||||
relig.selectAll("path").remove();
|
relig.selectAll("path").remove();
|
||||||
const cells = pack.cells, vertices = pack.vertices, religions = pack.religions, features = pack.features, n = cells.i.length;
|
const cells = pack.cells, vertices = pack.vertices, religions = pack.religions, features = pack.features, n = cells.i.length;
|
||||||
const used = new Uint8Array(cells.i.length);
|
const used = new Uint8Array(cells.i.length);
|
||||||
const fUsed = []; // already added features like lakes
|
const vArray = new Array(religions.length); // store vertices array
|
||||||
const paths = new Array(religions.length).fill("");
|
const body = new Array(religions.length).fill(""); // store path around each religion
|
||||||
|
const gap = new Array(religions.length).fill(""); // store path along water for each religion to fill the gaps
|
||||||
|
|
||||||
for (const i of cells.i) {
|
for (const i of cells.i) {
|
||||||
if (!cells.religion[i]) continue;
|
if (!cells.religion[i]) continue;
|
||||||
|
|
@ -545,40 +546,42 @@ function drawReligions() {
|
||||||
const r = cells.religion[i];
|
const r = cells.religion[i];
|
||||||
const onborder = cells.c[i].filter(n => cells.religion[n] !== r);
|
const onborder = cells.c[i].filter(n => cells.religion[n] !== r);
|
||||||
if (!onborder.length) continue;
|
if (!onborder.length) continue;
|
||||||
const f = cells.f[onborder[0]];
|
const borderWith = cells.c[i].map(c => cells.religion[c]).find(n => n !== r);
|
||||||
if (fUsed[f]) continue;
|
const vertex = cells.v[i].find(v => vertices.c[v].some(i => cells.religion[i] === borderWith));
|
||||||
if (features[f].type === "lake") {
|
const chain = connectVertices(vertex, r, borderWith);
|
||||||
paths[r] += defs.select("mask#land > path#land_"+f).attr("d");
|
|
||||||
fUsed[f] = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vertex = cells.v[i].find(v => vertices.c[v].some(n => cells.religion[n] !== r));
|
|
||||||
const chain = connectVertices(vertex, r);
|
|
||||||
if (chain.length < 3) continue;
|
if (chain.length < 3) continue;
|
||||||
const points = chain.map(v => vertices.p[v]);
|
const points = chain.map(v => vertices.p[v[0]]);
|
||||||
paths[r] += "M" + points.join("L") + "Z";
|
if (!vArray[r]) vArray[r] = [];
|
||||||
|
vArray[r].push(points);
|
||||||
|
body[r] += "M" + points.join("L");
|
||||||
|
gap[r] += "M" + vertices.p[chain[0][0]] + chain.reduce((r2,v,i,d) => !i ? r2 : !v[2] ? r2 + "L" + vertices.p[v[0]] : d[i+1] && !d[i+1][2] ? r2 + "M" + vertices.p[v[0]] : r2, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = paths.map((p, i) => [p, i]).filter(d => d[0].length > 10);
|
const bodyData = body.map((p, i) => [p.length > 10 ? p : null, i, religions[i].color]).filter(d => d[0]);
|
||||||
relig.selectAll("path").data(data).enter().append("path").attr("d", d => d[0]).attr("fill", d => religions[d[1]].color).attr("id", d => "religion"+d[1]);
|
relig.selectAll("path").data(bodyData).enter().append("path").attr("d", d => d[0]).attr("fill", d => d[2]).attr("stroke", "none").attr("id", d => "religion"+d[1]);
|
||||||
|
const gapData = gap.map((p, i) => [p.length > 10 ? p : null, i, religions[i].color]).filter(d => d[0]);
|
||||||
|
relig.selectAll(".path").data(gapData).enter().append("path").attr("d", d => d[0]).attr("fill", "none").attr("stroke", d => d[2]).attr("id", d => "religion-gap"+d[1]).attr("stroke-width", "10px");
|
||||||
|
|
||||||
// connect vertices to chain
|
// connect vertices to chain
|
||||||
function connectVertices(start, t) {
|
function connectVertices(start, t, religion) {
|
||||||
const chain = []; // vertices chain to form a path
|
const chain = []; // vertices chain to form a path
|
||||||
|
let land = vertices.c[start].some(c => cells.h[c] >= 20 && cells.religion[c] !== t);
|
||||||
|
function check(i) {religion = cells.religion[i]; land = cells.h[i] >= 20;}
|
||||||
|
|
||||||
for (let i=0, current = start; i === 0 || current !== start && i < 20000; i++) {
|
for (let i=0, current = start; i === 0 || current !== start && i < 20000; i++) {
|
||||||
const prev = chain[chain.length - 1]; // previous vertex in chain
|
const prev = chain[chain.length - 1] ? chain[chain.length - 1][0] : -1; // previous vertex in chain
|
||||||
chain.push(current); // add current vertex to sequence
|
chain.push([current, religion, land]); // add current vertex to sequence
|
||||||
const c = vertices.c[current]; // cells adjacent to vertex
|
const c = vertices.c[current]; // cells adjacent to vertex
|
||||||
c.filter(c => cells.religion[c] === t).forEach(c => used[c] = 1);
|
c.filter(c => cells.religion[c] === t).forEach(c => used[c] = 1);
|
||||||
const c0 = c[0] >= n || cells.religion[c[0]] !== t;
|
const c0 = c[0] >= n || cells.religion[c[0]] !== t;
|
||||||
const c1 = c[1] >= n || cells.religion[c[1]] !== t;
|
const c1 = c[1] >= n || cells.religion[c[1]] !== t;
|
||||||
const c2 = c[2] >= n || cells.religion[c[2]] !== t;
|
const c2 = c[2] >= n || cells.religion[c[2]] !== t;
|
||||||
const v = vertices.v[current]; // neighboring vertices
|
const v = vertices.v[current]; // neighboring vertices
|
||||||
if (v[0] !== prev && c0 !== c1) current = v[0];
|
if (v[0] !== prev && c0 !== c1) {current = v[0]; check(c0 ? c[0] : c[1]);} else
|
||||||
else if (v[1] !== prev && c1 !== c2) current = v[1];
|
if (v[1] !== prev && c1 !== c2) {current = v[1]; check(c1 ? c[1] : c[2]);} else
|
||||||
else if (v[2] !== prev && c0 !== c2) current = v[2];
|
if (v[2] !== prev && c0 !== c2) {current = v[2]; check(c2 ? c[2] : c[0]);}
|
||||||
if (current === chain[chain.length - 1]) {console.error("Next vertex is not found"); break;}
|
if (current === chain[chain.length - 1][0]) {console.error("Next vertex is not found"); break;}
|
||||||
|
|
||||||
}
|
}
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
|
|
@ -1176,4 +1179,4 @@ function getLayer(id) {
|
||||||
if (id === "toggleIcons") return $("#icons");
|
if (id === "toggleIcons") return $("#icons");
|
||||||
if (id === "toggleMarkers") return $("#markers");
|
if (id === "toggleMarkers") return $("#markers");
|
||||||
if (id === "toggleRulers") return $("#ruler");
|
if (id === "toggleRulers") return $("#ruler");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue