diff options
author | Markus Koch <markus@notsyncing.net> | 2020-04-14 18:10:19 +0200 |
---|---|---|
committer | Markus Koch <markus@notsyncing.net> | 2020-04-14 18:10:19 +0200 |
commit | be1dc049d63dccd22b60e64a2cf1f27a464b5ee4 (patch) | |
tree | 751a45b6f35850cab51d98be209222a8e5921ba0 | |
download | lifomapserver-be1dc049d63dccd22b60e64a2cf1f27a464b5ee4.tar.gz lifomapserver-be1dc049d63dccd22b60e64a2cf1f27a464b5ee4.tar.bz2 lifomapserver-be1dc049d63dccd22b60e64a2cf1f27a464b5ee4.zip |
Initial commit
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | index.html | 164 | ||||
-rwxr-xr-x | scripts/convert_maps.sh | 53 | ||||
-rw-r--r-- | scripts/geojson/cities.json | 14 | ||||
-rwxr-xr-x | scripts/geojson/fetch_cities.sh | 10 | ||||
-rwxr-xr-x | scripts/geojson/fetch_single.sh | 29 | ||||
-rw-r--r-- | tiles/index.php | 3 |
7 files changed, 274 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e22bc1f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +tiles/**/ diff --git a/index.html b/index.html new file mode 100644 index 0000000..1c4ecdd --- /dev/null +++ b/index.html @@ -0,0 +1,164 @@ +<!DOCTYPE html> +<html> +<head> + + <title>LinuxWorks Minetest Map (unofficial)</title> + + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/> + <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script> +</head> + <body style="position: absolute; padding: 0px; margin: 0px; width:100%; height:100%;"> + <div id="mapid" style="width: 100%; height: 100%;"></div> + <style> + .leaflet-tooltip.city-names { + background-color: transparent; + border: transparent; + box-shadow: none; + + font-weight: bold; + font-size: 14pt; + opacity:1.0; + color: white; + text-shadow: 0px 0px 5px black; + } + </style> + <script> + // Projection fix from: https://gis.stackexchange.com/questions/200865/leaflet-crs-simple-custom-scale + var factorx = 1/256 * 4; + var factory = factorx; + var originx = 7000; + var originy = 7000; + var zoom_level_real = 6; + + L.CRS.pr = L.extend({}, L.CRS.Simple, { + projection: L.Projection.LonLat, + transformation: new L.Transformation(factorx, factorx * originx, -factory, factory * originy), + + scale: function(zoom) { + return Math.pow(2, zoom); + }, + + zoom: function(scale) { + return Math.log(scale) / Math.LN2; + }, + + distance: function(latlng1, latlng2) { + var dx = latlng2.lng - latlng1.lng, + dy = latlng2.lat - latlng1.lat; + + return Math.sqrt(dx * dx + dy * dy); + }, + infinite: true + }); + + // Init map + var mymap = L.map('mapid', { + crs: L.CRS.pr + }).setView([0, 0], 6); + + var mapheight = 16384; + var mapwidth = mapheight; + var sw = mymap.unproject([0, 0], zoom_level_real); + var ne = mymap.unproject([mapwidth, mapheight], zoom_level_real); + var layerbounds = new L.LatLngBounds(sw, ne); + + function load_svg() { + var xhttp_ps = new XMLHttpRequest(); + xhttp_ps.onreadystatechange = function() { + if (this.readyState == 4) { + if (this.status == 200) { + var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + svgElement.setAttribute('xmlns', "http://www.w3.org/2000/svg"); + svgElement.setAttribute('viewBox', "0 0 16384 16384"); + svgElement.innerHTML = xhttp_ps.responseText; + var svgElementBounds = [ [ 85, -180 ], [ -77, 127 ] ]; + var overlayMaps = {"SVG (broken)": L.svgOverlay(svgElement, svgElementBounds)}; + L.control.layers({}, overlayMaps).addTo(mymap); + } else { + alert("Error: Could not load SVG map layer."); + } + } + }; + xhttp_ps.open("GET", "/manual2.svg", true); + xhttp_ps.send(); + } + + function load_satellite() { + var satellite = L.tileLayer('tiles/?id={id}&z={z}&x={x}&y={y}', { + maxZoom: 8, + maxNativeZoom: 6, + minNativeZoom: 0, + minZoom: 0, + noWrap: true, + attribution: 'Map data © <a href="https://wiki.linux-forks.de/mediawiki/index.php/Maps">Linux-Forks</a>, ' + + 'All rights reserved, ', + id: 'world-2020-04-09', + tileSize: 256, + zoomOffset: 0, + opacity: 1.0, + bounds: layerbounds + }); + var baseMaps = { + "Satellite": satellite + }; + var overlayMaps = {}; + // This is the only baseMap right now, so no need to show the selection dialog + // L.control.layers(baseMaps, overlayMaps).addTo(mymap); + satellite.addTo(mymap); + } + + function load_geojson() { + var xhttp_ps = new XMLHttpRequest(); + xhttp_ps.onreadystatechange = function() { + if (this.readyState == 4) { + if (this.status == 200) { + var geojson = L.geoJSON(JSON.parse(xhttp_ps.responseText), { + onEachFeature: function (feature, layer) { + label = String(feature.properties.name) + layer.bindPopup( + '<h1><a href="https://wiki.linux-forks.de/mediawiki/index.php/'+feature.properties.name+'">'+feature.properties.name+'</a> ('+feature.geometry.coordinates+')</h1>'+ + '<p><img style="width:100%" src="' + feature.properties.image + '"></p>' + + '<p>'+feature.properties.description+'</p>' + ); + layer.bindTooltip(label, {permanent: true, direction: "center", className: "city-names"}).openTooltip(); + }/*, + pointToLayer: function(feature,latlng){ + label = String(feature.properties.name) + return new L.CircleMarker(latlng, { + radius: 1, + }).bindTooltip(label, {permanent: true, direction: "center", opacity: 0.7}).openTooltip(); + }*/ + }).addTo(mymap); + L.control.layers({}, {"Cities": geojson}).addTo(mymap); + geojson.addTo(mymap); + } else { + alert("Error: Could not load geojson map layer (cities)."); + } + } + }; + xhttp_ps.open("GET", "./geojson/cities.json", true); + xhttp_ps.send(); + } + + load_satellite(); + //load_svg(); + load_geojson(); + + L.control.scale().addTo(mymap); + + var popup = L.popup(); + + function onMapClick(e) { + popup + .setLatLng(e.latlng) + .setContent("You clicked the map at " + e.latlng.toString()) + .openOn(mymap); + } + + mymap.on('click', onMapClick); + </script> + </body> +</html> diff --git a/scripts/convert_maps.sh b/scripts/convert_maps.sh new file mode 100755 index 0000000..32ef029 --- /dev/null +++ b/scripts/convert_maps.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Convert a huge .png file into smaller chunks for LeafletJS. +# +# Copyright (C) 2020 Markus Koch <markus@notsyncing.net> +# +# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +# You can obtain a copy of the license at https://mozilla.org/MPL/2.0/. + +# TODO: The width of the input png has to be a multiple of TILESIZE, otherwise bad things will happen. +# Workaround for now is to add white borders on the bottom and right: +# `convert $MAPFILE -extent ${crop}x${crop} -gravity NorthWest $MAPFILE.scaled.png` + +TILESIZE=256 +MAPNAME="world-2020-04-09" +MAPFILE="../$MAPNAME.png" + +width=`file "$MAPFILE" | sed -n "s/.* \([0-9]\+\) x \([0-9]\+\).*/\1/p"` +crop=$TILESIZE +zoom=0 + +while true; do + out="$MAPNAME/$zoom" + tempfile=$out/temp.png + + echo "" + echo "Generating maps for zoomlevel $zoom to $out..." + + mkdir -p $out; + + if [ ! -f "$tempfile" ]; then + if [ $crop -ge $width ]; then + echo " Reached max zoom at zoomlevel $zoom [using original zoom]" + cp $MAPFILE $tempfile + #convert $MAPFILE -extent ${crop}x${crop} -gravity NorthWest $tempfile + else + echo " Scaling map for zoomlevel $zoom" + convert $MAPFILE -resize ${crop}x${crop} $tempfile + fi + else + echo " Reusing existing scaled image" + fi + + echo " Generating tiles..." + convert $tempfile -crop ${TILESIZE}x${TILESIZE} +adjoin $out/%05d.png + + rm $tempfile + + if [ $crop -ge $width ]; then + break; + fi + crop=$(($crop * 2)) + zoom=$(($zoom + 1)) +done; diff --git a/scripts/geojson/cities.json b/scripts/geojson/cities.json new file mode 100644 index 0000000..d66fd89 --- /dev/null +++ b/scripts/geojson/cities.json @@ -0,0 +1,14 @@ +[ +{ "type": "Feature", "properties": { "name": "Anju Crossing", "amenity": "City", "description": "Anju Crossing is {{Player|Anju64}}'s settlement, located north of [[Spawn]].", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [-337, 403] } }, +{ "type": "Feature", "properties": { "name": "Crossroads", "amenity": "City", "description": "Crossroads is a city built by {{Player|Ywang}} and some contributors.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [1771, 991] } }, +{ "type": "Feature", "properties": { "name": "Fatamorgan City", "amenity": "City", "description": "Fatamorgan City is a hamlet situated south of [[Newton]].", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/Fatamorgan_aerial.jpeg/250px-Fatamorgan_aerial.jpeg" }, "geometry": { "type": "Point", "coordinates": [-742, -1421] } }, +{ "type": "Feature", "properties": { "name": "Neverbuild", "amenity": "City", "description": "Neverbuild is an city founded in the Lava/Savannah biome.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/Neverbuild_panorama.png/250px-Neverbuild_panorama.png" }, "geometry": { "type": "Point", "coordinates": [1350, 1940] } }, +{ "type": "Feature", "properties": { "name": "Origin", "amenity": "City", "description": "Origin is a coastal city built around the world origin of coordinates, managed by {{Player|Felfa}}.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [0, 0] } }, +{ "type": "Feature", "properties": { "name": "Personhood", "amenity": "City", "description": "Personhood is a major city in the northeast of the map and the previous beginner area.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/Personhood.png/250px-Personhood.png" }, "geometry": { "type": "Point", "coordinates": [1532, 2971] } }, +{ "type": "Feature", "properties": { "name": "Riverside", "amenity": "City", "description": "Riverside is a city located south of [[Spawn]].", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [-600, -787] } }, +{ "type": "Feature", "properties": { "name": "South Forest", "amenity": "City", "description": "South Forest is a former noob town managed by {{Player|dhausmig}}; it was the first noob town.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [285, -2045] } }, +{ "type": "Feature", "properties": { "name": "Spawn", "amenity": "City", "description": "Spawn is the capital of the Linux Works minetest server world.", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e//250px-" }, "geometry": { "type": "Point", "coordinates": [-675, -496] } }, +{ "type": "Feature", "properties": { "name": "Stallmangrad", "amenity": "City", "description": "", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/Stallmangrad_dec_2018.png/250px-Stallmangrad_dec_2018.png" }, "geometry": { "type": "Point", "coordinates": [1896, -2205] } }, +{ "type": "Feature", "properties": { "name": "Trisiston", "amenity": "City", "description": "", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/Trisiston_rathaus.png/250px-Trisiston_rathaus.png" }, "geometry": { "type": "Point", "coordinates": [-4250, -3130] } }, +{ "type": "Feature", "properties": { "name": "X Nihilo City", "amenity": "City", "description": "X Nihilo City is a ghost town in the far north of the map, at the end of the [[X Nihilo Mainline]].", "image": "https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/File:XNihilo.png/250px-File:XNihilo.png" }, "geometry": { "type": "Point", "coordinates": [2246, 5942] } }, +{}] diff --git a/scripts/geojson/fetch_cities.sh b/scripts/geojson/fetch_cities.sh new file mode 100755 index 0000000..16e81c1 --- /dev/null +++ b/scripts/geojson/fetch_cities.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +json=`curl 'https://wiki.linux-forks.de/mediawiki/api.php?action=query&format=json&list=categorymembers&cmtitle=Category:City&cmlimit=100'` +cities=`echo "$json" | json_reformat | sed -n 's/.*"title":\s*"\([^"]*\).*/\1/p' | tr ' ' '_' | tr '\n' ' '` + +echo "[" +for city in $cities; do + ./fetch_single.sh "$city" +done +echo "{}]" diff --git a/scripts/geojson/fetch_single.sh b/scripts/geojson/fetch_single.sh new file mode 100755 index 0000000..61ab79d --- /dev/null +++ b/scripts/geojson/fetch_single.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +json=`curl "https://wiki.linux-forks.de/mediawiki/api.php?action=query&prop=revisions&rvprop=content&format=json&titles=$1&rvsection=0&rvslots=main" | sed -s "s/\\\\\\\\n//g"` + +title=`echo $json | sed -n 's/.*"title":\s*"\([^"]\+\).*/\1/p'` +image=`echo "$json" | sed -n "s/.*image = \([^|]*\).*/\1/p"` + +coords=`echo "$json" | sed -n "s/.*coordinates = {{Co|\([^}]*\).*/\1/p"` +coord_x=`echo "$coords" | sed -n "s/\([^|]\+\).*/\1/p"` +coord_y=`echo "$coords" | sed -n "s/.*|\([^|]\+\).*/\1/p"` + +description=`echo $json | sed -n "s/.*coordinates.*[^']*'''\([^']*\)'''\([^\.]*\).*/\1\2./p" +` + +if [[ "$coord_x" != "" && "$coord_y" != "" ]]; then + echo "{\ + \"type\": \"Feature\",\ + \"properties\": {\ + \"name\": \"$title\",\ + \"amenity\": \"City\",\ + \"description\": \"$description\",\ + \"image\": \"https://wiki.linux-forks.de/mediawiki/images/thumb/0/0e/$image/250px-$image\"\ + },\ + \"geometry\": {\ + \"type\": \"Point\",\ + \"coordinates\": [$coord_x, $coord_y]\ + }\ + }," +fi diff --git a/tiles/index.php b/tiles/index.php new file mode 100644 index 0000000..62a2de0 --- /dev/null +++ b/tiles/index.php @@ -0,0 +1,3 @@ +<?php + +?> |