mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-17 09:41:24 +01:00
150 lines
4.2 KiB
JavaScript
150 lines
4.2 KiB
JavaScript
var _3dheightMapExponent = null;
|
|
var _3dmaxHeight = null;
|
|
var _3dcolorLookup = null;
|
|
|
|
function _2dto1d(source) {
|
|
var r = [];
|
|
|
|
var w = source[0].length;
|
|
var h = source.length;
|
|
|
|
var i=0;
|
|
for (var y=0; y < h; y++) {
|
|
for (var x=0; x < w; x++) {
|
|
r[i] = source[y][x];
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
function _1dto2d(source, w, h) {
|
|
|
|
var r = [];
|
|
|
|
var i=0;
|
|
for (var y=0; y < h; y++) {
|
|
r[y] = [];
|
|
for (var x=0; x < w; x++) {
|
|
r[y][x] = source[i];
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
function getSVGImage(type, width, height) {
|
|
// clone svg
|
|
const cloneEl = document.getElementById("map").cloneNode(true);
|
|
cloneEl.id = "fantasyMap";
|
|
document.getElementsByTagName("body")[0].appendChild(cloneEl);
|
|
const clone = d3.select("#fantasyMap");
|
|
|
|
if (type === "svg") {
|
|
clone.select("#viewbox").attr("transform", null); // reset transform to show whole map
|
|
}
|
|
|
|
clone.attr("width", width).attr("height", height);
|
|
|
|
// remove unused elements
|
|
if (!clone.select("#terrain").selectAll("use").size()) clone.select("#defs-relief").remove();
|
|
if (!clone.select("#prec").selectAll("circle").size()) clone.select("#prec").remove();
|
|
if (!clone.select("#scaleBar").selectAll("use").size()) clone.select("#scaleBar").remove();
|
|
|
|
// default to water - on Firefox, ocean pattern appears as alternating blocks of ocean and water pattern
|
|
const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
|
if (isFirefox) {
|
|
if (!clone.select("#oceanPattern").selectAll("use").size()) clone.select("#oceanPattern").remove();
|
|
}
|
|
|
|
const removeEmptyGroups = function() {
|
|
let empty = 0;
|
|
clone.selectAll("g").each(function() {
|
|
if (!this.hasChildNodes() || this.style.display === "none") {empty++; this.remove();}
|
|
if (this.hasAttribute("display") && this.style.display === "inline") this.removeAttribute("display");
|
|
});
|
|
return empty;
|
|
}
|
|
while(removeEmptyGroups()) {removeEmptyGroups();}
|
|
|
|
// for each g element get inline style
|
|
const emptyG = clone.append("g").node();
|
|
const defaultStyles = window.getComputedStyle(emptyG);
|
|
clone.selectAll("g, #ruler > g > *, #scaleBar > text").each(function(d) {
|
|
const compStyle = window.getComputedStyle(this);
|
|
let style = "";
|
|
for (let i=0; i < compStyle.length; i++) {
|
|
const key = compStyle[i];
|
|
const value = compStyle.getPropertyValue(key);
|
|
// Firefox mask hack
|
|
if (key === "mask-image" && value !== defaultStyles.getPropertyValue(key)) {
|
|
style += "mask-image: url('#land');";
|
|
continue;
|
|
}
|
|
if (key === "cursor") continue; // cursor should be default
|
|
if (this.hasAttribute(key)) continue; // don't add style if there is the same attribute
|
|
if (value === defaultStyles.getPropertyValue(key)) continue;
|
|
style += key + ':' + value + ';';
|
|
}
|
|
if (style != "") this.setAttribute('style', style);
|
|
});
|
|
emptyG.remove();
|
|
|
|
// load fonts as dataURI so they will be available in downloaded svg/png
|
|
const svg_xml = (new XMLSerializer()).serializeToString(clone.node());
|
|
clone.remove();
|
|
const blob = new Blob([svg_xml], {type: 'image/svg+xml;charset=utf-8'});
|
|
const url = window.URL.createObjectURL(blob);
|
|
return url;
|
|
}
|
|
|
|
function getHeightmap() {
|
|
var mh = 0;
|
|
grid.cells.h.forEach((height, i) => {
|
|
h = grid.cells.h[i];
|
|
|
|
if (h > mh) mh = h;
|
|
});
|
|
if (mh > 82) { mh = 82; }
|
|
|
|
_3dheightMapExponent = heightExponentInput.value;
|
|
// _3dmaxHeight = Math.pow(mh, _3dheightMapExponent);
|
|
_3dmaxHeight = Math.pow(82, _3dheightMapExponent);
|
|
|
|
var heightMap = [];
|
|
for (var y=0; y < grid.cellsY; y++) {
|
|
heightMap[y] = [];
|
|
}
|
|
|
|
var y = 0, x = 0;
|
|
|
|
// convert height from map heights to a linear height
|
|
grid.cells.h.forEach((height, i) => {
|
|
h = grid.cells.h[i];
|
|
|
|
// add heightmap exponent
|
|
if (h >= 20) height = Math.pow(h - 18, _3dheightMapExponent);
|
|
// else if (h > 0) height = (h - 20) / h * 50;
|
|
else height = 0;
|
|
|
|
// get heightmap as a percentage
|
|
let v = (height / _3dmaxHeight);
|
|
|
|
// convert to 0-255
|
|
v = (v * 255);
|
|
|
|
heightMap[y][x] = Math.floor(v);
|
|
x++;
|
|
if (x >= grid.cellsX) { x = 0; y++ }
|
|
});
|
|
|
|
var hm = _2dto1d(heightMap);
|
|
|
|
return hm;
|
|
}
|
|
|
|
function getPreviewTexture(width, height) {
|
|
return getSVGImage("svg", width, height);
|
|
}
|