v. 0.55b
BIN
images/Facebook.png
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
images/Pinterest.png
Normal file
|
After Width: | Height: | Size: 443 B |
BIN
images/Reddit.png
Normal file
|
After Width: | Height: | Size: 509 B |
BIN
images/Tumblr.png
Normal file
|
After Width: | Height: | Size: 310 B |
BIN
images/Twitter.png
Normal file
|
After Width: | Height: | Size: 379 B |
BIN
images/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
images/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
images/preview.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
index.css
53
index.html
|
|
@ -1,26 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<title>Azgaar's Fantasy Map Generator Demo</title>
|
||||
<meta name="author" content="Azgaar (Max Ganiev)">
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="Azgaar's Fantasy Map Generator demo. Based on D3 Voronoi diagram rendered to svg.">
|
||||
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
|
||||
<script src="https://d3js.org/d3.v4.min.js"></script>
|
||||
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
|
||||
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
|
||||
<script src="https://mewo2.com/js/priority-queue.js"></script>
|
||||
<script src="https://rawgit.com/LuisSevillano/9f6c9edd7f90ac6cca54ed744e28f3ee/raw/38f9774f83f00b286360db1ea97d851f79e594aa/polylabel.js"></script>
|
||||
<meta name="author" content="Azgaar (Max Ganiev)">
|
||||
<meta name="description" content="Azgaar's Fantasy Map Generator (demo version). Based on D3 Voronoi diagram rendered to svg">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<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:description" content="Demo version. Based on D3 Voronoi diagram rendered to svg">
|
||||
<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-16x16.png" sizes="16x16"/>
|
||||
<link rel="canonical" href="https://azgaar.github.io/Fantasy-Map-Generator/">
|
||||
<script src="libs/jquery-3.1.1.min.js"></script>
|
||||
<script src="libs/d3.v4.min.js"></script>
|
||||
<script src="libs/d3-scale-chromatic.v1.min.js"></script>
|
||||
<script src="libs/priority-queue.js"></script>
|
||||
<script src="names.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="index.css?version=0.54b"/>
|
||||
<link rel="stylesheet" type="text/css" href="icons.css?version=0.54b"/>
|
||||
<script src="libs/jquery-ui.min.js"></script>
|
||||
<script src="libs/polylabel.js" async></script>
|
||||
<script src="libs/quantize.js" defer></script>
|
||||
<script src="libs/d3-hexbin.v0.2.min.js" defer></script>
|
||||
<link rel="stylesheet" type="text/css" href="index.css?version=0.55b"/>
|
||||
<link rel="stylesheet" type="text/css" href="icons.css?version=0.55b"/>
|
||||
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
|
||||
<script src="quantize.js"></script>
|
||||
</head>
|
||||
<body class="fullscreen">
|
||||
<div id="loading">
|
||||
<h1 class="icon-cog spin"></h1>
|
||||
<h2 id="loading-text">Loading...</h2>
|
||||
<h3 id="loading-text">Loading...</h3>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="fullscreen">
|
||||
<defs>
|
||||
|
|
@ -97,7 +105,7 @@
|
|||
</g>
|
||||
</defs>
|
||||
</svg>
|
||||
<canvas id="canvas" width="960" height="540" style="opacity: 0;"></canvas>
|
||||
<canvas id="canvas" style="opacity: 0"></canvas>
|
||||
<div id="optionsContainer">
|
||||
<div id="collapsible">
|
||||
<button id="optionsTrigger" class="options" title="Click to display Options">▶</button>
|
||||
|
|
@ -110,6 +118,7 @@
|
|||
<button id="styleTab" class="options">Style</button>
|
||||
<button id="optionsTab" class="options">Options</button>
|
||||
<button id="customizeTab" class="options">Customize</button>
|
||||
<button id="aboutTab" class="options">?</button>
|
||||
</div>
|
||||
<div id="layoutContent" class="tabcontent">
|
||||
<p style="display: inline-block;">Select preset:</p>
|
||||
|
|
@ -403,6 +412,18 @@
|
|||
<button id="addRiver" title="Click on map to place new river on extend an existing one" class="radio">River</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="aboutContent" class="tabcontent">
|
||||
<p><a href="https://github.com/Azgaar/Fantasy-Map-Generator" target="_blank">Fantasy Map Generator</a> is an online tool which produces a procedurally generated fantasy maps. You may either use an auto-generated maps or create you own map manually or with a help of templates or image converter. Check out the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki" target="_blank">wiki</a> for guidance.<p/>
|
||||
<p>This is a Demo version, project is still under development. For older versions see the <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog" target="_blank">changelog</a>. Some details are covered in my <a href="https://azgaar.wordpress.com/" target="_blank">blog</a>. To track the current progress see the <a href="https://trello.com/b/7x832DG4/fantasy-map-generator" target="_blank">devboard</a>.<p/>
|
||||
<p>Please report bugs and suggest new features <a href="https://github.com/Azgaar/Fantasy-Map-Generator/issues" target="_blank">here</a>. You may also <a href="mailto:maxganiev@yandex.ru">send me</a> an email.<p/>
|
||||
<ul class="share-buttons">
|
||||
<li><a href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F"e=" title="Share on Facebook" target="_blank"><img alt="Share on Facebook" src="images/Facebook.png" /></a></li>
|
||||
<li><a href="https://twitter.com/intent/tweet?source=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F&text=:%20https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F" target="_blank" title="Tweet"><img alt="Tweet" src="images/Twitter.png" /></a></li>
|
||||
<li><a href="http://www.tumblr.com/share?v=3&u=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F"e=&s=" target="_blank" title="Post to Tumblr"><img alt="Post to Tumblr" src="images/Tumblr.png" /></a></li>
|
||||
<li><a href="http://pinterest.com/pin/create/button/?url=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F&description=" target="_blank" title="Pin it"><img alt="Pin it" src="images/Pinterest.png" /></a></li>
|
||||
<li><a href="http://www.reddit.com/submit?url=https%3A%2F%2Fazgaar.github.io%2FFantasy-Map-Generator%2F&title=" target="_blank" title="Submit to Reddit"><img alt="Submit to Reddit" src="images/Reddit.png" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="sticked">
|
||||
<button id="randomMap" title="Generate new random map based on options being set" class="options">New Map</button>
|
||||
<button id="saveButton" title="Select file format to save map" class="options">Save as</button>
|
||||
|
|
@ -729,8 +750,8 @@
|
|||
Coord: <span id="lx">0</span>/<span id="ly">0</span>;
|
||||
Cell: <span id="cell">0</span>;
|
||||
Height: <span id="height">0</span>;
|
||||
Type: <span id="feature">no</span>;
|
||||
Type: <span id="feature">no</span>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="script.js?version=0.54b"></script>
|
||||
<script type="text/javascript" src="script.js?version=0.55b"></script>
|
||||
</body>
|
||||
2
libs/d3-hexbin.v0.2.min.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// https://github.com/d3/d3-hexbin Version 0.2.2. Copyright 2017 Mike Bostock.
|
||||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(n.d3=n.d3||{})}(this,function(n){"use strict";function t(n){return n[0]}function r(n){return n[1]}var e=Math.PI/3,u=[0,e,2*e,3*e,4*e,5*e],o=function(){function n(n){var t,r={},e=[],u=n.length;for(t=0;t<u;++t)if(!isNaN(i=+d.call(null,o=n[t],t,n))&&!isNaN(c=+p.call(null,o,t,n))){var o,i,c,s=Math.round(c/=f),h=Math.round(i=i/a-(1&s)/2),l=c-s;if(3*Math.abs(l)>1){var v=i-h,M=h+(i<h?-1:1)/2,x=s+(c<s?-1:1),g=i-M,m=c-x;v*v+l*l>g*g+m*m&&(h=M+(1&s?1:-1)/2,s=x)}var y=h+"-"+s,j=r[y];j?j.push(o):(e.push(j=r[y]=[o]),j.x=(h+(1&s)/2)*a,j.y=s*f)}return e}function o(n){var t=0,r=0;return u.map(function(e){var u=Math.sin(e)*n,o=-Math.cos(e)*n,i=u-t,a=o-r;return t=u,r=o,[i,a]})}var i,a,f,c=0,s=0,h=1,l=1,d=t,p=r;return n.hexagon=function(n){return"m"+o(null==n?i:+n).join("l")+"z"},n.centers=function(){for(var n=[],t=Math.round(s/f),r=Math.round(c/a),e=t*f;e<l+i;e+=f,++t)for(var u=r*a+(1&t)*a/2;u<h+a/2;u+=a)n.push([u,e]);return n},n.mesh=function(){var t=o(i).slice(0,4).join("l");return n.centers().map(function(n){return"M"+n+"m"+t}).join("")},n.x=function(t){return arguments.length?(d=t,n):d},n.y=function(t){return arguments.length?(p=t,n):p},n.radius=function(t){return arguments.length?(i=+t,a=2*i*Math.sin(e),f=1.5*i,n):i},n.size=function(t){return arguments.length?(c=s=0,h=+t[0],l=+t[1],n):[h-c,l-s]},n.extent=function(t){return arguments.length?(c=+t[0][0],s=+t[0][1],h=+t[1][0],l=+t[1][1],n):[[c,s],[h,l]]},n.radius(1)};n.hexbin=o,Object.defineProperty(n,"__esModule",{value:!0})});
|
||||
2
libs/d3-scale-chromatic.v1.min.js
vendored
Normal file
2
libs/d3.v4.min.js
vendored
Normal file
4
libs/jquery-3.1.1.min.js
vendored
Normal file
13
libs/jquery-ui.min.js
vendored
Normal file
232
libs/polylabel.js
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.polylabel = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
||||
var Queue = require('tinyqueue');
|
||||
|
||||
module.exports = polylabel;
|
||||
|
||||
function polylabel(polygon, precision, debug) {
|
||||
precision = precision || 1.0;
|
||||
|
||||
// find the bounding box of the outer ring
|
||||
var minX, minY, maxX, maxY;
|
||||
for (var i = 0; i < polygon[0].length; i++) {
|
||||
var p = polygon[0][i];
|
||||
if (!i || p[0] < minX) minX = p[0];
|
||||
if (!i || p[1] < minY) minY = p[1];
|
||||
if (!i || p[0] > maxX) maxX = p[0];
|
||||
if (!i || p[1] > maxY) maxY = p[1];
|
||||
}
|
||||
|
||||
var width = maxX - minX;
|
||||
var height = maxY - minY;
|
||||
var cellSize = Math.min(width, height);
|
||||
var h = cellSize / 2;
|
||||
|
||||
// a priority queue of cells in order of their "potential" (max distance to polygon)
|
||||
var cellQueue = new Queue(null, compareMax);
|
||||
|
||||
// cover polygon with initial cells
|
||||
for (var x = minX; x < maxX; x += cellSize) {
|
||||
for (var y = minY; y < maxY; y += cellSize) {
|
||||
cellQueue.push(new Cell(x + h, y + h, h, polygon));
|
||||
}
|
||||
}
|
||||
|
||||
// take centroid as the first best guess
|
||||
var bestCell = getCentroidCell(polygon);
|
||||
var numProbes = cellQueue.length;
|
||||
|
||||
while (cellQueue.length) {
|
||||
// pick the most promising cell from the queue
|
||||
var cell = cellQueue.pop();
|
||||
|
||||
// update the best cell if we found a better one
|
||||
if (cell.d > bestCell.d) {
|
||||
bestCell = cell;
|
||||
if (debug) console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
|
||||
}
|
||||
|
||||
// do not drill down further if there's no chance of a better solution
|
||||
if (cell.max - bestCell.d <= precision) continue;
|
||||
|
||||
// split the cell into four cells
|
||||
h = cell.h / 2;
|
||||
cellQueue.push(new Cell(cell.x - h, cell.y - h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x + h, cell.y - h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x - h, cell.y + h, h, polygon));
|
||||
cellQueue.push(new Cell(cell.x + h, cell.y + h, h, polygon));
|
||||
numProbes += 4;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.log('num probes: ' + numProbes);
|
||||
console.log('best distance: ' + bestCell.d);
|
||||
}
|
||||
|
||||
return [bestCell.x, bestCell.y];
|
||||
}
|
||||
|
||||
function compareMax(a, b) {
|
||||
return b.max - a.max;
|
||||
}
|
||||
|
||||
function Cell(x, y, h, polygon) {
|
||||
this.x = x; // cell center x
|
||||
this.y = y; // cell center y
|
||||
this.h = h; // half the cell size
|
||||
this.d = pointToPolygonDist(x, y, polygon); // distance from cell center to polygon
|
||||
this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
|
||||
}
|
||||
|
||||
// signed distance from point to polygon outline (negative if point is outside)
|
||||
function pointToPolygonDist(x, y, polygon) {
|
||||
var inside = false;
|
||||
var minDistSq = Infinity;
|
||||
|
||||
for (var k = 0; k < polygon.length; k++) {
|
||||
var ring = polygon[k];
|
||||
|
||||
for (var i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
|
||||
var a = ring[i];
|
||||
var b = ring[j];
|
||||
|
||||
if ((a[1] > y !== b[1] > y) &&
|
||||
(x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0])) inside = !inside;
|
||||
|
||||
minDistSq = Math.min(minDistSq, getSegDistSq(x, y, a, b));
|
||||
}
|
||||
}
|
||||
|
||||
return (inside ? 1 : -1) * Math.sqrt(minDistSq);
|
||||
}
|
||||
|
||||
// get polygon centroid
|
||||
function getCentroidCell(polygon) {
|
||||
var area = 0;
|
||||
var x = 0;
|
||||
var y = 0;
|
||||
var points = polygon[0];
|
||||
|
||||
for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
|
||||
var a = points[i];
|
||||
var b = points[j];
|
||||
var f = a[0] * b[1] - b[0] * a[1];
|
||||
x += (a[0] + b[0]) * f;
|
||||
y += (a[1] + b[1]) * f;
|
||||
area += f * 3;
|
||||
}
|
||||
return new Cell(x / area, y / area, 0, polygon);
|
||||
}
|
||||
|
||||
// get squared distance from a point to a segment
|
||||
function getSegDistSq(px, py, a, b) {
|
||||
|
||||
var x = a[0];
|
||||
var y = a[1];
|
||||
var dx = b[0] - x;
|
||||
var dy = b[1] - y;
|
||||
|
||||
if (dx !== 0 || dy !== 0) {
|
||||
|
||||
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
|
||||
|
||||
if (t > 1) {
|
||||
x = b[0];
|
||||
y = b[1];
|
||||
|
||||
} else if (t > 0) {
|
||||
x += dx * t;
|
||||
y += dy * t;
|
||||
}
|
||||
}
|
||||
|
||||
dx = px - x;
|
||||
dy = py - y;
|
||||
|
||||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
},{"tinyqueue":2}],2:[function(require,module,exports){
|
||||
'use strict';
|
||||
|
||||
module.exports = TinyQueue;
|
||||
|
||||
function TinyQueue(data, compare) {
|
||||
if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare);
|
||||
|
||||
this.data = data || [];
|
||||
this.length = this.data.length;
|
||||
this.compare = compare || defaultCompare;
|
||||
|
||||
if (data) for (var i = Math.floor(this.length / 2); i >= 0; i--) this._down(i);
|
||||
}
|
||||
|
||||
function defaultCompare(a, b) {
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}
|
||||
|
||||
TinyQueue.prototype = {
|
||||
|
||||
push: function (item) {
|
||||
this.data.push(item);
|
||||
this.length++;
|
||||
this._up(this.length - 1);
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
var top = this.data[0];
|
||||
this.data[0] = this.data[this.length - 1];
|
||||
this.length--;
|
||||
this.data.pop();
|
||||
this._down(0);
|
||||
return top;
|
||||
},
|
||||
|
||||
peek: function () {
|
||||
return this.data[0];
|
||||
},
|
||||
|
||||
_up: function (pos) {
|
||||
var data = this.data,
|
||||
compare = this.compare;
|
||||
|
||||
while (pos > 0) {
|
||||
var parent = Math.floor((pos - 1) / 2);
|
||||
if (compare(data[pos], data[parent]) < 0) {
|
||||
swap(data, parent, pos);
|
||||
pos = parent;
|
||||
|
||||
} else break;
|
||||
}
|
||||
},
|
||||
|
||||
_down: function (pos) {
|
||||
var data = this.data,
|
||||
compare = this.compare,
|
||||
len = this.length;
|
||||
|
||||
while (true) {
|
||||
var left = 2 * pos + 1,
|
||||
right = left + 1,
|
||||
min = pos;
|
||||
|
||||
if (left < len && compare(data[left], data[min]) < 0) min = left;
|
||||
if (right < len && compare(data[right], data[min]) < 0) min = right;
|
||||
|
||||
if (min === pos) return;
|
||||
|
||||
swap(data, min, pos);
|
||||
pos = min;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function swap(data, i, j) {
|
||||
var tmp = data[i];
|
||||
data[i] = data[j];
|
||||
data[j] = tmp;
|
||||
}
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
387
libs/priority-queue.js
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.PriorityQueue = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||||
var AbstractPriorityQueue, ArrayStrategy, BHeapStrategy, BinaryHeapStrategy, PriorityQueue,
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
AbstractPriorityQueue = _dereq_('./PriorityQueue/AbstractPriorityQueue');
|
||||
|
||||
ArrayStrategy = _dereq_('./PriorityQueue/ArrayStrategy');
|
||||
|
||||
BinaryHeapStrategy = _dereq_('./PriorityQueue/BinaryHeapStrategy');
|
||||
|
||||
BHeapStrategy = _dereq_('./PriorityQueue/BHeapStrategy');
|
||||
|
||||
PriorityQueue = (function(superClass) {
|
||||
extend(PriorityQueue, superClass);
|
||||
|
||||
function PriorityQueue(options) {
|
||||
options || (options = {});
|
||||
options.strategy || (options.strategy = BinaryHeapStrategy);
|
||||
options.comparator || (options.comparator = function(a, b) {
|
||||
return (a || 0) - (b || 0);
|
||||
});
|
||||
PriorityQueue.__super__.constructor.call(this, options);
|
||||
}
|
||||
|
||||
return PriorityQueue;
|
||||
|
||||
})(AbstractPriorityQueue);
|
||||
|
||||
PriorityQueue.ArrayStrategy = ArrayStrategy;
|
||||
|
||||
PriorityQueue.BinaryHeapStrategy = BinaryHeapStrategy;
|
||||
|
||||
PriorityQueue.BHeapStrategy = BHeapStrategy;
|
||||
|
||||
module.exports = PriorityQueue;
|
||||
|
||||
|
||||
},{"./PriorityQueue/AbstractPriorityQueue":2,"./PriorityQueue/ArrayStrategy":3,"./PriorityQueue/BHeapStrategy":4,"./PriorityQueue/BinaryHeapStrategy":5}],2:[function(_dereq_,module,exports){
|
||||
var AbstractPriorityQueue;
|
||||
|
||||
module.exports = AbstractPriorityQueue = (function() {
|
||||
function AbstractPriorityQueue(options) {
|
||||
var ref;
|
||||
if ((options != null ? options.strategy : void 0) == null) {
|
||||
throw 'Must pass options.strategy, a strategy';
|
||||
}
|
||||
if ((options != null ? options.comparator : void 0) == null) {
|
||||
throw 'Must pass options.comparator, a comparator';
|
||||
}
|
||||
this.priv = new options.strategy(options);
|
||||
this.length = (options != null ? (ref = options.initialValues) != null ? ref.length : void 0 : void 0) || 0;
|
||||
}
|
||||
|
||||
AbstractPriorityQueue.prototype.queue = function(value) {
|
||||
this.length++;
|
||||
this.priv.queue(value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.dequeue = function(value) {
|
||||
if (!this.length) {
|
||||
throw 'Empty queue';
|
||||
}
|
||||
this.length--;
|
||||
return this.priv.dequeue();
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.peek = function(value) {
|
||||
if (!this.length) {
|
||||
throw 'Empty queue';
|
||||
}
|
||||
return this.priv.peek();
|
||||
};
|
||||
|
||||
AbstractPriorityQueue.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
return this.priv.clear();
|
||||
};
|
||||
|
||||
return AbstractPriorityQueue;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],3:[function(_dereq_,module,exports){
|
||||
var ArrayStrategy, binarySearchForIndexReversed;
|
||||
|
||||
binarySearchForIndexReversed = function(array, value, comparator) {
|
||||
var high, low, mid;
|
||||
low = 0;
|
||||
high = array.length;
|
||||
while (low < high) {
|
||||
mid = (low + high) >>> 1;
|
||||
if (comparator(array[mid], value) >= 0) {
|
||||
low = mid + 1;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
module.exports = ArrayStrategy = (function() {
|
||||
function ArrayStrategy(options) {
|
||||
var ref;
|
||||
this.options = options;
|
||||
this.comparator = this.options.comparator;
|
||||
this.data = ((ref = this.options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||
this.data.sort(this.comparator).reverse();
|
||||
}
|
||||
|
||||
ArrayStrategy.prototype.queue = function(value) {
|
||||
var pos;
|
||||
pos = binarySearchForIndexReversed(this.data, value, this.comparator);
|
||||
this.data.splice(pos, 0, value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.dequeue = function() {
|
||||
return this.data.pop();
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.peek = function() {
|
||||
return this.data[this.data.length - 1];
|
||||
};
|
||||
|
||||
ArrayStrategy.prototype.clear = function() {
|
||||
this.data.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return ArrayStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],4:[function(_dereq_,module,exports){
|
||||
var BHeapStrategy;
|
||||
|
||||
module.exports = BHeapStrategy = (function() {
|
||||
function BHeapStrategy(options) {
|
||||
var arr, i, j, k, len, ref, ref1, shift, value;
|
||||
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
this.pageSize = (options != null ? options.pageSize : void 0) || 512;
|
||||
this.length = 0;
|
||||
shift = 0;
|
||||
while ((1 << shift) < this.pageSize) {
|
||||
shift += 1;
|
||||
}
|
||||
if (1 << shift !== this.pageSize) {
|
||||
throw 'pageSize must be a power of two';
|
||||
}
|
||||
this._shift = shift;
|
||||
this._emptyMemoryPageTemplate = arr = [];
|
||||
for (i = j = 0, ref = this.pageSize; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
|
||||
arr.push(null);
|
||||
}
|
||||
this._memory = [];
|
||||
this._mask = this.pageSize - 1;
|
||||
if (options.initialValues) {
|
||||
ref1 = options.initialValues;
|
||||
for (k = 0, len = ref1.length; k < len; k++) {
|
||||
value = ref1[k];
|
||||
this.queue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BHeapStrategy.prototype.queue = function(value) {
|
||||
this.length += 1;
|
||||
this._write(this.length, value);
|
||||
this._bubbleUp(this.length, value);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.dequeue = function() {
|
||||
var ret, val;
|
||||
ret = this._read(1);
|
||||
val = this._read(this.length);
|
||||
this.length -= 1;
|
||||
if (this.length > 0) {
|
||||
this._write(1, val);
|
||||
this._bubbleDown(1, val);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.peek = function() {
|
||||
return this._read(1);
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
this._memory.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._write = function(index, value) {
|
||||
var page;
|
||||
page = index >> this._shift;
|
||||
while (page >= this._memory.length) {
|
||||
this._memory.push(this._emptyMemoryPageTemplate.slice(0));
|
||||
}
|
||||
return this._memory[page][index & this._mask] = value;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._read = function(index) {
|
||||
return this._memory[index >> this._shift][index & this._mask];
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._bubbleUp = function(index, value) {
|
||||
var compare, indexInPage, parentIndex, parentValue;
|
||||
compare = this.comparator;
|
||||
while (index > 1) {
|
||||
indexInPage = index & this._mask;
|
||||
if (index < this.pageSize || indexInPage > 3) {
|
||||
parentIndex = (index & ~this._mask) | (indexInPage >> 1);
|
||||
} else if (indexInPage < 2) {
|
||||
parentIndex = (index - this.pageSize) >> this._shift;
|
||||
parentIndex += parentIndex & ~(this._mask >> 1);
|
||||
parentIndex |= this.pageSize >> 1;
|
||||
} else {
|
||||
parentIndex = index - 2;
|
||||
}
|
||||
parentValue = this._read(parentIndex);
|
||||
if (compare(parentValue, value) < 0) {
|
||||
break;
|
||||
}
|
||||
this._write(parentIndex, value);
|
||||
this._write(index, parentValue);
|
||||
index = parentIndex;
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BHeapStrategy.prototype._bubbleDown = function(index, value) {
|
||||
var childIndex1, childIndex2, childValue1, childValue2, compare;
|
||||
compare = this.comparator;
|
||||
while (index < this.length) {
|
||||
if (index > this._mask && !(index & (this._mask - 1))) {
|
||||
childIndex1 = childIndex2 = index + 2;
|
||||
} else if (index & (this.pageSize >> 1)) {
|
||||
childIndex1 = (index & ~this._mask) >> 1;
|
||||
childIndex1 |= index & (this._mask >> 1);
|
||||
childIndex1 = (childIndex1 + 1) << this._shift;
|
||||
childIndex2 = childIndex1 + 1;
|
||||
} else {
|
||||
childIndex1 = index + (index & this._mask);
|
||||
childIndex2 = childIndex1 + 1;
|
||||
}
|
||||
if (childIndex1 !== childIndex2 && childIndex2 <= this.length) {
|
||||
childValue1 = this._read(childIndex1);
|
||||
childValue2 = this._read(childIndex2);
|
||||
if (compare(childValue1, value) < 0 && compare(childValue1, childValue2) <= 0) {
|
||||
this._write(childIndex1, value);
|
||||
this._write(index, childValue1);
|
||||
index = childIndex1;
|
||||
} else if (compare(childValue2, value) < 0) {
|
||||
this._write(childIndex2, value);
|
||||
this._write(index, childValue2);
|
||||
index = childIndex2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (childIndex1 <= this.length) {
|
||||
childValue1 = this._read(childIndex1);
|
||||
if (compare(childValue1, value) < 0) {
|
||||
this._write(childIndex1, value);
|
||||
this._write(index, childValue1);
|
||||
index = childIndex1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return BHeapStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}],5:[function(_dereq_,module,exports){
|
||||
var BinaryHeapStrategy;
|
||||
|
||||
module.exports = BinaryHeapStrategy = (function() {
|
||||
function BinaryHeapStrategy(options) {
|
||||
var ref;
|
||||
this.comparator = (options != null ? options.comparator : void 0) || function(a, b) {
|
||||
return a - b;
|
||||
};
|
||||
this.length = 0;
|
||||
this.data = ((ref = options.initialValues) != null ? ref.slice(0) : void 0) || [];
|
||||
this._heapify();
|
||||
}
|
||||
|
||||
BinaryHeapStrategy.prototype._heapify = function() {
|
||||
var i, j, ref;
|
||||
if (this.data.length > 0) {
|
||||
for (i = j = 1, ref = this.data.length; 1 <= ref ? j < ref : j > ref; i = 1 <= ref ? ++j : --j) {
|
||||
this._bubbleUp(i);
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.queue = function(value) {
|
||||
this.data.push(value);
|
||||
this._bubbleUp(this.data.length - 1);
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.dequeue = function() {
|
||||
var last, ret;
|
||||
ret = this.data[0];
|
||||
last = this.data.pop();
|
||||
if (this.data.length > 0) {
|
||||
this.data[0] = last;
|
||||
this._bubbleDown(0);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.peek = function() {
|
||||
return this.data[0];
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
this.data.length = 0;
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype._bubbleUp = function(pos) {
|
||||
var parent, x;
|
||||
while (pos > 0) {
|
||||
parent = (pos - 1) >>> 1;
|
||||
if (this.comparator(this.data[pos], this.data[parent]) < 0) {
|
||||
x = this.data[parent];
|
||||
this.data[parent] = this.data[pos];
|
||||
this.data[pos] = x;
|
||||
pos = parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
BinaryHeapStrategy.prototype._bubbleDown = function(pos) {
|
||||
var last, left, minIndex, right, x;
|
||||
last = this.data.length - 1;
|
||||
while (true) {
|
||||
left = (pos << 1) + 1;
|
||||
right = left + 1;
|
||||
minIndex = pos;
|
||||
if (left <= last && this.comparator(this.data[left], this.data[minIndex]) < 0) {
|
||||
minIndex = left;
|
||||
}
|
||||
if (right <= last && this.comparator(this.data[right], this.data[minIndex]) < 0) {
|
||||
minIndex = right;
|
||||
}
|
||||
if (minIndex !== pos) {
|
||||
x = this.data[minIndex];
|
||||
this.data[minIndex] = this.data[pos];
|
||||
this.data[pos] = x;
|
||||
pos = minIndex;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
};
|
||||
|
||||
return BinaryHeapStrategy;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
212
script.js
|
|
@ -2,10 +2,14 @@
|
|||
"use strict;"
|
||||
fantasyMap();
|
||||
function fantasyMap() {
|
||||
// Version control
|
||||
var version = "0.55b";
|
||||
document.title += " v. " + version;
|
||||
|
||||
// Declare variables
|
||||
var svg = d3.select("svg"),
|
||||
defs = svg.select("#deftemp"),
|
||||
viewbox = svg.append("g").attr("id", "viewbox").on("touchmove mousemove", moved).on("click", clicked),
|
||||
viewbox = svg.append("g").attr("id", "viewbox"),
|
||||
ocean = viewbox.append("g").attr("id", "ocean"),
|
||||
oceanLayers = ocean.append("g").attr("id", "oceanLayers"),
|
||||
oceanPattern = ocean.append("g").attr("id", "oceanPattern"),
|
||||
|
|
@ -33,6 +37,7 @@ function fantasyMap() {
|
|||
debug = viewbox.append("g").attr("id", "debug");
|
||||
|
||||
// Declare styles
|
||||
viewbox.on("touchmove mousemove", moved).on("click", clicked);
|
||||
landmass.attr("fill", "#eef6fb");
|
||||
coastline.attr("opacity", .5).attr("stroke", "#1f3846").attr("stroke-width", .7).attr("filter", "url(#dropShadow)");
|
||||
regions.attr("opacity", .55);
|
||||
|
|
@ -49,40 +54,21 @@ function fantasyMap() {
|
|||
ruler.style("display", "none").attr("filter", "url(#dropShadow)");
|
||||
overlay.attr("stroke", "#808080").attr("stroke-width", .5);
|
||||
|
||||
// Common variables
|
||||
var mapWidth, mapHeight,
|
||||
customization, history = [], historyStage = -1, elSelected,
|
||||
cells = [], land = [], riversData = [], manors = [], states = [],
|
||||
queue = [], chain = {}, island = 0, cultureTree, manorTree, shift = false;
|
||||
|
||||
// canvas
|
||||
var canvas = document.getElementById("canvas"),
|
||||
ctx = canvas.getContext("2d");
|
||||
|
||||
// Color schemes
|
||||
// Color schemes;
|
||||
var color = d3.scaleSequential(d3.interpolateSpectral),
|
||||
colors8 = d3.scaleOrdinal(d3.schemeSet2),
|
||||
colors20 = d3.scaleOrdinal(d3.schemeCategory20);
|
||||
|
||||
// Version control
|
||||
var version = "0.54b";
|
||||
document.title = document.title + " v. " + version;
|
||||
|
||||
// Set screen size
|
||||
var mapWidth, mapHeight;
|
||||
if (localStorage.getItem("screenSize")) {
|
||||
var stored = localStorage.getItem("screenSize").split(",");
|
||||
mapWidth = mapWidthInput.value = +stored[0];
|
||||
mapHeight = mapHeightInput.value = +stored[1];
|
||||
} else {
|
||||
mapWidth = mapWidthInput.value = $(window).width();
|
||||
mapHeight = mapHeightInput.value = $(window).height();
|
||||
}
|
||||
svg.attr("width", mapWidth);
|
||||
svg.attr("height", mapHeight);
|
||||
$("#loading").remove();
|
||||
$("#statusbar").css("top", mapHeight - 20).show();
|
||||
$("#optionsContainer").show();
|
||||
|
||||
// Common variables
|
||||
var customization, history = [], historyStage = -1, elSelected,
|
||||
cells = [], land = [], riversData = [], manors = [], states = [],
|
||||
queue = [], chain = {}, island = 0, cultureTree, manorTree, shift = false,
|
||||
scalePos = [mapWidth - 10, mapHeight - 10];
|
||||
// randomize options
|
||||
var graphSize = +sizeInput.value,
|
||||
manorsCount = manorsOutput.innerHTML = +manorsInput.value,
|
||||
|
|
@ -101,6 +87,24 @@ function fantasyMap() {
|
|||
countries = labels.append("g").attr("id", "countries").attr("fill", "#3e3e4b").attr("opacity", 1).attr("font-family", "Amatic SC").attr("data-font", "Amatic+SC:700").attr("font-size", size).attr("data-size", size),
|
||||
addedLabels = labels.append("g").attr("id", "addedLabels").attr("fill", "#3e3e4b").attr("opacity", 1).attr("font-family", "Amatic SC").attr("data-font", "Amatic+SC:700").attr("font-size", 18).attr("data-size", 18);
|
||||
|
||||
// Get screen size
|
||||
if (localStorage.getItem("screenSize")) {
|
||||
var stored = localStorage.getItem("screenSize").split(",");
|
||||
mapWidthInput.value = +stored[0];
|
||||
mapHeightInput.value = +stored[1];
|
||||
$(".fullscreen").removeClass("fullscreen");
|
||||
$("#mapScreenSize").addClass("icon-resize-full-alt").removeClass("icon-resize-small");
|
||||
} else {
|
||||
mapWidthInput.value = $(window).width();
|
||||
mapHeightInput.value = $(window).height();
|
||||
}
|
||||
applyMapSize();
|
||||
|
||||
// toggle off loading screen and on menus
|
||||
$("#loading").remove();
|
||||
$("#statusbar").css("top", mapHeight - 20).show();
|
||||
$("#optionsContainer").show();
|
||||
|
||||
// append ocean pattern
|
||||
oceanPattern.append("rect").attr("x", 0).attr("y", 0)
|
||||
.attr("width", mapWidth).attr("height", mapHeight).attr("class", "pattern")
|
||||
|
|
@ -199,20 +203,20 @@ function fantasyMap() {
|
|||
// Changelog dialog window
|
||||
var storedVersion = localStorage.getItem("version"); // show message on load
|
||||
if (storedVersion != version) {
|
||||
var message = "2018-03-07: The <i>Fantasy Map Generator</i> Demo is updated up to version " + version + ". <br><br>Main changes:";
|
||||
message += "<br>* 'Graph size' option is usable now";
|
||||
message += "<br>* 'Add River' button (click to auto-add a new River)";
|
||||
message += "<br>* Re-worked 'Paint Brushes' (Undo-Redo etc)";
|
||||
message += "<br>* 'Perspective' preview for Heightmap";
|
||||
message += "<br>* Active zooming (rescale labels on zooming)";
|
||||
message += "<br>* Save/Load buttons moved to Options footer";
|
||||
message += "<br>* 'Print' button is added";
|
||||
message += "<br><br>See ";
|
||||
var message = "2018-03-30: The <i>Fantasy Map Generator</i> Demo is updated up to version " + version + ". Main features:<br><br>";
|
||||
message += "<li>Countries Editor: add, remove, change borders, export data etc.</li>";
|
||||
message += "<li>Burgs Editor: add, rename, remove, change population or capital</li>";
|
||||
message += "<li>Scale Editor: set distance, area and population scales</li>";
|
||||
message += "<li>Measurers: linear distance, curve length and area measurers</li>";
|
||||
message += "<li>Scale bar: toggable auto-rourded and auto-sized bar</li>";
|
||||
message += "<li>Overlays: hex grid, square grid, wind rose</li>";
|
||||
message += "<br><i>See ";
|
||||
message += "<a href='https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Changelog' target='_blank'>changelog</a>";
|
||||
message += " for additional details. Please report bugs and suggest enhancements ";
|
||||
message += "<a href='https://github.com/Azgaar/Fantasy-Map-Generator/issues' target='_blank'>here</a>";
|
||||
message += " for more details. Please report bugs ";
|
||||
message += "<a href='https://github.com/Azgaar/Fantasy-Map-Generator/issues' target='_blank'>here</a></i>";
|
||||
alertMessage.innerHTML = message;
|
||||
$(function() {$("#alert").dialog({resizable: false, title: "Fantasy Map Generator v. " + version,
|
||||
$("#alert").dialog(
|
||||
{resizable: false, title: "Fantasy Map Generator v. " + version, width: 400,
|
||||
buttons: {
|
||||
"Don't show again": function() {
|
||||
localStorage.setItem("version", version);
|
||||
|
|
@ -220,7 +224,7 @@ function fantasyMap() {
|
|||
},
|
||||
Close: function() {$(this).dialog("close");}
|
||||
},
|
||||
position: {my: "center", at: "center", of: "svg"}})
|
||||
position: {my: "center", at: "center", of: "svg"}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +234,8 @@ function fantasyMap() {
|
|||
function generate() {
|
||||
console.group("Random map");
|
||||
console.time("TOTAL");
|
||||
if (randomizeInput.value === "1") {randomizeOptions();}
|
||||
applyMapSize();
|
||||
randomizeOptions();
|
||||
placePoints();
|
||||
calculateVoronoi(points);
|
||||
detectNeighbors();
|
||||
|
|
@ -245,13 +250,13 @@ function fantasyMap() {
|
|||
drawCoastline();
|
||||
manorsAndRegions();
|
||||
cleanData();
|
||||
if (!$("#toggleHeight").hasClass("buttonoff") && !terrs.selectAll("path").size()) {toggleHeight();}
|
||||
console.timeEnd("TOTAL");
|
||||
console.groupEnd("Random map");
|
||||
}
|
||||
|
||||
// randomize options if randomization is allowed in option
|
||||
function randomizeOptions() {
|
||||
if (randomizeInput.value !== "1") {return;}
|
||||
regionsInput.value = 7 + Math.floor(Math.random() * 10);
|
||||
manorsInput.value = regionsInput.value * 27 + Math.floor(Math.random() * 300);
|
||||
manorsCount = manorsOutput.innerHTML = manorsInput.value;
|
||||
|
|
@ -553,77 +558,78 @@ function fantasyMap() {
|
|||
if (rnd <= 0.01) {mapTemplate = "Atoll";}
|
||||
}
|
||||
addMountain();
|
||||
if (mapTemplate === "Volcano") {templateVolcano();}
|
||||
if (mapTemplate === "High Island") {templateHighIsland();}
|
||||
if (mapTemplate === "Low Island") {templateLowIsland();}
|
||||
if (mapTemplate === "Continents") {templateContinents();}
|
||||
if (mapTemplate === "Archipelago") {templateArchipelago();}
|
||||
if (mapTemplate === "Atoll") {templateAtoll();}
|
||||
var mod = rn((mapWidth + mapHeight) / 1500, 2); // add mod for big screens
|
||||
if (mapTemplate === "Volcano") {templateVolcano(mod);}
|
||||
if (mapTemplate === "High Island") {templateHighIsland(mod);}
|
||||
if (mapTemplate === "Low Island") {templateLowIsland(mod);}
|
||||
if (mapTemplate === "Continents") {templateContinents(mod);}
|
||||
if (mapTemplate === "Archipelago") {templateArchipelago(mod);}
|
||||
if (mapTemplate === "Atoll") {templateAtoll(mod);}
|
||||
console.log(mapTemplate + " template is applied");
|
||||
console.timeEnd('defineHeightmap');
|
||||
}
|
||||
|
||||
// Heighmap Template: Volcano
|
||||
function templateVolcano() {
|
||||
function templateVolcano(mod) {
|
||||
modifyHeights("all", 0.05, 1.1);
|
||||
addHill(5, 0.4);
|
||||
addHill(2, 0.15);
|
||||
addRange(3);
|
||||
addRange(-3);
|
||||
addHill(rn(5 * mod), 0.4);
|
||||
addHill(rn(2 * mod), 0.15);
|
||||
addRange(rn(3 * mod));
|
||||
addRange(rn(-3 * mod));
|
||||
}
|
||||
|
||||
// Heighmap Template: High Island
|
||||
function templateHighIsland() {
|
||||
function templateHighIsland(mod) {
|
||||
modifyHeights("all", 0.05, 0.9);
|
||||
addRange(4);
|
||||
addHill(12, 0.25);
|
||||
addRange(-3);
|
||||
addRange(rn(4 * mod));
|
||||
addHill(rn(12 * mod), 0.25);
|
||||
addRange(rn(-3 * mod));
|
||||
modifyHeights("land", 0, 0.75);
|
||||
addHill(3, 0.15);
|
||||
addHill(rn(3 * mod), 0.15);
|
||||
}
|
||||
|
||||
// Heighmap Template: Low Island
|
||||
function templateLowIsland() {
|
||||
function templateLowIsland(mod) {
|
||||
smoothHeights(2);
|
||||
addRange(1);
|
||||
addHill(4, 0.4);
|
||||
addHill(12, 0.2);
|
||||
addRange(-8);
|
||||
addRange(rn(1 * mod));
|
||||
addHill(rn(4 * mod), 0.4);
|
||||
addHill(rn(12 * mod), 0.2);
|
||||
addRange(rn(-8 * mod));
|
||||
modifyHeights("land", 0, 0.35);
|
||||
}
|
||||
|
||||
// Heighmap Template: Continents
|
||||
function templateContinents() {
|
||||
addHill(24, 0.25);
|
||||
addRange(4);
|
||||
addHill(3, 0.18);
|
||||
function templateContinents(mod) {
|
||||
addHill(rn(24 * mod), 0.25);
|
||||
addRange(rn(4 * mod));
|
||||
addHill(rn(3 * mod), 0.18);
|
||||
modifyHeights("land", 0, 0.7);
|
||||
var count = Math.ceil(Math.random() * 6 + 2);
|
||||
addStrait(count);
|
||||
smoothHeights(2);
|
||||
addPit(7);
|
||||
addRange(-8);
|
||||
addPit(rn(7 * mod));
|
||||
addRange(rn(-8 * mod));
|
||||
modifyHeights("land", 0, 0.8);
|
||||
modifyHeights("all", 0.02, 1);
|
||||
}
|
||||
|
||||
// Heighmap Template: Archipelago
|
||||
function templateArchipelago() {
|
||||
function templateArchipelago(mod) {
|
||||
modifyHeights("land", -0.2, 1);
|
||||
addHill(14, 0.17);
|
||||
addRange(5);
|
||||
addHill(rn(14 * mod), 0.17);
|
||||
addRange(rn(5 * mod));
|
||||
var count = Math.ceil(Math.random() * 2 + 2);
|
||||
addStrait(count);
|
||||
addRange(-12);
|
||||
addPit(8);
|
||||
addRange(rn(-12 * mod));
|
||||
addPit(rn(8 * mod));
|
||||
modifyHeights("land", -0.05, 0.7);
|
||||
smoothHeights(4);
|
||||
}
|
||||
|
||||
// Heighmap Template: Atoll
|
||||
function templateAtoll() {
|
||||
addHill(2, 0.35);
|
||||
addRange(2);
|
||||
function templateAtoll(mod) {
|
||||
addHill(rn(2 * mod), 0.35);
|
||||
addRange(rn(2 * mod));
|
||||
modifyHeights("all", 0.07, 1);
|
||||
smoothHeights(1);
|
||||
modifyHeights("0.27-10", 0, 0.1);
|
||||
|
|
@ -653,7 +659,7 @@ function fantasyMap() {
|
|||
}
|
||||
|
||||
function add(start, type, height) {
|
||||
var session = Math.ceil(Math.random() * 100000);
|
||||
var session = Math.ceil(Math.random() * 1e5);
|
||||
var sharpness = 0.2;
|
||||
var radius, hRadius, mRadius;
|
||||
switch (+graphSize) {
|
||||
|
|
@ -664,7 +670,7 @@ function fantasyMap() {
|
|||
}
|
||||
radius = type === "mountain" ? mRadius : hRadius;
|
||||
var queue = [start];
|
||||
cells[start].height += height;
|
||||
if (type === "mountain") {cells[start].height = height;}
|
||||
for (i = 0; i < queue.length && height >= 0.01; i++) {
|
||||
if (type == "mountain") {
|
||||
height = +cells[queue[i]].height * radius - height / 100;
|
||||
|
|
@ -1107,7 +1113,7 @@ function fantasyMap() {
|
|||
if (cells[ea].height < 0.2) {
|
||||
var start = edge[0].join(" ");
|
||||
var end = edge[1].join(" ");
|
||||
if (cells[ea].fn === "Lake") {
|
||||
if (cells[ea].f === "Lake") {
|
||||
lakeEdges.push({start, end});
|
||||
} else {
|
||||
// island extreme points
|
||||
|
|
@ -1182,8 +1188,13 @@ function fantasyMap() {
|
|||
label = `One pixel equals ${dScale} ${unit}`;
|
||||
scaleBar.append("text").attr("x", x + (l+1) / 2).attr("y", y + 2 * size).attr("dominant-baseline", "text-before-edge").attr("font-size", rn(7 * size, 1)).text(label);
|
||||
// move scaleBar to desired bottom-right point
|
||||
var bbox = scaleBar.node().getBBox();
|
||||
var tr = [scalePos[0] - bbox.width, scalePos[1] - bbox.height];
|
||||
var tr, bbox = scaleBar.node().getBBox();
|
||||
if (localStorage.getItem("scaleBar")) {
|
||||
var scalePos = localStorage.getItem("scaleBar").split(",");
|
||||
tr = [+scalePos[0] - bbox.width, +scalePos[1] - bbox.height];
|
||||
} else {
|
||||
tr = [mapWidth - 10 - bbox.width, mapHeight - 10 - bbox.height];
|
||||
}
|
||||
scaleBar.attr("transform", "translate(" + rn(tr[0]) + "," + rn(tr[1]) + ")");
|
||||
}
|
||||
|
||||
|
|
@ -1225,7 +1236,7 @@ function fantasyMap() {
|
|||
// remember scaleBar bottom-right position
|
||||
if (el.attr("id") === "scaleBar") {
|
||||
var bbox = el.node().getBoundingClientRect();
|
||||
scalePos = [bbox.right, bbox.bottom];
|
||||
localStorage.setItem("scaleBar", [bbox.right, bbox.bottom])
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -2722,8 +2733,9 @@ function fantasyMap() {
|
|||
delete c.used;
|
||||
delete c.coastX;
|
||||
delete c.coastY;
|
||||
|
||||
});
|
||||
// restore heightmap layer if it was turned on
|
||||
if (!$("#toggleHeight").hasClass("buttonoff") && !terrs.selectAll("path").size()) {toggleHeight();}
|
||||
console.timeEnd("cleanData");
|
||||
}
|
||||
|
||||
|
|
@ -2898,7 +2910,8 @@ function fantasyMap() {
|
|||
function getMap() {
|
||||
exitCustomization();
|
||||
console.time("TOTAL");
|
||||
if (randomizeInput.value === "1") {randomizeOptions();}
|
||||
applyMapSize();
|
||||
randomizeOptions();
|
||||
markFeatures();
|
||||
drawOcean();
|
||||
reGraph();
|
||||
|
|
@ -2908,7 +2921,6 @@ function fantasyMap() {
|
|||
drawCoastline();
|
||||
manorsAndRegions();
|
||||
cleanData();
|
||||
if (!$("#toggleHeight").hasClass("buttonoff") && terrs.selectAll("path").size() === 0) {toggleHeight();}
|
||||
console.timeEnd("TOTAL");
|
||||
}
|
||||
|
||||
|
|
@ -4402,7 +4414,7 @@ function fantasyMap() {
|
|||
$("svg").addClass("fullscreen");
|
||||
$(this).removeClass("icon-resize-full-alt").addClass("icon-resize-small");
|
||||
}
|
||||
updateMapSize();
|
||||
changeMapSize();
|
||||
}
|
||||
if (id === "saveButton") {$("#saveDropdown").slideToggle();}
|
||||
if (id === "loadMap") {fileToLoad.click();}
|
||||
|
|
@ -5609,12 +5621,25 @@ function fantasyMap() {
|
|||
lines.detach().appendTo(list);
|
||||
});
|
||||
|
||||
// updateMapSize
|
||||
function updateMapSize() {
|
||||
// just apply map size that was already set
|
||||
function applyMapSize() {
|
||||
mapWidth = +mapWidthInput.value;
|
||||
mapHeight = +mapHeightInput.value;
|
||||
svg.attr("width", mapWidth).attr("height", mapHeight);
|
||||
canvas.width = mapWidth;
|
||||
canvas.height = mapHeight;
|
||||
}
|
||||
|
||||
// change map size on manual size change or window resize
|
||||
function changeMapSize() {
|
||||
mapWidth = +mapWidthInput.value;
|
||||
mapHeight = +mapHeightInput.value;
|
||||
svg.attr("width", mapWidth).attr("height", mapHeight);
|
||||
if ($("body").hasClass("fullscreen")) {
|
||||
localStorage.removeItem("screenSize");
|
||||
} else {
|
||||
localStorage.setItem("screenSize", [mapWidth, mapHeight]);
|
||||
}
|
||||
voronoi = d3.voronoi().extent([[0, 0], [mapWidth, mapHeight]]);
|
||||
oceanPattern.select("rect").attr("width", mapWidth).attr("height", mapHeight);
|
||||
oceanLayers.select("rect").attr("width", mapWidth).attr("height", mapHeight);
|
||||
|
|
@ -5622,10 +5647,12 @@ function fantasyMap() {
|
|||
scY = d3.scaleLinear().domain([0, mapHeight]).range([0, mapHeight]);
|
||||
lineGen = d3.line().x(function(d) {return scX(d.scX);}).y(function(d) {return scY(d.scY);});
|
||||
zoom.translateExtent([[0, 0], [mapWidth, mapHeight]]);
|
||||
scalePos = [mapWidth - 10, mapHeight - 10];
|
||||
if (d3.select("#scaleBar").size()) {
|
||||
var bbox = d3.select("#scaleBar").node().getBBox();
|
||||
var tr = [scalePos[0] - bbox.width, scalePos[1] - bbox.height];
|
||||
var tr = [mapWidth - 10 - bbox.width, mapHeight - 10 - bbox.height];
|
||||
d3.select("#scaleBar").attr("transform", "translate(" + rn(tr[0]) + "," + rn(tr[1]) + ")");
|
||||
localStorage.removeItem("scaleBar");
|
||||
}
|
||||
$("#statusbar").css("top", mapHeight + 8);
|
||||
if ($("body").hasClass("fullscreen")) {$("#statusbar").css("top", mapHeight - 20);}
|
||||
}
|
||||
|
|
@ -5775,7 +5802,7 @@ function fantasyMap() {
|
|||
toggleOverlay();
|
||||
}
|
||||
}
|
||||
if (id === "mapWidthInput" || id === "mapHeightInput") {updateMapSize();}
|
||||
if (id === "mapWidthInput" || id === "mapHeightInput") {changeMapSize();}
|
||||
if (id === "sizeInput") {graphSize = sizeOutput.value = this.value;}
|
||||
if (id === "randomizeInput") {randomizeOutput.innerHTML = +this.value ? "✓" : "✕";}
|
||||
if (id === "manorsInput") {
|
||||
|
|
@ -5917,5 +5944,6 @@ function fantasyMap() {
|
|||
if (id === "styleTab") {$("#styleContent").show();}
|
||||
if (id === "optionsTab") {$("#optionsContent").show();}
|
||||
if (id === "customizeTab") {$("#customizeContent").show();}
|
||||
if (id === "aboutTab") {$("#aboutContent").show();}
|
||||
});
|
||||
}
|
||||