Spaces:
Sleeping
Sleeping
| 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() |