mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
v. 0.58.02b
This commit is contained in:
parent
93cadafa27
commit
22fd48eabd
3 changed files with 145 additions and 117 deletions
|
|
@ -59,8 +59,7 @@ button, select, a {
|
||||||
}
|
}
|
||||||
|
|
||||||
#landmass {
|
#landmass {
|
||||||
fill-rule: evenodd;
|
mask: url(#shape);
|
||||||
stroke: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#lakes,
|
#lakes,
|
||||||
|
|
|
||||||
116
index.html
116
index.html
|
|
@ -13,11 +13,11 @@
|
||||||
<title>Azgaar's Fantasy Map Generator</title>
|
<title>Azgaar's Fantasy Map Generator</title>
|
||||||
<meta name="application-name" content="Azgaar's Fantasy Map Generator">
|
<meta name="application-name" content="Azgaar's Fantasy Map Generator">
|
||||||
<meta name="author" content="Azgaar (Max Ganiev)">
|
<meta name="author" content="Azgaar (Max Ganiev)">
|
||||||
<meta name="description" content="Azgaar's Fantasy Map Generator (demo). Based on D3 Voronoi diagram rendered to svg">
|
<meta name="description" content="Azgaar's Fantasy Map Generator and Editor">
|
||||||
<meta name="google" content="notranslate">
|
<meta name="google" content="notranslate">
|
||||||
<meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator/">
|
<meta property="og:url" content="https://azgaar.github.io/Fantasy-Map-Generator/">
|
||||||
<meta property="og:title" content="Azgaar's Fantasy Map Generator">
|
<meta property="og:title" content="Azgaar's Fantasy Map Generator">
|
||||||
<meta property="og:description" content="Demo version. Based on D3 Voronoi diagram rendered to svg">
|
<meta property="og:description" content="Based on Voronoi diagram rendered to svg">
|
||||||
<meta property="og:image" content="images/preview.png">
|
<meta property="og:image" content="images/preview.png">
|
||||||
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/>
|
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32"/>
|
||||||
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/>
|
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16"/>
|
||||||
|
|
@ -31,64 +31,66 @@
|
||||||
<script src="libs/quantize.min.js" defer></script>
|
<script src="libs/quantize.min.js" defer></script>
|
||||||
<script src="libs/d3-hexbin.v0.2.min.js" defer></script>
|
<script src="libs/d3-hexbin.v0.2.min.js" defer></script>
|
||||||
<script src="libs/jquery.ui.touch-punch.min.js" defer></script>
|
<script src="libs/jquery.ui.touch-punch.min.js" defer></script>
|
||||||
<link rel="stylesheet" type="text/css" href="index.css?version=0.58.00b"/>
|
<link rel="stylesheet" type="text/css" href="index.css?version=0.58.02b"/>
|
||||||
<link rel="stylesheet" type="text/css" href="icons.css?version=0.58.00b"/>
|
<link rel="stylesheet" type="text/css" href="icons.css?version=0.58.02b"/>
|
||||||
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
|
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%">
|
||||||
<defs>
|
<defs>
|
||||||
<filter id="blurFilter" x="-1" y="-1" width="100" height="100">
|
<g id="filters">
|
||||||
<feGaussianBlur in="SourceGraphic" stdDeviation="0.2"/>
|
<filter id="blurFilter" x="-1" y="-1" width="100" height="100">
|
||||||
</filter>
|
<feGaussianBlur in="SourceGraphic" stdDeviation="0.2"/>
|
||||||
<filter id="blur1" x="-1" y="-1" width="100" height="100">
|
</filter>
|
||||||
<feGaussianBlur in="SourceGraphic" stdDeviation="1"/>
|
<filter id="blur1" x="-1" y="-1" width="100" height="100">
|
||||||
</filter>
|
<feGaussianBlur in="SourceGraphic" stdDeviation="1"/>
|
||||||
<filter id="blur5" x="-1" y="-1" width="100" height="100">
|
</filter>
|
||||||
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
|
<filter id="blur5" x="-1" y="-1" width="100" height="100">
|
||||||
</filter>
|
<feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
|
||||||
<filter id="blur10" x="-1" y="-1" width="100" height="100">
|
</filter>
|
||||||
<feGaussianBlur in="SourceGraphic" stdDeviation="10"/>
|
<filter id="blur10" x="-1" y="-1" width="100" height="100">
|
||||||
</filter>
|
<feGaussianBlur in="SourceGraphic" stdDeviation="10"/>
|
||||||
<filter id="splotch">
|
</filter>
|
||||||
<feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="4"/>
|
<filter id="splotch">
|
||||||
<feColorMatrix values="0 0 0 0 0, 0 0 0 0 0, 0 0 0 0 0, 0 0 0 -0.9 1.2" result="texture"/>
|
<feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="4"/>
|
||||||
<feComposite in="SourceGraphic" in2="texture" operator="in"/>
|
<feColorMatrix values="0 0 0 0 0, 0 0 0 0 0, 0 0 0 0 0, 0 0 0 -0.9 1.2" result="texture"/>
|
||||||
</filter>
|
<feComposite in="SourceGraphic" in2="texture" operator="in"/>
|
||||||
<filter id="bluredSplotch">
|
</filter>
|
||||||
<feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="4"/>
|
<filter id="bluredSplotch">
|
||||||
<feColorMatrix values="0 0 0 0 0, 0 0 0 0 0, 0 0 0 0 0, 0 0 0 -0.9 1.2" result="texture"/>
|
<feTurbulence type="fractalNoise" baseFrequency=".01" numOctaves="4"/>
|
||||||
<feComposite in="SourceGraphic" in2="texture" operator="in"/>
|
<feColorMatrix values="0 0 0 0 0, 0 0 0 0 0, 0 0 0 0 0, 0 0 0 -0.9 1.2" result="texture"/>
|
||||||
<feGaussianBlur stdDeviation="4"/>
|
<feComposite in="SourceGraphic" in2="texture" operator="in"/>
|
||||||
</filter>
|
<feGaussianBlur stdDeviation="4"/>
|
||||||
<filter id="dropShadow">
|
</filter>
|
||||||
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
|
<filter id="dropShadow">
|
||||||
<feOffset dx="1" dy="2"/>
|
<feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
|
||||||
<feMerge>
|
<feOffset dx="1" dy="2"/>
|
||||||
<feMergeNode/>
|
<feMerge>
|
||||||
<feMergeNode in="SourceGraphic"/>
|
<feMergeNode/>
|
||||||
</feMerge>
|
<feMergeNode in="SourceGraphic"/>
|
||||||
</filter>
|
</feMerge>
|
||||||
<filter id="pencil">
|
</filter>
|
||||||
<feTurbulence baseFrequency="0.03" numOctaves="6" type="fractalNoise"/>
|
<filter id="pencil">
|
||||||
<feDisplacementMap scale="3" in="SourceGraphic" xChannelSelector="R" yChannelSelector="G"/>
|
<feTurbulence baseFrequency="0.03" numOctaves="6" type="fractalNoise"/>
|
||||||
</filter>
|
<feDisplacementMap scale="3" in="SourceGraphic" xChannelSelector="R" yChannelSelector="G"/>
|
||||||
<filter id="turbulence">
|
</filter>
|
||||||
<feTurbulence baseFrequency="0.1" numOctaves="3" type="fractalNoise"/>
|
<filter id="turbulence">
|
||||||
<feDisplacementMap scale="10" in="SourceGraphic" xChannelSelector="R" yChannelSelector="G"/>
|
<feTurbulence baseFrequency="0.1" numOctaves="3" type="fractalNoise"/>
|
||||||
</filter>
|
<feDisplacementMap scale="10" in="SourceGraphic" xChannelSelector="R" yChannelSelector="G"/>
|
||||||
<filter id="filter-grayscale">
|
</filter>
|
||||||
<feColorMatrix values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>
|
<filter id="filter-grayscale">
|
||||||
</filter>
|
<feColorMatrix values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"/>
|
||||||
<filter id="filter-sepia">
|
</filter>
|
||||||
<feColorMatrix values="0.393 0.769 0.189 0 0 0.349 0.686 0.168 0 0 0.272 0.534 0.131 0 0 0 0 0 1 0"/>
|
<filter id="filter-sepia">
|
||||||
</filter>
|
<feColorMatrix values="0.393 0.769 0.189 0 0 0.349 0.686 0.168 0 0 0.272 0.534 0.131 0 0 0 0 0 1 0"/>
|
||||||
<filter id="filter-dingy">
|
</filter>
|
||||||
<feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0.3 0.3 0 0 0 0 0 1 0"/>
|
<filter id="filter-dingy">
|
||||||
</filter>
|
<feColorMatrix values="1 0 0 0 0 0 1 0 0 0 0 0.3 0.3 0 0 0 0 0 1 0"/>
|
||||||
<filter id="filter-tint">
|
</filter>
|
||||||
<feColorMatrix values="1.1 0 0 0 0 0 1.1 0 0 0 0 0 0.9 0 0 0 0 0 1 0"/>
|
<filter id="filter-tint">
|
||||||
</filter>
|
<feColorMatrix values="1.1 0 0 0 0 0 1.1 0 0 0 0 0 0.9 0 0 0 0 0 1 0"/>
|
||||||
|
</filter>
|
||||||
|
</g>
|
||||||
<g id="deftemp">
|
<g id="deftemp">
|
||||||
<mask id="shape" x="0" y="0" width="100%" height="100%" fill="black"></mask>
|
<mask id="shape" x="0" y="0" width="100%" height="100%" fill="black"></mask>
|
||||||
</g>
|
</g>
|
||||||
|
|
@ -534,6 +536,7 @@
|
||||||
<div>
|
<div>
|
||||||
Coord: <span id="infoX">0</span>/<span id="infoY">0</span><br>
|
Coord: <span id="infoX">0</span>/<span id="infoY">0</span><br>
|
||||||
Cell: <span id="infoCell">0</span><br>
|
Cell: <span id="infoCell">0</span><br>
|
||||||
|
Area: <span id="infoArea">0</span><br>
|
||||||
Height: <span id="infoHeight">0</span><br>
|
Height: <span id="infoHeight">0</span><br>
|
||||||
Flux: <span id="infoFlux">0</span>
|
Flux: <span id="infoFlux">0</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -541,6 +544,7 @@
|
||||||
Type: <span id="infoFeature">n/a</span><br>
|
Type: <span id="infoFeature">n/a</span><br>
|
||||||
Country: <span id="infoCountry">n/a</span><br>
|
Country: <span id="infoCountry">n/a</span><br>
|
||||||
Culture: <span id="infoCulture">n/a</span><br>
|
Culture: <span id="infoCulture">n/a</span><br>
|
||||||
|
Population: <span id="infoPopulation">0</span><br>
|
||||||
Burg: <span id="infoBurg">n/a</span>
|
Burg: <span id="infoBurg">n/a</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1107,5 +1111,5 @@
|
||||||
<input type="file" accept=".txt" id="namesbaseToLoad">
|
<input type="file" accept=".txt" id="namesbaseToLoad">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="script.js?version=0.58.00b"></script>
|
<script src="script.js?version=0.58.02b"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
143
script.js
143
script.js
|
|
@ -3,7 +3,7 @@
|
||||||
fantasyMap();
|
fantasyMap();
|
||||||
function fantasyMap() {
|
function fantasyMap() {
|
||||||
// Version control
|
// Version control
|
||||||
var version = "0.58b";
|
const version = "0.58b";
|
||||||
document.title += " v. " + version;
|
document.title += " v. " + version;
|
||||||
|
|
||||||
// Declare variables
|
// Declare variables
|
||||||
|
|
@ -11,11 +11,11 @@ function fantasyMap() {
|
||||||
defs = svg.select("#deftemp"),
|
defs = svg.select("#deftemp"),
|
||||||
viewbox = svg.append("g").attr("id", "viewbox"),
|
viewbox = svg.append("g").attr("id", "viewbox"),
|
||||||
ocean = viewbox.append("g").attr("id", "ocean"),
|
ocean = viewbox.append("g").attr("id", "ocean"),
|
||||||
|
lakes = viewbox.append("g").attr("id", "lakes"),
|
||||||
oceanLayers = ocean.append("g").attr("id", "oceanLayers"),
|
oceanLayers = ocean.append("g").attr("id", "oceanLayers"),
|
||||||
oceanPattern = ocean.append("g").attr("id", "oceanPattern"),
|
oceanPattern = ocean.append("g").attr("id", "oceanPattern"),
|
||||||
landmass = viewbox.append("g").attr("id", "landmass"),
|
landmass = viewbox.append("g").attr("id", "landmass"),
|
||||||
terrs = viewbox.append("g").attr("id", "terrs"),
|
terrs = viewbox.append("g").attr("id", "terrs"),
|
||||||
lakes = viewbox.append("g").attr("id", "lakes"),
|
|
||||||
grid = viewbox.append("g").attr("id", "grid"),
|
grid = viewbox.append("g").attr("id", "grid"),
|
||||||
overlay = viewbox.append("g").attr("id", "overlay"),
|
overlay = viewbox.append("g").attr("id", "overlay"),
|
||||||
routes = viewbox.append("g").attr("id", "routes"),
|
routes = viewbox.append("g").attr("id", "routes"),
|
||||||
|
|
@ -414,14 +414,19 @@ function fantasyMap() {
|
||||||
infoX.innerHTML = rn(point[0]);
|
infoX.innerHTML = rn(point[0]);
|
||||||
infoY.innerHTML = rn(point[1]);
|
infoY.innerHTML = rn(point[1]);
|
||||||
infoCell.innerHTML = i;
|
infoCell.innerHTML = i;
|
||||||
|
infoArea.innerHTML = ifDefined(p.area, "n/a", 2);
|
||||||
infoHeight.innerHTML = ifDefined(p.height, "n/a", 2);
|
infoHeight.innerHTML = ifDefined(p.height, "n/a", 2);
|
||||||
infoFlux.innerHTML = ifDefined(p.flux, "n/a", 2);
|
infoFlux.innerHTML = ifDefined(p.flux, "n/a", 2);
|
||||||
infoFeature.innerHTML = ifDefined(p.f) + "" + ifDefined(p.fn);
|
|
||||||
let country = p.region === undefined ? "n/a" : p.region === "neutral" ? "neutral" : states[p.region].name + " (" + p.region + ")";
|
let country = p.region === undefined ? "n/a" : p.region === "neutral" ? "neutral" : states[p.region].name + " (" + p.region + ")";
|
||||||
infoCountry.innerHTML = country;
|
infoCountry.innerHTML = country;
|
||||||
let culture = ifDefined(p.culture) !== "no" ? cultures[p.culture].name + " (" + p.culture + ")" : "n/a";
|
let culture = ifDefined(p.culture) !== "no" ? cultures[p.culture].name + " (" + p.culture + ")" : "n/a";
|
||||||
infoCulture.innerHTML = culture;
|
infoCulture.innerHTML = culture;
|
||||||
|
infoPopulation.innerHTML = ifDefined(p.pop, "n/a", 2);
|
||||||
infoBurg.innerHTML = ifDefined(p.manor) !== "no" ? manors[p.manor].name + " (" + p.manor + ")" : "no";
|
infoBurg.innerHTML = ifDefined(p.manor) !== "no" ? manors[p.manor].name + " (" + p.manor + ")" : "no";
|
||||||
|
const feature = features[p.fn];
|
||||||
|
if (feature === undefined) return;
|
||||||
|
const fType = feature.land ? "Island" : feature.border ? "Ocean" : "Lake";
|
||||||
|
infoFeature.innerHTML = fType + " (" + p.fn + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// update tooltip
|
// update tooltip
|
||||||
|
|
@ -474,8 +479,8 @@ function fantasyMap() {
|
||||||
// return value (v) if defined with specified number of decimals (d)
|
// return value (v) if defined with specified number of decimals (d)
|
||||||
// else return "no" or attribute (r)
|
// else return "no" or attribute (r)
|
||||||
function ifDefined(v, r, d) {
|
function ifDefined(v, r, d) {
|
||||||
if (v == undefined) {return r || "no";}
|
if (v === undefined) return r || "no";
|
||||||
if (d) {return v.toFixed(d);}
|
if (d) return v.toFixed(d);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1264,7 +1269,6 @@ function fantasyMap() {
|
||||||
calculateVoronoi(newPoints); // recalculate Voronoi diagram using new points
|
calculateVoronoi(newPoints); // recalculate Voronoi diagram using new points
|
||||||
let gridPath = ""; // store grid as huge single path string
|
let gridPath = ""; // store grid as huge single path string
|
||||||
cells.map(function(i, d) {
|
cells.map(function(i, d) {
|
||||||
if (!polygons[d]) debugger;
|
|
||||||
if (i.height >= 0.2) {
|
if (i.height >= 0.2) {
|
||||||
// calc cell area
|
// calc cell area
|
||||||
i.area = rn(Math.abs(d3.polygonArea(polygons[d])), 2);
|
i.area = rn(Math.abs(d3.polygonArea(polygons[d])), 2);
|
||||||
|
|
@ -1408,14 +1412,14 @@ function fantasyMap() {
|
||||||
// Detect and draw the coasline
|
// Detect and draw the coasline
|
||||||
function drawCoastline() {
|
function drawCoastline() {
|
||||||
console.time('drawCoastline');
|
console.time('drawCoastline');
|
||||||
var oceanCoastline = "", lakeCoastline = "";
|
const shape = d3.select("#shape");
|
||||||
$("#landmass").empty();
|
$("#landmass").empty();
|
||||||
let minX = graphWidth, maxX = 0; // extreme points
|
let minX = graphWidth, maxX = 0; // extreme points
|
||||||
let minXedge, maxXedge; // extreme edges
|
let minXedge, maxXedge; // extreme edges
|
||||||
for (let f = 0; f < features.length; f++) {
|
for (let f = 0; f < features.length; f++) {
|
||||||
if (!features[f].land) continue;
|
if (!features[f].land) continue;
|
||||||
const coastal = $.grep(land, function(e) {return ((e.ctype === 1 || e.ctype === 99) && e.fn === f);});
|
const coastal = $.grep(land, function(e) {return ((e.ctype === 1 || e.ctype === 99) && e.fn === f);});
|
||||||
const oceanEdges = [], lakeEdges = [];
|
let oceanEdges = [], lakeEdges = [];
|
||||||
for (let i = 0; i < coastal.length; i++) {
|
for (let i = 0; i < coastal.length; i++) {
|
||||||
const id = coastal[i].index, cell = diagram.cells[id];
|
const id = coastal[i].index, cell = diagram.cells[id];
|
||||||
cell.halfedges.forEach(function(e) {
|
cell.halfedges.forEach(function(e) {
|
||||||
|
|
@ -1425,15 +1429,15 @@ function fantasyMap() {
|
||||||
if (edge.left && edge.right) {
|
if (edge.left && edge.right) {
|
||||||
const ea = edge.left.index === id ? edge.right.index : edge.left.index;
|
const ea = edge.left.index === id ? edge.right.index : edge.left.index;
|
||||||
if (cells[ea].height < 0.2) {
|
if (cells[ea].height < 0.2) {
|
||||||
if (!features[cells[ea].fn].border) {
|
if (features[cells[ea].fn].border) {
|
||||||
lakeEdges.push({start, end});
|
|
||||||
} else {
|
|
||||||
oceanEdges.push({start, end});
|
oceanEdges.push({start, end});
|
||||||
// island extreme points
|
// island extreme points
|
||||||
if (edge[0][0] < minX) {minX = edge[0][0]; minXedge = edge[0]}
|
if (edge[0][0] < minX) {minX = edge[0][0]; minXedge = edge[0]}
|
||||||
if (edge[1][0] < minX) {minX = edge[1][0]; minXedge = edge[1]}
|
if (edge[1][0] < minX) {minX = edge[1][0]; minXedge = edge[1]}
|
||||||
if (edge[0][0] > maxX) {maxX = edge[0][0]; maxXedge = edge[0]}
|
if (edge[0][0] > maxX) {maxX = edge[0][0]; maxXedge = edge[0]}
|
||||||
if (edge[1][0] > maxX) {maxX = edge[1][0]; maxXedge = edge[1]}
|
if (edge[1][0] > maxX) {maxX = edge[1][0]; maxXedge = edge[1]}
|
||||||
|
} else {
|
||||||
|
lakeEdges.push({start, end});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1441,17 +1445,21 @@ function fantasyMap() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (coastal.length && lakeEdges.length && oceanEdges.length < 3) {
|
||||||
|
console.error("Feature " + f + " is an on-lake island. This can cause defects!");
|
||||||
|
oceanEdges = lakeEdges;
|
||||||
|
lakeEdges = [];
|
||||||
|
}
|
||||||
lineGen.curve(d3.curveCatmullRomClosed.alpha(0.1));
|
lineGen.curve(d3.curveCatmullRomClosed.alpha(0.1));
|
||||||
oceanCoastline += getContinuousLine(oceanEdges, 3, 0);
|
const oceanCoastline = getContinuousLine(oceanEdges, 3, 0);
|
||||||
lineGen.curve(d3.curveBasisClosed);
|
lineGen.curve(d3.curveBasisClosed);
|
||||||
if (lakeEdges.length > 0) {lakeCoastline += getContinuousLine(lakeEdges, 1.5, 0);}
|
const lakeCoastline = getContinuousLine(lakeEdges, 1.5, 0);
|
||||||
|
shape.append("path").attr("d", oceanCoastline).attr("fill", "white");
|
||||||
|
if (lakeCoastline) shape.append("path").attr("d", lakeCoastline).attr("fill", "black");
|
||||||
|
coastline.append("path").attr("d", oceanCoastline); // draw the coastline
|
||||||
|
if (lakeCoastline) lakes.append("path").attr("d", lakeCoastline); // draw the lakes
|
||||||
}
|
}
|
||||||
const shape = d3.select("#shape");
|
landmass.append("rect").attr("x", 0).attr("y", 0).attr("width", graphWidth).attr("height", graphHeight); // draw the landmass
|
||||||
shape.append("path").attr("d", oceanCoastline).attr("fill", "white"); // add clippath
|
|
||||||
shape.append("path").attr("d", lakeCoastline).attr("fill", "black"); // add clippath
|
|
||||||
landmass.append("path").attr("d", oceanCoastline + lakeCoastline); // draw the landmass
|
|
||||||
coastline.append("path").attr("d", oceanCoastline); // draw the coastline
|
|
||||||
lakes.append("path").attr("d", lakeCoastline); // draw the lakes
|
|
||||||
drawDefaultRuler(minXedge, maxXedge);
|
drawDefaultRuler(minXedge, maxXedge);
|
||||||
console.timeEnd('drawCoastline');
|
console.timeEnd('drawCoastline');
|
||||||
}
|
}
|
||||||
|
|
@ -1658,6 +1666,7 @@ function fantasyMap() {
|
||||||
|
|
||||||
function getContinuousLine(edges, indention, relax) {
|
function getContinuousLine(edges, indention, relax) {
|
||||||
let line = "";
|
let line = "";
|
||||||
|
if (edges.length < 3) return "";
|
||||||
while (edges.length > 2) {
|
while (edges.length > 2) {
|
||||||
let edgesOrdered = []; // to store points in a correct order
|
let edgesOrdered = []; // to store points in a correct order
|
||||||
let start = edges[0].start;
|
let start = edges[0].start;
|
||||||
|
|
@ -1706,14 +1715,17 @@ function fantasyMap() {
|
||||||
|
|
||||||
// temporary elevate lakes to min neighbors heights to correctly flux the water
|
// temporary elevate lakes to min neighbors heights to correctly flux the water
|
||||||
function elevateLakes() {
|
function elevateLakes() {
|
||||||
for (let i=0; i < cells.length; i++) {
|
console.time('elevateLakes');
|
||||||
if (cells[i].height >= 0.2) continue;
|
const lakes = $.grep(cells, function(e) {return e.height < 0.2 && !features[e.fn].border;});
|
||||||
if (features[cells[i].fn].border) continue;
|
lakes.sort(function(a, b) {return b.height - a.height;});
|
||||||
const heights = cells[i].neighbors.map(function(n) {if (cells[n].height >= 0.2) return cells[n].height});
|
for (let i=0; i < lakes.length; i++) {
|
||||||
if (heights.length) cells[i].height = d3.mean(heights) - 0.02;
|
const heights = [];
|
||||||
if (cells[i].height < 0.2) cells[i].height = 0.2;
|
lakes[i].neighbors.forEach(function(n) {if (cells[n].height >= 0.2) heights.push(cells[n].height)});
|
||||||
cells[i].lake = true;
|
if (heights.length) lakes[i].height = d3.min(heights) - 0.01;
|
||||||
|
if (cells[i].height < 0.2) lakes[i].height = 0.2;
|
||||||
|
lakes[i].lake = true;
|
||||||
}
|
}
|
||||||
|
console.timeEnd('elevateLakes');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depression filling algorithm (for a correct water flux modeling; phase1)
|
// Depression filling algorithm (for a correct water flux modeling; phase1)
|
||||||
|
|
@ -1835,7 +1847,7 @@ function fantasyMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cells[min].flux += land[i].flux;
|
if (cells[min].flux) cells[min].flux += land[i].flux;
|
||||||
if (land[i].river !== undefined) {
|
if (land[i].river !== undefined) {
|
||||||
const px = cells[min].data[0];
|
const px = cells[min].data[0];
|
||||||
const py = cells[min].data[1];
|
const py = cells[min].data[1];
|
||||||
|
|
@ -2025,12 +2037,12 @@ function fantasyMap() {
|
||||||
}
|
}
|
||||||
if (land[i].lake === 2) {
|
if (land[i].lake === 2) {
|
||||||
if (land[i].river !== undefined) {
|
if (land[i].river !== undefined) {
|
||||||
addLakeAtCell(i);
|
addLakeAtCell(land[i].index);
|
||||||
} else {
|
} else {
|
||||||
//land[i].lake = undefined;
|
delete land[i].lake;
|
||||||
land[i].neighbors.forEach(function(n) {
|
land[i].neighbors.forEach(function(n) {
|
||||||
if (cells[n].river !== undefined) {
|
if (cells[n].river !== undefined) {
|
||||||
addLakeAtCell(i);
|
addLakeAtCell(n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -2039,18 +2051,18 @@ function fantasyMap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLakeAtCell(i) {
|
function addLakeAtCell(i) {
|
||||||
land[i].height = 0.19;
|
cells[i].lake = 2;
|
||||||
land[i].ctype = -1;
|
cells[i].height = 0.19;
|
||||||
|
cells[i].ctype = -1;
|
||||||
let fn = features.length;
|
let fn = features.length;
|
||||||
land[i].neighbors.forEach(function(e) {
|
cells[i].neighbors.forEach(function(e) {
|
||||||
if (cells[e].height >= 0.2) cells[e].ctype = 1;
|
if (cells[e].height >= 0.2) cells[e].ctype = 1;
|
||||||
// change fn to neighboring lake
|
// change fn to neighboring lake
|
||||||
if (cells[e].lake) fn = cells[e].fn;
|
if (cells[e].lake === 2 && cells[e].river !== undefined) fn = cells[e].fn;
|
||||||
|
else if (cells[e].lake === 1) fn = cells[e].fn;
|
||||||
});
|
});
|
||||||
land[i].fn = fn;
|
cells[i].fn = fn;
|
||||||
if (fn === features.length) {
|
if (fn === features.length) features.push({i: fn, land: false, border: false});
|
||||||
features.push({i: features.length, land: false, border: false});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
land = $.grep(cells, function(e) {return e.height >= 0.2;});
|
land = $.grep(cells, function(e) {return e.height >= 0.2;});
|
||||||
|
|
@ -3303,7 +3315,7 @@ function fantasyMap() {
|
||||||
// calculate population for manors, cells and states
|
// calculate population for manors, cells and states
|
||||||
function calculatePopulation() {
|
function calculatePopulation() {
|
||||||
// neutral population factors < 1 as neutral lands are usually pretty wild
|
// neutral population factors < 1 as neutral lands are usually pretty wild
|
||||||
var ruralFactor = 0.5, urbanFactor = 0.9;
|
const ruralFactor = 0.5, urbanFactor = 0.9;
|
||||||
|
|
||||||
// calculate population for each burg (based on trade/people attractors)
|
// calculate population for each burg (based on trade/people attractors)
|
||||||
manors.map(function(m) {
|
manors.map(function(m) {
|
||||||
|
|
@ -3986,7 +3998,6 @@ function fantasyMap() {
|
||||||
let dist = 100000, manor = null;
|
let dist = 100000, manor = null;
|
||||||
if (manors.length) {
|
if (manors.length) {
|
||||||
const c = manorTree.find(x, y);
|
const c = manorTree.find(x, y);
|
||||||
if (!c) debugger;
|
|
||||||
dist = Math.hypot(c[0] - x, c[1] - y);
|
dist = Math.hypot(c[0] - x, c[1] - y);
|
||||||
manor = getManorId(c);
|
manor = getManorId(c);
|
||||||
}
|
}
|
||||||
|
|
@ -4233,7 +4244,7 @@ function fantasyMap() {
|
||||||
console.time("recalculateCultures");
|
console.time("recalculateCultures");
|
||||||
// For each capital find closest culture and assign it to capital
|
// For each capital find closest culture and assign it to capital
|
||||||
states.forEach(function(s) {
|
states.forEach(function(s) {
|
||||||
if (s.capital === "neutral") return;
|
if (s.capital === "neutral" || s.capital === "select") return;
|
||||||
const capital = manors[s.capital];
|
const capital = manors[s.capital];
|
||||||
const c = cultureTree.find(capital.x, capital.y);
|
const c = cultureTree.find(capital.x, capital.y);
|
||||||
capital.culture = getCultureId(c);
|
capital.culture = getCultureId(c);
|
||||||
|
|
@ -4389,7 +4400,7 @@ function fantasyMap() {
|
||||||
delete c.coastY;
|
delete c.coastY;
|
||||||
if (c.ctype === undefined) {delete c.ctype;}
|
if (c.ctype === undefined) {delete c.ctype;}
|
||||||
c.height = rn(c.height, 2);
|
c.height = rn(c.height, 2);
|
||||||
c.flux = rn(c.flux, 2);
|
if (c.height >= 0.2) c.flux = rn(c.flux, 2);
|
||||||
});
|
});
|
||||||
// restore layers if they was turned on
|
// restore layers if they was turned on
|
||||||
if (!$("#toggleHeight").hasClass("buttonoff") && !terrs.selectAll("path").size()) toggleHeight();
|
if (!$("#toggleHeight").hasClass("buttonoff") && !terrs.selectAll("path").size()) toggleHeight();
|
||||||
|
|
@ -5715,6 +5726,20 @@ function fantasyMap() {
|
||||||
if(data[8]) nameBase = JSON.parse(data[8]);
|
if(data[8]) nameBase = JSON.parse(data[8]);
|
||||||
if(data[8]) nameBases = JSON.parse(data[9]);
|
if(data[8]) nameBases = JSON.parse(data[9]);
|
||||||
|
|
||||||
|
// calculate areas / population for old maps
|
||||||
|
const graphSizeAdj = 90 / Math.sqrt(cells.length, 2); // adjust to different graphSize
|
||||||
|
land.forEach(function(i) {
|
||||||
|
const p = i.index;
|
||||||
|
i.area = rn(Math.abs(d3.polygonArea(polygons[p])), 2);
|
||||||
|
if (i.pop === undefined) {
|
||||||
|
let population = 0;
|
||||||
|
const elevationFactor = Math.pow(1 - i.height, 3);
|
||||||
|
population = elevationFactor * i.area * graphSizeAdj;
|
||||||
|
if (i.region === "neutral") population *= 0.5;
|
||||||
|
i.pop = rn(population, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// restore Heightmap customization mode
|
// restore Heightmap customization mode
|
||||||
if (customization === 1) {
|
if (customization === 1) {
|
||||||
optionsTrigger.click();
|
optionsTrigger.click();
|
||||||
|
|
@ -5845,6 +5870,9 @@ function fantasyMap() {
|
||||||
case 83: // "S" to log states data
|
case 83: // "S" to log states data
|
||||||
console.table(states);
|
console.table(states);
|
||||||
break;
|
break;
|
||||||
|
case 70: // "F" to log features data
|
||||||
|
console.table(features);
|
||||||
|
break;
|
||||||
case 37: // Left to scroll map left
|
case 37: // Left to scroll map left
|
||||||
zoom.translateBy(svg, 10, 0);
|
zoom.translateBy(svg, 10, 0);
|
||||||
break;
|
break;
|
||||||
|
|
@ -5960,8 +5988,7 @@ function fantasyMap() {
|
||||||
$("#countriesManuallyButtons").show();
|
$("#countriesManuallyButtons").show();
|
||||||
// highlight capital cells as it's not allowed to change capital's state that way
|
// highlight capital cells as it's not allowed to change capital's state that way
|
||||||
states.map(function(s) {
|
states.map(function(s) {
|
||||||
if (s.color === "neutral") {return;}
|
if (s.capital === "neutral" || s.capital === "select") return;
|
||||||
if (s.capital === "select") {return;}
|
|
||||||
const capital = s.capital;
|
const capital = s.capital;
|
||||||
const index = manors[capital].cell;
|
const index = manors[capital].cell;
|
||||||
temp.append("path")
|
temp.append("path")
|
||||||
|
|
@ -6549,30 +6576,28 @@ function fantasyMap() {
|
||||||
|
|
||||||
function editHeightmap(type) {
|
function editHeightmap(type) {
|
||||||
closeDialogs();
|
closeDialogs();
|
||||||
var heights = [], regionData = [], cultureData = [];
|
const heights = [], regionData = [], cultureData = [];
|
||||||
for (var i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
var cell = diagram.find(points[i][0], points[i][1]).index;
|
const cell = diagram.find(points[i][0], points[i][1]).index;
|
||||||
heights.push(cells[cell].height);
|
heights.push(cells[cell].height);
|
||||||
var region = cells[cell].region;
|
let region = cells[cell].region;
|
||||||
if (region === undefined) {region = -1;}
|
if (region === undefined) region = -1;
|
||||||
regionData.push(region);
|
regionData.push(region);
|
||||||
var culture = cells[cell].culture;
|
let culture = cells[cell].culture;
|
||||||
if (culture === undefined) {culture = -1;}
|
if (culture === undefined) culture = -1;
|
||||||
cultureData.push(culture);
|
cultureData.push(culture);
|
||||||
}
|
}
|
||||||
if (type === "clean") {undraw();}
|
if (type === "clean") undraw();
|
||||||
calculateVoronoi(points);
|
calculateVoronoi(points);
|
||||||
detectNeighbors("grid");
|
detectNeighbors("grid");
|
||||||
drawScaleBar();
|
drawScaleBar();
|
||||||
for (var i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {cells[i].height = heights[i];}
|
||||||
cells[i].height = heights[i];
|
|
||||||
}
|
|
||||||
if (type === "keep") {
|
if (type === "keep") {
|
||||||
svg.selectAll("#shape, #lakes, #coastline, #terrain, #rivers, #grid, #terrs, #landmass, #ocean, #regions")
|
svg.selectAll("#shape, #lakes, #coastline, #terrain, #rivers, #grid, #terrs, #landmass, #ocean, #regions")
|
||||||
.selectAll("path, circle, line").remove();
|
.selectAll("path, circle, line").remove();
|
||||||
for (var i = 0; i < points.length; i++) {
|
for (let i = 0; i < points.length; i++) {
|
||||||
if (regionData[i] !== -1) {cells[i].region = regionData[i];}
|
if (regionData[i] !== -1) cells[i].region = regionData[i];
|
||||||
if (cultureData[i] !== -1) {cells[i].culture = cultureData[i];}
|
if (cultureData[i] !== -1) cells[i].culture = cultureData[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mockHeightmap();
|
mockHeightmap();
|
||||||
|
|
@ -8468,7 +8493,7 @@ function fantasyMap() {
|
||||||
neutralBorders.attr("opacity", .8).attr("stroke", "#56566d").attr("stroke-width", .3).attr("stroke-dasharray", "1 1.5").attr("stroke-linecap", "butt");
|
neutralBorders.attr("opacity", .8).attr("stroke", "#56566d").attr("stroke-width", .3).attr("stroke-dasharray", "1 1.5").attr("stroke-linecap", "butt");
|
||||||
cults.attr("opacity", .6);
|
cults.attr("opacity", .6);
|
||||||
rivers.attr("opacity", 1).attr("fill", "#5d97bb");
|
rivers.attr("opacity", 1).attr("fill", "#5d97bb");
|
||||||
lakes.attr("opacity", .5).attr("fill", "#a6c1fd").attr("stroke", "#5f799d").attr("stroke-width", .25);
|
lakes.attr("opacity", .5).attr("fill", "#a6c1fd").attr("stroke", "#5f799d").attr("stroke-width", .7);
|
||||||
icons.selectAll("g").attr("opacity", 1).attr("fill", "#ffffff").attr("stroke", "#3e3e4b");
|
icons.selectAll("g").attr("opacity", 1).attr("fill", "#ffffff").attr("stroke", "#3e3e4b");
|
||||||
roads.attr("opacity", .9).attr("stroke", "#d06324").attr("stroke-width", .35).attr("stroke-dasharray", "1.5").attr("stroke-linecap", "butt");
|
roads.attr("opacity", .9).attr("stroke", "#d06324").attr("stroke-width", .35).attr("stroke-dasharray", "1.5").attr("stroke-linecap", "butt");
|
||||||
trails.attr("opacity", .9).attr("stroke", "#d06324").attr("stroke-width", .15).attr("stroke-dasharray", ".8 1.6").attr("stroke-linecap", "butt");
|
trails.attr("opacity", .9).attr("stroke", "#d06324").attr("stroke-width", .15).attr("stroke-dasharray", ".8 1.6").attr("stroke-linecap", "butt");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue