VertGis / pages /mipmap.py
Vertdure's picture
Create mipmap.py
5ab6160 verified
raw
history blame
8.97 kB
import streamlit as st
import folium
from streamlit_folium import folium_static
from folium.plugins import Draw, MousePosition
from branca.element import Template, MacroElement
# Configuration de la page Streamlit
st.set_page_config(layout="wide", page_title="SwissScape Advanced")
class AdvancedMapControl(MacroElement):
def __init__(self):
super(AdvancedMapControl, self).__init__()
self._template = Template("""
{% macro script(this, kwargs) %}
var advancedMapControl = L.control({position: 'topright'});
advancedMapControl.onAdd = function (map) {
var div = L.DomUtil.create('div', 'advanced-map-control');
div.innerHTML = `
<input type="number" id="block-width" value="0.4" step="0.01" min="0.01"> Largeur du bloc (m)
<input type="number" id="block-height" value="0.4" step="0.01" min="0.01"> Hauteur du bloc (m)
<input type="number" id="scale" value="1000" min="1" step="100"> Échelle
<button id="calculate-blocks">Calculer Blocs</button>
<div id="block-result"></div>
<button id="export-geojson">Exporter GeoJSON</button>
`;
L.DomEvent.disableClickPropagation(div);
return div;
};
advancedMapControl.addTo({{ this._parent.get_name() }});
var rectangle;
var grid;
var blocks = [];
document.getElementById('calculate-blocks').addEventListener('click', function() {
var drawnItems = {{ this._parent.get_name() }}.pm.getGeomanDrawLayers();
if (drawnItems.getLayers().length === 0) {
alert("Veuillez d'abord dessiner une bbox sur la carte.");
return;
}
rectangle = drawnItems.getLayers()[0];
var bounds = rectangle.getBounds();
var scale = parseInt(document.getElementById('scale').value);
var blockWidth = parseFloat(document.getElementById('block-width').value) * scale / 100; // Convert to meters at scale
var blockHeight = parseFloat(document.getElementById('block-height').value) * scale / 100; // Convert to meters at scale
var widthMeters = (bounds.getEast() - bounds.getWest()) * 111320 * Math.cos(bounds.getCenter().lat * Math.PI / 180);
var heightMeters = (bounds.getNorth() - bounds.getSouth()) * 111320;
var blocksX = Math.ceil(widthMeters / blockWidth);
var blocksY = Math.ceil(heightMeters / blockHeight);
var result = `Blocs nécessaires : ${blocksX} x ${blocksY} (${blocksX * blocksY} au total)`;
document.getElementById('block-result').innerText = result;
if (grid) {
{{ this._parent.get_name() }}.removeLayer(grid);
}
grid = L.layerGroup().addTo({{ this._parent.get_name() }});
blocks = [];
var latStep = blockHeight / 111320;
var lngStep = blockWidth / (111320 * Math.cos(bounds.getCenter().lat * Math.PI / 180));
for (var i = 0; i < blocksY; i++) {
for (var j = 0; j < blocksX; j++) {
var blockSouth = bounds.getSouth() + i * latStep;
var blockWest = bounds.getWest() + j * lngStep;
var blockNorth = Math.min(blockSouth + latStep, bounds.getNorth());
var blockEast = Math.min(blockWest + lngStep, bounds.getEast());
L.rectangle([[blockSouth, blockWest], [blockNorth, blockEast]], {color: "#ff7800", weight: 1, fill: false}).addTo(grid);
blocks.push([[blockWest, blockSouth], [blockEast, blockNorth]]);
}
}
});
document.getElementById('export-geojson').addEventListener('click', function() {
if (rectangle && blocks.length > 0) {
var bounds = rectangle.getBounds();
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"blockWidth": parseFloat(document.getElementById('block-width').value),
"blockHeight": parseFloat(document.getElementById('block-height').value),
"scale": parseInt(document.getElementById('scale').value)
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[bounds.getWest(), bounds.getSouth()],
[bounds.getEast(), bounds.getSouth()],
[bounds.getEast(), bounds.getNorth()],
[bounds.getWest(), bounds.getNorth()],
[bounds.getWest(), bounds.getSouth()]
]]
}
}]
};
blocks.forEach(function(block, index) {
geojson.features.push({
"type": "Feature",
"properties": {
"blockIndex": index
},
"geometry": {
"type": "Polygon",
"coordinates": [[
[block[0][0], block[0][1]],
[block[1][0], block[0][1]],
[block[1][0], block[1][1]],
[block[0][0], block[1][1]],
[block[0][0], block[0][1]]
]]
}
});
});
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(geojson));
var downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", "export.geojson");
document.body.appendChild(downloadAnchorNode);
downloadAnchorNode.click();
downloadAnchorNode.remove();
} else {
alert("Veuillez d'abord calculer les blocs.");
}
});
{% endmacro %}
""")
def main():
st.title("SwissScape Advanced")
st.markdown("""
SwissScape Advanced est un outil pour les paysagistes permettant de générer des fonds de plans personnalisés.
Instructions :
1. Utilisez l'outil de dessin (en haut à gauche de la carte) pour dessiner une bbox sur la carte.
2. Spécifiez la largeur et la hauteur du bloc d'impression en mètres.
3. Définissez l'échelle souhaitée.
4. Cliquez sur "Calculer Blocs" pour voir combien de blocs d'impression sont nécessaires.
5. Utilisez "Exporter GeoJSON" pour télécharger les données de la bbox et des blocs.
""")
# Création de la carte Folium
m = folium.Map(location=[46.8182, 8.2275], zoom_start=8)
# Ajout du fond de carte swisstopo
folium.TileLayer(
tiles="https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/current/3857/{z}/{x}/{y}.jpeg",
attr="© swisstopo",
name="swisstopo",
overlay=False,
control=True
).add_to(m)
# Ajout du contrôle de dessin
draw = Draw(
draw_options={
'polyline': False,
'polygon': False,
'circle': False,
'marker': False,
'circlemarker': False,
'rectangle': True,
},
edit_options={'edit': False}
)
m.add_child(draw)
# Ajout du contrôle de carte avancé
m.add_child(AdvancedMapControl())
# Ajout des coordonnées de la souris
formatter = "function(num) {return L.Util.formatNum(num, 5);};"
MousePosition(
position="bottomleft",
separator=" | ",
empty_string="",
lng_first=True,
num_digits=20,
prefix="Coordonnées:",
lat_formatter=formatter,
lng_formatter=formatter,
).add_to(m)
# Affichage de la carte
folium_static(m, width=1000, height=600)
if __name__ == "__main__":
main()