mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-16 17:31:24 +01:00
v1.0.11
This commit is contained in:
parent
0140eccd9f
commit
359b27ae2d
6 changed files with 146 additions and 619 deletions
|
|
@ -1,361 +0,0 @@
|
|||
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
|
||||
<qgis styleCategories="Symbology" version="3.8.2-Zanzibar">
|
||||
<renderer-v2 enableorderby="0" forceraster="0" attr="biome" symbollevels="0" type="categorizedSymbol">
|
||||
<categories>
|
||||
<category label="Marine" value="0" symbol="0" render="true"/>
|
||||
<category label="Hot Desert" value="1" symbol="1" render="true"/>
|
||||
<category label="Tundra" value="10" symbol="2" render="true"/>
|
||||
<category label="Glacier" value="11" symbol="3" render="true"/>
|
||||
<category label="Wetland" value="12" symbol="4" render="true"/>
|
||||
<category label="Cold Desert" value="2" symbol="5" render="true"/>
|
||||
<category label="Savanna" value="3" symbol="6" render="true"/>
|
||||
<category label="Grassland" value="4" symbol="7" render="true"/>
|
||||
<category label="Tropical Seasonal Forest" value="5" symbol="8" render="true"/>
|
||||
<category label="Temperate Deciduous Forest" value="6" symbol="9" render="true"/>
|
||||
<category label="Tropical Rainforest" value="7" symbol="10" render="true"/>
|
||||
<category label="Temperate Rainforest" value="8" symbol="11" render="true"/>
|
||||
<category label="Taiga" value="9" symbol="12" render="true"/>
|
||||
<category label="" value="" symbol="13" render="true"/>
|
||||
</categories>
|
||||
<symbols>
|
||||
<symbol name="0" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="31,120,180,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="31,120,180,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="1" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="254,239,124,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="254,239,124,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="10" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="44,156,102,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="44,156,102,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="11" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="81,155,119,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="81,155,119,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="12" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="203,227,81,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="203,227,81,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="13" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="58,205,107,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="35,35,35,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="2" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="210,220,60,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="210,220,60,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="3" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="247,252,255,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="247,252,255,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="4" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="135,143,97,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="135,143,97,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="5" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="244,228,104,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="244,228,104,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="6" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="253,191,111,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="253,191,111,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.36"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="7" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="178,223,138,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="178,223,138,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="8" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="31,114,13,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="31,114,13,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
<symbol name="9" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="51,160,44,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="51,160,44,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
</symbols>
|
||||
<source-symbol>
|
||||
<symbol name="0" alpha="1" clip_to_extent="1" force_rhr="0" type="fill">
|
||||
<layer locked="0" pass="0" enabled="1" class="SimpleFill">
|
||||
<prop k="border_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="color" v="229,182,54,255"/>
|
||||
<prop k="joinstyle" v="bevel"/>
|
||||
<prop k="offset" v="0,0"/>
|
||||
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
|
||||
<prop k="offset_unit" v="MM"/>
|
||||
<prop k="outline_color" v="35,35,35,255"/>
|
||||
<prop k="outline_style" v="solid"/>
|
||||
<prop k="outline_width" v="0.26"/>
|
||||
<prop k="outline_width_unit" v="MM"/>
|
||||
<prop k="style" v="solid"/>
|
||||
<data_defined_properties>
|
||||
<Option type="Map">
|
||||
<Option value="" name="name" type="QString"/>
|
||||
<Option name="properties"/>
|
||||
<Option value="collection" name="type" type="QString"/>
|
||||
</Option>
|
||||
</data_defined_properties>
|
||||
</layer>
|
||||
</symbol>
|
||||
</source-symbol>
|
||||
<colorramp name="[source]" type="randomcolors"/>
|
||||
<rotation/>
|
||||
<sizescale/>
|
||||
</renderer-v2>
|
||||
<blendMode>0</blendMode>
|
||||
<featureBlendMode>0</featureBlendMode>
|
||||
<layerGeometryType>2</layerGeometryType>
|
||||
</qgis>
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
<?php
|
||||
|
||||
$max_deviation = 0.2;
|
||||
$max_abs = 0.02;
|
||||
$min_distance = 0.1;
|
||||
|
||||
$iterations = 4;
|
||||
|
||||
if ($argc < 2 ) {
|
||||
exit( "Usage: add_random_points.php <filename.json>\n" );
|
||||
}
|
||||
|
||||
// FIXME: This script created a few cases of self-intersection that must be fixed manually
|
||||
// in QGIS: Vector -> Geometry Tools -> Check Validity
|
||||
|
||||
$cells = json_decode(file_get_contents($argv[1]), true);
|
||||
|
||||
|
||||
for ($i=0; $i<$iterations; $i++) {
|
||||
$lookup = array();
|
||||
|
||||
foreach ($cells['features'] as &$cell) {
|
||||
$points = $cell['geometry']['coordinates'][0];
|
||||
|
||||
$prev = null;
|
||||
$newpoints = array();
|
||||
|
||||
foreach ($points as $point) {
|
||||
if ($prev) {
|
||||
$distance = sqrt(pow($prev[0] - $point[0], 2) + pow($prev[1] - $point[1], 2));
|
||||
if ($distance == 0) continue;
|
||||
|
||||
if ($distance > $min_distance) {
|
||||
$id_a = $prev[0]."-".$prev[1];
|
||||
$id_b = $point[0]."-".$point[1];
|
||||
|
||||
if (isset($lookup[$id_a."--".$id_b])) {
|
||||
$newpoints[] = $lookup[$id_a."--".$id_b];
|
||||
} elseif (isset($lookup[$id_b."--".$id_a])) {
|
||||
$newpoints[] = $lookup[$id_b."--".$id_a];
|
||||
} else {
|
||||
$x = ($prev[0]+$point[0])/2.0;
|
||||
$y = ($prev[1]+$point[1])/2.0;
|
||||
|
||||
$r = mt_rand() / mt_getrandmax(); // 0-1
|
||||
$r = ($r+1) / 2; // 0.5 - 1.0
|
||||
|
||||
// if we define dx=x2-x1 and dy=y2-y1, then the normals are (-dy, dx) and (dy, -dx).
|
||||
$dx = $point[0] - $x;
|
||||
$dy = $point[1] - $y;
|
||||
|
||||
if (mt_rand() / mt_getrandmax() < 0.5) {
|
||||
$x_off = -$dy;
|
||||
$y_off = $dx;
|
||||
} else {
|
||||
$x_off = $dy;
|
||||
$y_off = -$dx;
|
||||
}
|
||||
|
||||
$x_off *= $r * $max_deviation;
|
||||
$x_off = max(min($x_off, $max_abs), $max_abs*-1);
|
||||
|
||||
$y_off *= $r * $max_deviation;
|
||||
$y_off = max(min($y_off, $max_abs), $max_abs*-1);
|
||||
|
||||
$p = array($x + $x_off, $y + $y_off);
|
||||
$lookup[$id_a."--".$id_b] = $p;
|
||||
$newpoints[] = $p;
|
||||
}
|
||||
}
|
||||
}
|
||||
$newpoints[] = $point;
|
||||
$prev = $point;
|
||||
}
|
||||
$cell['geometry']['coordinates'][0] = $newpoints;
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($cells, JSON_PRETTY_PRINT);
|
||||
|
||||
?>
|
||||
|
|
@ -1838,7 +1838,7 @@
|
|||
<div id="saveMap" data-tip="Download the map as fully functional .map file to your machine. Shortcut: Ctrl + M">.map</div>
|
||||
<div id="saveSVG" data-tip="Download the map as vector image (open in browser or Inkscape). Shortcut: Ctrl + S">.svg</div>
|
||||
<div id="savePNG" data-tip="Download visible part of the map as .png image. Shortcut: Ctrl + P">.png</div>
|
||||
<div id="saveGeo" data-tip="Download map data as GeoJSON (for use in GIS tools such as QGIS)">.json</div>
|
||||
<div id="saveGeo" data-tip="Download map data in GeoJSON format. Shortcut: Ctrl + G">.json</div>
|
||||
<div id="quickSave" data-tip="Save map to browser storage. Shortcut: F6">storage</div>
|
||||
<!-- <div id="saveDropbox" data-tip="Save fully functional .map file to Dropbox. Shortcut: Ctrl + B">Dropbox</div> -->
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,176 +1,6 @@
|
|||
// Functions to save and load the map
|
||||
"use strict";
|
||||
|
||||
// download map data as GeoJSON
|
||||
function saveGeoJSON() {
|
||||
saveGeoJSON_Cells();
|
||||
saveGeoJSON_Roads();
|
||||
saveGeoJSON_Rivers();
|
||||
}
|
||||
|
||||
function saveGeoJSON_Roads() {
|
||||
// this is work-in-progress
|
||||
roads = routes.select("#roads");
|
||||
trails = routes.select("#trails");
|
||||
searoutes = routes.select("#searoutes");
|
||||
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
routes._groups[0][0].childNodes.forEach(n => {
|
||||
//console.log(n.id);
|
||||
n.childNodes.forEach(r => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRoadPoints(r));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+r.id+"\",\n";
|
||||
data += " \"type\": \""+n.id+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_routes_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function saveGeoJSON_Rivers() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
rivers._groups[0][0].childNodes.forEach(n => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRiverPoints(n));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+n.id+"\",\n";
|
||||
data += " \"width\": \""+n.dataset.width+"\",\n";
|
||||
data += " \"increment\": \""+n.dataset.increment+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_rivers_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function getRoadPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength();
|
||||
const increment = l / Math.ceil(l / 2);
|
||||
for (let i=0; i <= l; i += increment) {
|
||||
const p = node.getPointAtLength(i);
|
||||
|
||||
let x = mapCoordinates.lonW + (p.x / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (p.y / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function getRiverPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength() / 2; // half-length
|
||||
const increment = 0.25; // defines density of points
|
||||
for (let i=l, c=i; i >= 0; i -= increment, c += increment) {
|
||||
const p1 = node.getPointAtLength(i);
|
||||
const p2 = node.getPointAtLength(c);
|
||||
|
||||
let x = mapCoordinates.lonW + (((p1.x+p2.x)/2) / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (((p1.y+p2.y)/2) / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
function saveGeoJSON_Cells() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
const cells = pack.cells;
|
||||
const v = pack.vertices;
|
||||
|
||||
/*
|
||||
my guesses on the cells structure:
|
||||
|
||||
cells.h = height
|
||||
cells.p = coordinates of center point (of the voronoi cell)
|
||||
cells.pop = population
|
||||
|
||||
// from voronoi.js:
|
||||
const cells = {v: [], c: [], b: []}; // voronoi cells: v = cell vertices, c = adjacent cells, b = near-border cell
|
||||
const vertices = {p: [], v: [], c: []}; // cells vertices: p = vertex coordinates, v = neighboring vertices, c = adjacent cells
|
||||
|
||||
|
||||
*/
|
||||
|
||||
cells.i.forEach(i => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [[";
|
||||
cells.v[i].forEach(n => {
|
||||
let x = mapCoordinates.lonW + (v.p[n][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[n][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"],";
|
||||
});
|
||||
// close the ring
|
||||
let x = mapCoordinates.lonW + (v.p[cells.v[i][0]][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[cells.v[i][0]][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"]";
|
||||
|
||||
data += "]] },\n \"properties\": {\n";
|
||||
|
||||
let height = parseInt(getFriendlyHeight(cells.h[i]));
|
||||
|
||||
data += " \"id\": \""+i+"\",\n";
|
||||
data += " \"height\": \""+height+"\",\n";
|
||||
data += " \"biome\": \""+cells.biome[i]+"\",\n";
|
||||
data += " \"population\": \""+cells.pop[i]+"\",\n";
|
||||
data += " \"state\": \""+cells.state[i]+"\",\n";
|
||||
data += " \"province\": \""+cells.province[i]+"\",\n";
|
||||
data += " \"culture\": \""+cells.culture[i]+"\",\n";
|
||||
data += " \"religion\": \""+cells.religion[i]+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
|
||||
/*
|
||||
cells.i.forEach(i => {
|
||||
let x = (cells.p[i][0] / graphWidth) * mapCoordinates.lonT + mapCoordinates.lonW;
|
||||
let y = mapCoordinates.latN - (cells.p[i][1] / graphHeight) * mapCoordinates.lonT; // inverted in QGIS otherwise
|
||||
let height = parseInt(getFriendlyHeight(cells.h[i]));
|
||||
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Point\", \"coordinates\": ["+x+", "+y+", "+height+"] },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+i+"\",\n";
|
||||
data += " \"biome\": \""+cells.biome[i]+"\",\n";
|
||||
data += " \"height\": \""+cells.h[i]+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
*/
|
||||
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_cells_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
// download map as SVG or PNG file
|
||||
function saveAsImage(type) {
|
||||
console.time("saveAsImage");
|
||||
|
|
@ -387,6 +217,146 @@ async function saveMap() {
|
|||
window.setTimeout(() => window.URL.revokeObjectURL(URL), 5000);
|
||||
}
|
||||
|
||||
// download map data as GeoJSON
|
||||
function saveGeoJSON() {
|
||||
alertMessage.innerHTML = `You can export map data in GeoJSON format used in GIS tools such as QGIS.
|
||||
Check out <a href="https://github.com/Azgaar/Fantasy-Map-Generator/wiki/GIS-data-export" target="_blank">wiki-page</a> for guidance`;
|
||||
|
||||
$("#alert").dialog({title: "GIS data export", resizable: false, width: 320, position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
Cells: saveGeoJSON_Cells,
|
||||
Routes: saveGeoJSON_Roads,
|
||||
Rivers: saveGeoJSON_Rivers,
|
||||
Close: function() {$(this).dialog("close");}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveGeoJSON_Roads() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
routes._groups[0][0].childNodes.forEach(n => {
|
||||
n.childNodes.forEach(r => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRoadPoints(r));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+r.id+"\",\n";
|
||||
data += " \"type\": \""+n.id+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_routes_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function saveGeoJSON_Rivers() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
|
||||
rivers._groups[0][0].childNodes.forEach(n => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"LineString\", \"coordinates\": ";
|
||||
data += JSON.stringify(getRiverPoints(n));
|
||||
data += " },\n \"properties\": {\n";
|
||||
data += " \"id\": \""+n.id+"\",\n";
|
||||
data += " \"width\": \""+n.dataset.width+"\",\n";
|
||||
data += " \"increment\": \""+n.dataset.increment+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_rivers_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function getRoadPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength();
|
||||
const increment = l / Math.ceil(l / 2);
|
||||
for (let i=0; i <= l; i += increment) {
|
||||
const p = node.getPointAtLength(i);
|
||||
|
||||
let x = mapCoordinates.lonW + (p.x / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (p.y / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
function getRiverPoints(node) {
|
||||
let points = [];
|
||||
const l = node.getTotalLength() / 2; // half-length
|
||||
const increment = 0.25; // defines density of points
|
||||
for (let i=l, c=i; i >= 0; i -= increment, c += increment) {
|
||||
const p1 = node.getPointAtLength(i);
|
||||
const p2 = node.getPointAtLength(c);
|
||||
|
||||
let x = mapCoordinates.lonW + (((p1.x+p2.x)/2) / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (((p1.y+p2.y)/2) / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
points.push([x,y]);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
|
||||
function saveGeoJSON_Cells() {
|
||||
let data = "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
const cells = pack.cells, v = pack.vertices;
|
||||
|
||||
cells.i.forEach(i => {
|
||||
data += "{\n \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\", \"coordinates\": [[";
|
||||
cells.v[i].forEach(n => {
|
||||
let x = mapCoordinates.lonW + (v.p[n][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[n][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"],";
|
||||
});
|
||||
// close the ring
|
||||
let x = mapCoordinates.lonW + (v.p[cells.v[i][0]][0] / graphWidth) * mapCoordinates.lonT;
|
||||
let y = mapCoordinates.latN - (v.p[cells.v[i][0]][1] / graphHeight) * mapCoordinates.latT; // this is inverted in QGIS otherwise
|
||||
data += "["+x+","+y+"]";
|
||||
data += "]] },\n \"properties\": {\n";
|
||||
|
||||
let height = parseInt(getFriendlyHeight(cells.h[i]));
|
||||
|
||||
data += " \"id\": \""+i+"\",\n";
|
||||
data += " \"height\": \""+height+"\",\n";
|
||||
data += " \"biome\": \""+cells.biome[i]+"\",\n";
|
||||
data += " \"population\": \""+cells.pop[i]+"\",\n";
|
||||
data += " \"state\": \""+cells.state[i]+"\",\n";
|
||||
data += " \"province\": \""+cells.province[i]+"\",\n";
|
||||
data += " \"culture\": \""+cells.culture[i]+"\",\n";
|
||||
data += " \"religion\": \""+cells.religion[i]+"\"\n";
|
||||
data +=" }\n},\n";
|
||||
});
|
||||
|
||||
data = data.substring(0, data.length - 2)+"\n"; // remove trailing comma
|
||||
data += "]}";
|
||||
|
||||
const dataBlob = new Blob([data], {type: "application/json"});
|
||||
const url = window.URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement("a");
|
||||
document.body.appendChild(link);
|
||||
link.download = "fmg_cells_" + Date.now() + ".geojson";
|
||||
link.href = url;
|
||||
link.click();
|
||||
window.setTimeout(function() {window.URL.revokeObjectURL(url);}, 2000);
|
||||
}
|
||||
|
||||
function uploadFile(file, callback) {
|
||||
uploadFile.timeStart = performance.now();
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,7 @@ document.addEventListener("keydown", function(event) {
|
|||
else if (ctrl && key === 80) saveAsImage("png"); // Ctrl + "P" to save as PNG
|
||||
else if (ctrl && key === 83) saveAsImage("svg"); // Ctrl + "S" to save as SVG
|
||||
else if (ctrl && key === 77) saveMap(); // Ctrl + "M" to save MAP file
|
||||
else if (ctrl && key === 71) saveGeoJSON(); // Ctrl + "G" to save as GeoJSON
|
||||
else if (ctrl && key === 85) mapToLoad.click(); // Ctrl + "U" to load MAP from URL
|
||||
else if (ctrl && key === 76) mapToLoad.click(); // Ctrl + "L" to load MAP from local file
|
||||
else if (ctrl && key === 81) toggleSaveReminder(); // Ctrl + "Q" to toggle save reminder
|
||||
|
|
|
|||
|
|
@ -1027,12 +1027,10 @@ function toggleSavePane() {
|
|||
<br>Please check browser settings and turn off adBlocker if it is enabled`;
|
||||
|
||||
$("#alert").dialog({title: "File saver", resizable: false, position: {my: "center", at: "center", of: "svg"},
|
||||
buttons: {
|
||||
OK: function() {
|
||||
localStorage.setItem("dns_allow_popup_message", true);
|
||||
$(this).dialog("close");
|
||||
}
|
||||
}
|
||||
buttons: {OK: function() {
|
||||
localStorage.setItem("dns_allow_popup_message", true);
|
||||
$(this).dialog("close");
|
||||
}}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue