Skip to content

Commit b3e2aa0

Browse files
AzgaarStempunkDev
andauthored
Independent North and South Poles temperature (#972)
* Poles to have Different Temperature (Ref: Axial Tilt suggestion) (#964) * Initial Idea * Changed Names: Currently still only on NorthTemperature reliant, compadible version * Restored Generation of Temperature * Temperature Function found * Version Bump * Scuffed Saving solution * Current Version(without the save changes) * Globe Temperature Display * Individual Regeneration of Temperatures * Fixed Loading and Saving New Maps save a Dummy 0 at settings[17] * Final Version Bump (currently no description for the Update) --------- Co-authored-by: Azgaar <[email protected]> * chore: formatting * refactor: temperature inputs * feat: rework temperature generation alg * style: respore winds button * refactor: update options on load, don't update temperature UI * refactor: no need to keep compatibility here * fix: load temp setting from .map file --------- Co-authored-by: Leo <[email protected]>
1 parent 7b3f897 commit b3e2aa0

File tree

9 files changed

+238
-153
lines changed

9 files changed

+238
-153
lines changed

index.html

Lines changed: 105 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,29 +2346,58 @@
23462346

23472347
<div id="dialogs">
23482348
<div id="worldConfigurator" class="dialog stable" style="display: none">
2349-
<div>
2349+
<div style="display: flex">
23502350
<div id="worldControls">
23512351
<div>
23522352
<i data-locked="0" id="lock_temperatureEquator" class="icon-lock-open"></i>
23532353
<label data-tip="Set temperature at equator">
23542354
<i>Equator:</i>
2355+
<input id="temperatureEquatorInput" data-stored="temperatureEquator" type="number" min="-50" max="50" />
2356+
<span>°C = <span id="temperatureEquatorF"></span></span>
2357+
<input id="temperatureEquatorOutput" data-stored="temperatureEquator" type="range" min="-50" max="50" />
2358+
</label>
2359+
</div>
2360+
<div>
2361+
<label data-tip="Set the North Pole average yearly temperature">
2362+
<i data-locked="0" id="lock_temperatureNorthPole" class="icon-lock-open"></i>
2363+
<i>North Pole:</i>
23552364
<input
2356-
id="temperatureEquatorInput"
2357-
data-stored="temperatureEquator"
2365+
id="temperatureNorthPoleInput"
2366+
data-stored="temperatureNorthPole"
23582367
type="number"
23592368
min="-50"
23602369
max="50"
2361-
/>°C = <span id="temperatureEquatorF"></span>°F
2362-
<input id="temperatureEquatorOutput" data-stored="temperatureEquator" type="range" min="-50" max="50" />
2370+
/>
2371+
<span>°C = <span id="temperatureNorthPoleF"></span></span>
2372+
<input
2373+
id="temperatureNorthPoleOutput"
2374+
data-stored="temperatureNorthPole"
2375+
type="range"
2376+
min="-50"
2377+
max="50"
2378+
/>
23632379
</label>
23642380
</div>
2381+
23652382
<div>
2366-
<i data-locked="0" id="lock_temperaturePole" class="icon-lock-open"></i>
2367-
<label data-tip="Set temperature near poles">
2368-
<i>Poles:</i>
2369-
<input id="temperaturePoleInput" data-stored="temperaturePole" type="number" min="-50" max="50" />°C =
2370-
<span id="temperaturePoleF"></span>°F
2371-
<input id="temperaturePoleOutput" data-stored="temperaturePole" type="range" min="-50" max="50" />
2383+
<label data-tip="Set the South Pole average yearly temperature">
2384+
<i data-locked="0" id="lock_temperatureSouthPole" class="icon-lock-open"></i>
2385+
<i>South Pole:</i>
2386+
<input
2387+
id="temperatureSouthPoleInput"
2388+
data-stored="temperatureSouthPole"
2389+
type="number"
2390+
min="-50"
2391+
max="50"
2392+
/>
2393+
<span>°C = <span id="temperatureSouthPoleF"></span></span>
2394+
<input
2395+
id="temperatureSouthPoleOutput"
2396+
data-stored="temperatureSouthPole"
2397+
type="range"
2398+
min="-50"
2399+
max="50"
2400+
/>
23722401
</label>
23732402
</div>
23742403
<div>
@@ -2424,59 +2453,65 @@
24242453
<div data-tip="Map coordinates on globe"><i>Coords:</i> <span id="mapCoordinates"></span></div>
24252454
</div>
24262455

2427-
<svg id="globe" width="22em" height="22em" viewBox="-20 -25 240 240">
2428-
<defs>
2429-
<linearGradient id="temperatureGradient" x1="0" x2="0" y1="0" y2="1">
2430-
<stop class="tempGradient90" offset="0%" stop-color="blue" />
2431-
<stop class="tempGradient60" offset="16.6%" stop-color="green" />
2432-
<stop class="tempGradient30" offset="33.3%" stop-color="yellow" />
2433-
<stop class="tempGradient0" offset="50%" stop-color="red" />
2434-
<stop class="tempGradient30" offset="66.6%" stop-color="yellow" />
2435-
<stop class="tempGradient60" offset="83.3%" stop-color="green" />
2436-
<stop class="tempGradient90" offset="100%" stop-color="blue" />
2437-
</linearGradient>
2438-
</defs>
2439-
<g id="globeNoteLines">
2440-
<line x1="5" x2="220" y1="0" y2="0" />
2441-
<line x1="5" x2="220" y1="13" y2="13" />
2442-
<line x1="5" x2="220" y1="49.5" y2="49.5" />
2443-
<line x1="-5" x2="220" y1="100" y2="100" />
2444-
<line x1="5" x2="220" y1="150.5" y2="150.5" />
2445-
<line x1="5" x2="220" y1="187" y2="187" />
2446-
<line x1="5" x2="220" y1="200" y2="200" />
2447-
</g>
2448-
<g id="globeWindArrows" data-tip="Click to change wind direction" stroke-linejoin="round">
2449-
<circle cx="210" cy="6" r="12" />
2450-
<path data-tier="0" d="M210,11 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(225 210 6)" />
2451-
<circle cx="210" cy="30" r="12" />
2452-
<path data-tier="1" d="M210,35 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(45 210 30)" />
2453-
<circle cx="210" cy="75" r="12" />
2454-
<path data-tier="2" d="M210,80 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(225 210 75)" />
2455-
<circle cx="210" cy="130" r="12" />
2456-
<path data-tier="3" d="M210,135 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(315 210 130)" />
2457-
<circle cx="210" cy="173" r="12" />
2458-
<path data-tier="4" d="M210,178 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(135 210 173)" />
2459-
<circle cx="210" cy="194" r="12" />
2460-
<path data-tier="5" d="M210,199 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(315 210 194)" />
2461-
</g>
2462-
<g id="globaAxisLabels">
2463-
<text x="82%" y="-4%">wind</text>
2464-
<text x="-8%" y="-4%">latitude</text>
2465-
</g>
2466-
<g id="globeLatLabels">
2467-
<text x="-15" y="5">90°</text>
2468-
<text x="-15" y="18">60°</text>
2469-
<text x="-15" y="53">30°</text>
2470-
<text x="-15" y="103">0°</text>
2471-
<text x="-15" y="153">30°</text>
2472-
<text x="-15" y="190">60°</text>
2473-
<text x="-15" y="204">90°</text>
2474-
</g>
2475-
<circle id="globeOutline" cx="100" cy="100" r="100" />
2476-
<line id="globeEquator" x1="1" x2="199" y1="100" y2="100" />
2477-
<path id="globeGraticule" />
2478-
<path id="globeArea" />
2479-
</svg>
2456+
<div style="display: flex; flex-direction: column; align-items: flex-end">
2457+
<svg id="globe" width="22em" viewBox="-20 -25 240 240">
2458+
<defs>
2459+
<linearGradient id="temperatureGradient" x1="0" x2="0" y1="0" y2="1">
2460+
<stop id="grad90" offset="0%" stop-color="blue" />
2461+
<stop id="grad60" offset="16.6%" stop-color="green" />
2462+
<stop id="grad30" offset="33.3%" stop-color="yellow" />
2463+
<stop id="grad0" offset="50%" stop-color="red" />
2464+
<stop id="grad-30" offset="66.6%" stop-color="yellow" />
2465+
<stop id="grad-60" offset="83.3%" stop-color="green" />
2466+
<stop id="grad-90" offset="100%" stop-color="blue" />
2467+
</linearGradient>
2468+
</defs>
2469+
<g id="globeNoteLines">
2470+
<line x1="5" x2="220" y1="0" y2="0" />
2471+
<line x1="5" x2="220" y1="13" y2="13" />
2472+
<line x1="5" x2="220" y1="49.5" y2="49.5" />
2473+
<line x1="-5" x2="220" y1="100" y2="100" />
2474+
<line x1="5" x2="220" y1="150.5" y2="150.5" />
2475+
<line x1="5" x2="220" y1="187" y2="187" />
2476+
<line x1="5" x2="220" y1="200" y2="200" />
2477+
</g>
2478+
<g id="globeWindArrows" data-tip="Click to change wind direction" stroke-linejoin="round">
2479+
<circle cx="210" cy="6" r="12" />
2480+
<path data-tier="0" d="M210,11 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(225 210 6)" />
2481+
<circle cx="210" cy="30" r="12" />
2482+
<path data-tier="1" d="M210,35 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(45 210 30)" />
2483+
<circle cx="210" cy="75" r="12" />
2484+
<path data-tier="2" d="M210,80 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(225 210 75)" />
2485+
<circle cx="210" cy="130" r="12" />
2486+
<path data-tier="3" d="M210,135 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(315 210 130)" />
2487+
<circle cx="210" cy="173" r="12" />
2488+
<path data-tier="4" d="M210,178 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(135 210 173)" />
2489+
<circle cx="210" cy="194" r="12" />
2490+
<path data-tier="5" d="M210,199 v-10 l-3,3 m6,0 l-3,-3" transform="rotate(315 210 194)" />
2491+
</g>
2492+
<g id="globaAxisLabels">
2493+
<text x="82%" y="-4%">wind</text>
2494+
<text x="-8%" y="-4%">latitude</text>
2495+
</g>
2496+
<g id="globeLatLabels">
2497+
<text x="-15" y="5">90°</text>
2498+
<text x="-15" y="18">60°</text>
2499+
<text x="-15" y="53">30°</text>
2500+
<text x="-15" y="103">0°</text>
2501+
<text x="-15" y="153">30°</text>
2502+
<text x="-15" y="190">60°</text>
2503+
<text x="-15" y="204">90°</text>
2504+
</g>
2505+
<circle id="globeOutline" cx="100" cy="100" r="100" />
2506+
<line id="globeEquator" x1="1" x2="199" y1="100" y2="100" />
2507+
<path id="globeGraticule" />
2508+
<path id="globeArea" />
2509+
</svg>
2510+
2511+
<button id="restoreWinds" data-tip="Click to restore default (Earth-based) wind directions">
2512+
Restore winds
2513+
</button>
2514+
</div>
24802515
</div>
24812516
</div>
24822517

@@ -7924,14 +7959,14 @@
79247959
<script src="modules/ui/stylePresets.js?v=1.89.11"></script>
79257960

79267961
<script src="modules/ui/general.js?v=1.87.03"></script>
7927-
<script src="modules/ui/options.js?v=1.89.36"></script>
7928-
<script src="main.js?v=1.89.32"></script>
7962+
<script src="modules/ui/options.js?v=1.90.00"></script>
7963+
<script src="main.js?v=1.90.00"></script>
79297964

79307965
<script defer src="modules/relief-icons.js"></script>
79317966
<script defer src="modules/ui/style.js"></script>
79327967
<script defer src="modules/ui/editors.js?v=1.89.35"></script>
7933-
<script defer src="modules/ui/tools.js?v=1.89.38"></script>
7934-
<script defer src="modules/ui/world-configurator.js"></script>
7968+
<script defer src="modules/ui/tools.js?v=1.90.00"></script>
7969+
<script defer src="modules/ui/world-configurator.js?v=1.90.00"></script>
79357970
<script defer src="modules/ui/heightmap-editor.js?v=1.89.06"></script>
79367971
<script defer src="modules/ui/provinces-editor.js?v=1.89.00"></script>
79377972
<script defer src="modules/ui/biomes-editor.js"></script>
@@ -7967,8 +8002,8 @@
79678002
<script defer src="libs/rgbquant.min.js"></script>
79688003
<script defer src="libs/jquery.ui.touch-punch.min.js"></script>
79698004

7970-
<script defer src="modules/io/save.js?v=1.89.29"></script>
7971-
<script defer src="modules/io/load.js?v=1.89.30"></script>
8005+
<script defer src="modules/io/save.js?v=1.90.00"></script>
8006+
<script defer src="modules/io/load.js?v=1.90.00"></script>
79728007
<script defer src="modules/io/cloud.js"></script>
79738008
<script defer src="modules/io/export.js?v=1.89.36"></script>
79748009
<script defer src="modules/io/formats.js"></script>

main.js

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
// set debug options
66
const PRODUCTION = location.hostname && location.hostname !== "localhost" && location.hostname !== "127.0.0.1";
77
const DEBUG = localStorage.getItem("debug");
8-
const INFO = DEBUG || !PRODUCTION;
9-
const TIME = DEBUG || !PRODUCTION;
8+
const INFO = true;
9+
const TIME = true;
1010
const WARN = true;
1111
const ERROR = true;
1212

@@ -179,13 +179,17 @@ function onZoom() {
179179
const onZoomDebouced = debounce(onZoom, 50);
180180
const zoom = d3.zoom().scaleExtent([1, 20]).on("zoom", onZoomDebouced);
181181

182-
// default options
182+
// default options, based on Earth data
183183
let options = {
184184
pinNotes: false,
185185
showMFCGMap: true,
186186
winds: [225, 45, 225, 315, 135, 315],
187+
temperatureEquator: 27,
188+
temperatureNorthPole: -30,
189+
temperatureSouthPole: -15,
187190
stateLabelsMode: "auto"
188191
};
192+
189193
let mapCoordinates = {}; // map coordinates on globe
190194
let populationRate = +document.getElementById("populationRateInput").value;
191195
let distanceScale = +document.getElementById("distanceScaleInput").value;
@@ -467,7 +471,7 @@ function applyDefaultBiomesSystem() {
467471
const biomesMartix = [
468472
// hot ↔ cold [>19°C; <-4°C]; dry ↕ wet
469473
new Uint8Array([1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10]),
470-
new Uint8Array([3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10]),
474+
new Uint8Array([1, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 9, 9, 9, 9, 10, 10, 10]),
471475
new Uint8Array([5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 9, 9, 9, 10, 10, 10]),
472476
new Uint8Array([5, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10]),
473477
new Uint8Array([7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10])
@@ -968,7 +972,7 @@ function defineMapSize() {
968972

969973
const part = grid.features.some(f => f.land && f.border); // if land goes over map borders
970974
const max = part ? 80 : 100; // max size
971-
const lat = () => gauss(P(0.5) ? 40 : 60, 15, 25, 75); // latitude shift
975+
const lat = () => gauss(P(0.5) ? 40 : 60, 20, 25, 75); // latitude shift
972976

973977
if (!part) {
974978
if (template === "Pangea") return [100, 50];
@@ -1003,30 +1007,49 @@ function calculateMapCoordinates() {
10031007
mapCoordinates = {latT, latN, latS, lonT: lon * 2, lonW: -lon, lonE: lon};
10041008
}
10051009

1006-
// temperature model
1010+
// temperature model, trying to follow real-world data
1011+
// based on http://www-das.uwyo.edu/~geerts/cwx/notes/chap16/Image64.gif
10071012
function calculateTemperatures() {
10081013
TIME && console.time("calculateTemperatures");
10091014
const cells = grid.cells;
10101015
cells.temp = new Int8Array(cells.i.length); // temperature array
10111016

1012-
const tEq = +temperatureEquatorInput.value;
1013-
const tPole = +temperaturePoleInput.value;
1014-
const tDelta = tEq - tPole;
1015-
const int = d3.easePolyInOut.exponent(0.5); // interpolation function
1016-
1017-
d3.range(0, cells.i.length, grid.cellsX).forEach(function (r) {
1018-
const y = grid.points[r][1];
1019-
const lat = Math.abs(mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT); // [0; 90]
1020-
const initTemp = tEq - int(lat / 90) * tDelta;
1021-
for (let i = r; i < r + grid.cellsX; i++) {
1022-
cells.temp[i] = minmax(initTemp - convertToFriendly(cells.h[i]), -128, 127);
1017+
const {temperatureEquator, temperatureNorthPole, temperatureSouthPole} = options;
1018+
const tropics = [16, -20]; // tropics zone
1019+
const tropicalGradient = 0.15;
1020+
1021+
const tempNorthTropic = temperatureEquator - tropics[0] * tropicalGradient;
1022+
const northernGradient = (tempNorthTropic - temperatureNorthPole) / (90 - tropics[0]);
1023+
1024+
const tempSouthTropic = temperatureEquator + tropics[1] * tropicalGradient;
1025+
const southernGradient = (tempSouthTropic - temperatureSouthPole) / (90 + tropics[1]);
1026+
1027+
const exponent = +heightExponentInput.value;
1028+
1029+
for (let rowCellId = 0; rowCellId < cells.i.length; rowCellId += grid.cellsX) {
1030+
const [, y] = grid.points[rowCellId];
1031+
const rowLatitude = mapCoordinates.latN - (y / graphHeight) * mapCoordinates.latT; // [90; -90]
1032+
const tempSeaLevel = calculateSeaLevelTemp(rowLatitude);
1033+
DEBUG && console.info(`${rn(rowLatitude)}° sea temperature: ${rn(tempSeaLevel)}°C`);
1034+
1035+
for (let cellId = rowCellId; cellId < rowCellId + grid.cellsX; cellId++) {
1036+
const tempAltitudeDrop = getAltitudeTemperatureDrop(cells.h[cellId]);
1037+
cells.temp[cellId] = minmax(tempSeaLevel - tempAltitudeDrop, -128, 127);
10231038
}
1024-
});
1039+
}
1040+
1041+
function calculateSeaLevelTemp(latitude) {
1042+
const isTropical = latitude <= 16 && latitude >= -20;
1043+
if (isTropical) return temperatureEquator - Math.abs(latitude) * tropicalGradient;
1044+
1045+
return latitude > 0
1046+
? tempNorthTropic - (latitude - tropics[0]) * northernGradient
1047+
: tempSouthTropic + (latitude - tropics[1]) * southernGradient;
1048+
}
10251049

1026-
// temperature decreases by 6.5 degree C per 1km
1027-
function convertToFriendly(h) {
1050+
// temperature drops by 6.5°C per 1km of altitude
1051+
function getAltitudeTemperatureDrop(h) {
10281052
if (h < 20) return 0;
1029-
const exponent = +heightExponentInput.value;
10301053
const height = Math.pow(h - 18, exponent);
10311054
return rn((height / 1000) * 6.5);
10321055
}

modules/dynamic/export-json.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ function getSettings() {
108108
urbanization: urbanization,
109109
mapSize: mapSizeOutput.value,
110110
latitudeO: latitudeOutput.value,
111-
temperatureEquator: temperatureEquatorOutput.value,
112-
temperaturePole: temperaturePoleOutput.value,
113111
prec: precOutput.value,
114112
options: options,
115113
mapName: mapName.value,

modules/io/load.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,13 @@ async function parseLoadedData(data) {
218218
if (settings[13]) urbanization = urbanizationInput.value = urbanizationOutput.value = settings[13];
219219
if (settings[14]) mapSizeInput.value = mapSizeOutput.value = minmax(settings[14], 1, 100);
220220
if (settings[15]) latitudeInput.value = latitudeOutput.value = minmax(settings[15], 0, 100);
221-
if (settings[16]) temperatureEquatorInput.value = temperatureEquatorOutput.value = settings[16];
222-
if (settings[17]) temperaturePoleInput.value = temperaturePoleOutput.value = settings[17];
223221
if (settings[18]) precInput.value = precOutput.value = settings[18];
222+
224223
if (settings[19]) options = JSON.parse(settings[19]);
224+
// setting 16 and 17 (temperature) are part of options now
225+
if (settings[16]) options.temperatureEquator = Number(settings[16]);
226+
if (settings[17]) options.temperatureNorthPole = options.temperatureSouthPole = Number(settings[17]);
227+
225228
if (settings[20]) mapName.value = settings[20];
226229
if (settings[21]) hideLabels.checked = +settings[21];
227230
if (settings[22]) stylePreset.value = settings[22];
@@ -231,6 +234,9 @@ async function parseLoadedData(data) {
231234

232235
void (function applyOptionsToUI() {
233236
stateLabelsModeInput.value = options.stateLabelsMode;
237+
yearInput.value = options.year;
238+
eraInput.value = options.era;
239+
shapeRendering.value = viewbox.attr("shape-rendering") || "geometricPrecision";
234240
})();
235241

236242
void (function parseConfiguration() {
@@ -586,11 +592,6 @@ async function parseLoadedData(data) {
586592
if (rulers && layerIsOn("toggleRulers")) rulers.draw();
587593
if (layerIsOn("toggleGrid")) drawGrid();
588594

589-
// set options
590-
yearInput.value = options.year;
591-
eraInput.value = options.era;
592-
shapeRendering.value = viewbox.attr("shape-rendering") || "geometricPrecision";
593-
594595
if (window.restoreDefaultEvents) restoreDefaultEvents();
595596
focusOn(); // based on searchParams focus on point, cell or burg
596597
invokeActiveZooming();

modules/io/save.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ function getMapData() {
2424
urbanization,
2525
mapSizeOutput.value,
2626
latitudeOutput.value,
27-
temperatureEquatorOutput.value,
28-
temperaturePoleOutput.value,
27+
0, // previously used for temperatureEquatorOutput.value
28+
0, // previously used for tempNorthOutput.value
2929
precOutput.value,
3030
JSON.stringify(options),
3131
mapName.value,

0 commit comments

Comments
 (0)