mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-22 20:11:24 +01:00
The coefficients have been changed so that the sign of the latitude does not affect the result
220 lines
No EOL
9.7 KiB
JavaScript
220 lines
No EOL
9.7 KiB
JavaScript
"use strict";
|
|
|
|
function showTGForBurg(id) {
|
|
const b = pack.burgs[id];
|
|
const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
|
|
const temperature = grid.cells.temp[pack.cells.g[b.cell]];
|
|
const prec = grid.cells.prec[pack.cells.g[b.cell]];
|
|
|
|
const weights = [
|
|
[//Layer0
|
|
//IN0 IN1
|
|
[10.782752257744338, 2.7100404240962126],
|
|
[-2.8226802110591462, 51.62920138583541],
|
|
[-6.6250956268643835, 4.427939197315455],
|
|
[-59.64690518541339, 41.89084162654791],
|
|
[-1.3302059550553835, -3.6964487738450913],
|
|
[-2.5844898544535497, 0.09879268612455298],
|
|
[-5.58528252533573, -0.23426224364501905],
|
|
[26.94531337690372, 20.898158905988907],
|
|
[3.816397481634785, -0.19045424064580757],
|
|
[-4.835697931609101, -10.748232783636434]
|
|
],
|
|
[//Layer1
|
|
[-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
|
|
[-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
|
|
[-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
|
|
[20.706518520569514, 18.344297403881875, 99.52244671131733, -58.53124969563653, -60.74384321042212, -80.57540534651835, 7.884792406540866, -144.33871131678563, 80.134199744324, 20.50745285622448],
|
|
[-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
|
|
[-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
|
|
],
|
|
[//Layer2
|
|
[-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
|
|
[-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
|
|
[1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
|
|
]
|
|
];
|
|
//From (-∞,∞) to ~[-1,1]
|
|
const In1 = [(Math.abs(lat) - 26.950680212887473)/48.378128506956,(prec - 12.229929140832644)/29.94402033696607];
|
|
|
|
let lastIn = In1;
|
|
let lstOut = [];
|
|
for (let levelN = 0; levelN < weights.length ; levelN++) {
|
|
let layerN = weights[levelN];
|
|
for (let i = 0; i < layerN.length ; i++) {
|
|
lstOut[i] = 0;
|
|
for (let j = 0; j < layerN[i].length ; j++)
|
|
lstOut[i] = lstOut[i] + lastIn[j]*layerN[i][j] ;
|
|
//Sigmoid
|
|
lstOut[i] = 1/(1+Math.exp(-lstOut[i]));
|
|
}
|
|
lastIn = lstOut.slice(0);
|
|
}
|
|
|
|
//From [0,1] to [min,max]
|
|
//Standard deviation for average temperature for the year
|
|
const yearSig = lstOut[0]*62.9466411977018+0.28613807855649165;
|
|
//Standard deviation for the difference between the minimum and maximum temperatures for the year
|
|
const yearDelTmpSig = (lstOut[1]*13.541688670361175+0.1414213562373084) > yearSig ? yearSig : (lstOut[1]*13.541688670361175+0.1414213562373084);
|
|
//Expected value for the difference between the minimum and maximum temperatures for the year
|
|
const yearDelTmpMu = lstOut[2]*15.266666666666667+0.6416666666666663;
|
|
|
|
//Temperature change shape
|
|
//const formTmp = -Math.cos(data*2*Math.PI) / 2;
|
|
const delT = yearDelTmpMu/2+0.5*yearDelTmpSig/2;
|
|
const minT = temperature - ((yearSig+delT) > 15 ? (yearSig+delT) : 15);
|
|
const maxT = temperature + (temperature - minT);
|
|
|
|
const chartWidth = window.innerWidth/2,
|
|
chartHeight = 300; // height of our land/sea profile, excluding the biomes data below
|
|
const xOffset = 80,
|
|
yOffset = 10; // this is our drawing starting point from top-left (y = 0) of SVG
|
|
|
|
const xscale = d3.scaleLinear().domain([0,360]).range([0, chartWidth]);
|
|
const xscale_inv = d3.scaleLinear().domain([0, chartWidth]).range([0,360]);
|
|
const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
|
|
const yscale_inv = d3.scaleLinear().domain([chartHeight, 0]).range([minT, maxT]);
|
|
|
|
const dataAverTmp = [];
|
|
const dataMinTmp = [];
|
|
const dataMaxTmp = [];
|
|
for (let i = 0; i < 360 ; i++) {
|
|
let formTmp = Math.cos(i/360*2*Math.PI) / 2;
|
|
if(lat > 0) formTmp = -formTmp;
|
|
const averT = formTmp * yearSig + temperature;
|
|
const delT = yearDelTmpMu/2+formTmp*yearDelTmpSig/2;
|
|
dataAverTmp.push({x:xscale(i) + xOffset,y:yscale(averT) + yOffset});
|
|
dataMinTmp.push({x:xscale(i) + xOffset,y:yscale(averT-delT) + yOffset});
|
|
dataMaxTmp.push({x:xscale(i) + xOffset,y:yscale(averT+delT) + yOffset});
|
|
}
|
|
|
|
document.getElementById("epControls").style.visibility = "hidden";
|
|
|
|
$("#elevationProfile").dialog({
|
|
title: "Seasonal temperature schedule",
|
|
resizable: false,
|
|
width: window.width,
|
|
close: closeTGForBurg,
|
|
position: {my: "left top", at: "left+20 bottom-500", of: window, collision: "fit"}
|
|
});
|
|
|
|
draw();
|
|
|
|
function draw() {
|
|
|
|
document.getElementById("elevationGraph").innerHTML = "";
|
|
const legendSize = 60;
|
|
const chart = d3
|
|
.select("#elevationGraph")
|
|
.append("svg")
|
|
.attr("width", chartWidth + 120)
|
|
.attr("height", chartHeight + yOffset + legendSize)
|
|
.attr("id", "elevationSVG")
|
|
.attr("class", "epbackground");
|
|
// arrow-head definition
|
|
chart.append("defs").append("marker").attr("id", "arrowhead").attr("orient", "auto").attr("markerWidth", "2").attr("markerHeight", "4").attr("refX", "0.1").attr("refY", "2");
|
|
|
|
let Gen = d3.line().curve(d3.curveBasis).x((p) => p.x).y((p) => p.y);
|
|
|
|
//print graphs
|
|
chart.append("g").append("path").attr("d", Gen(dataAverTmp))
|
|
.attr("fill", "none").attr("stroke", "orange").on("mousemove", printVal).style("stroke-width", "2");
|
|
chart.append("g").append("path").attr("d", Gen(dataMinTmp))
|
|
.attr("fill", "none").attr("stroke", "blue").on("mousemove", printVal).style("stroke-width", "2");
|
|
chart.append("g").append("path").attr("d", Gen(dataMaxTmp))
|
|
.attr("fill", "none").attr("stroke", "red").on("mousemove", printVal).style("stroke-width", "2");
|
|
|
|
//print legend
|
|
chart.append("circle").attr("cx",chartWidth*1/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "red")
|
|
chart.append("text").attr("x", chartWidth*1/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
|
|
.text("Day temperature").style("font-size", "10px").attr("alignment-baseline","middle")
|
|
chart.append("circle").attr("cx",chartWidth*2/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "orange")
|
|
chart.append("text").attr("x", chartWidth*2/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
|
|
.text("Average daily temperature").style("font-size", "10px").attr("alignment-baseline","middle")
|
|
chart.append("circle").attr("cx",chartWidth*3/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "blue")
|
|
chart.append("text").attr("x", chartWidth*3/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
|
|
.text("Night temperature").style("font-size", "10px").attr("alignment-baseline","middle")
|
|
|
|
|
|
|
|
//print title
|
|
let timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
|
|
|
|
const months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
|
|
//Val under line
|
|
function printVal(){
|
|
let m = d3.mouse(this);
|
|
let tmp = convertTemperature(yscale_inv(m[1]-yOffset).toFixed(1));
|
|
let month = months[parseInt(xscale_inv(m[0]-xOffset)/360*12)];
|
|
chart.attr("data-tip", tmp + " in " + month);
|
|
clearTimeout(timerId);
|
|
timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
|
|
}
|
|
|
|
const xAxis = d3
|
|
.axisBottom(xscale)
|
|
.ticks(10)
|
|
.tickFormat(function (d) {
|
|
return months[parseInt(d/360*12)];
|
|
});
|
|
const yAxis = d3
|
|
.axisLeft(yscale)
|
|
.ticks(5)
|
|
.tickFormat(function (d) {
|
|
return convertTemperature(d);
|
|
});
|
|
|
|
const xGrid = d3.axisBottom(xscale).ticks(10).tickSize(-chartHeight).tickFormat("");
|
|
const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth).tickFormat("");
|
|
|
|
chart
|
|
.append("g")
|
|
.attr("id", "epxaxis")
|
|
.attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset + 20) + ")")
|
|
.call(xAxis)
|
|
.selectAll("text")
|
|
.style("text-anchor", "center")
|
|
.attr("transform", function (d) {
|
|
return "rotate(0)"; // used to rotate labels, - anti-clockwise, + clockwise
|
|
});
|
|
|
|
chart
|
|
.append("g")
|
|
.attr("id", "epyaxis")
|
|
.attr("transform", "translate(" + parseInt(+xOffset - 10) + "," + parseInt(+yOffset) + ")")
|
|
.call(yAxis);
|
|
|
|
// add the X gridlines
|
|
chart
|
|
.append("g")
|
|
.attr("id", "epxgrid")
|
|
.attr("class", "epgrid")
|
|
.attr("stroke-dasharray", "4 1")
|
|
.attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset) + ")")
|
|
.call(xGrid);
|
|
|
|
if(minT < 0 && maxT > 0){
|
|
//add zero lv
|
|
chart.append("g").append("line")
|
|
.attr("x1", xscale(0) + xOffset)
|
|
.attr("y1", yscale(0) + yOffset)
|
|
.attr("x2", xscale(360) + xOffset)
|
|
.attr("y2", yscale(0) + yOffset)
|
|
.attr("stroke", "black");
|
|
}
|
|
|
|
// add the Y gridlines
|
|
chart
|
|
.append("g")
|
|
.attr("id", "epygrid")
|
|
.attr("class", "epgrid")
|
|
.attr("stroke-dasharray", "4 1")
|
|
.attr("transform", "translate(" + xOffset + "," + yOffset + ")")
|
|
.call(yGrid);
|
|
}
|
|
function closeTGForBurg() {
|
|
document.getElementById("epControls").style.visibility = "visible";
|
|
document.getElementById("elevationGraph").innerHTML = "";
|
|
modules.elevation = false;
|
|
}
|
|
} |