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 = ` Largeur du bloc (m) Hauteur du bloc (m) Échelle
`; 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()