class MapDrawingManager { constructor(mapSelector) { this.mapSelector = mapSelector; this.hasUnsavedChanges = false; this.hasMultiPolygon = false; } setupDrawControls() { const drawOptions = { position: "topright", draw: { polyline: false, circlemarker: false, marker: false, circle: { shapeOptions: { color: "#00394D", fillColor: "#00394D", fillOpacity: 0.2, weight: 2, }, showRadius: true, metric: true, }, rectangle: { shapeOptions: { color: "#00394D", fillColor: "#00394D", fillOpacity: 0.2, weight: 2, }, }, polygon: { allowIntersection: false, drawError: { color: "#f03e3e", message: "Erreur: Les polygones ne peuvent pas s'intersecter!", }, shapeOptions: { color: "#00394D", fillColor: "#00394D", fillOpacity: 0.2, weight: 2, }, }, }, edit: { featureGroup: this.mapSelector.drawnItems, remove: true, poly: { allowIntersection: false, }, edit: { selectedPathOptions: { maintainColor: true, fillOpacity: 0.3, } } }, }; this.mapSelector.drawControl = new L.Control.Draw(drawOptions); this.mapSelector.map.addControl(this.mapSelector.drawControl); } disableEditingForMultiPolygon(geoJSON) { if (geoJSON.geometry && geoJSON.geometry.type === 'MultiPolygon') { this.hasMultiPolygon = true; if (this.mapSelector.drawControl) { const currentOptions = this.mapSelector.drawControl.options; const newOptions = { ...currentOptions, edit: { ...currentOptions.edit, edit: false } }; this.mapSelector.map.removeControl(this.mapSelector.drawControl); this.mapSelector.drawControl = new L.Control.Draw(newOptions); this.mapSelector.map.addControl(this.mapSelector.drawControl); this.replaceDrawIcons(); } } } updateMultiPolygonState() { const hasMultiPolygon = this.mapSelector.selectedAreas.some(area => area.geometry && area.geometry.type === 'MultiPolygon' ); if (!hasMultiPolygon && this.hasMultiPolygon) { this.hasMultiPolygon = false; if (this.mapSelector.drawControl) { const currentOptions = this.mapSelector.drawControl.options; const newOptions = { ...currentOptions, edit: { ...currentOptions.edit, edit: true } }; this.mapSelector.map.removeControl(this.mapSelector.drawControl); this.mapSelector.drawControl = new L.Control.Draw(newOptions); this.mapSelector.map.addControl(this.mapSelector.drawControl); this.replaceDrawIcons(); } } } setupMapEvents() { this.mapSelector.map.on(L.Draw.Event.CREATED, this._handleDrawCreated.bind(this)); this.mapSelector.map.on(L.Draw.Event.DELETED, this._handleDrawDeleted.bind(this)); this.mapSelector.map.on('draw:edited', (e) => { const layers = e.layers; const updatedAreas = []; this.mapSelector.drawnItems.eachLayer((layer) => { if (layer instanceof L.Circle) { const center = layer.getLatLng(); const radius = layer.getRadius(); updatedAreas.push({ type: 'Feature', geometry: { type: 'Point', coordinates: [center.lng, center.lat] }, properties: { type: 'circle', radius: radius } }); } else if (layer instanceof L.Polygon || layer instanceof L.Rectangle) { const geoJSON = layer.toGeoJSON(); const existingArea = this.mapSelector.selectedAreas.find(area => area.geometry.type === 'Polygon' && area.properties?.name === geoJSON.properties?.name ); if (existingArea) { updatedAreas.push({ ...existingArea, geometry: geoJSON.geometry }); } else { updatedAreas.push(geoJSON); } } }); this.mapSelector.selectedAreas = updatedAreas; this.mapSelector.uiManager.updateSelectedAreasList(); }); this.mapSelector.map.on('editable:editing', () => { this.hasUnsavedChanges = true; }); this.mapSelector.map.on('draw:editstart', () => { this.mapSelector.isEditing = true; const confirmBtn = document.querySelector('#confirmSelectionBtn'); const closeBtn = document.querySelector('.mapSelectorCloseBtn'); if (confirmBtn) confirmBtn.classList.add('disabled'); if (closeBtn) closeBtn.classList.add('disabled'); }); this.mapSelector.map.on('draw:editstop', () => { this.mapSelector.isEditing = false; const confirmBtn = document.querySelector('#confirmSelectionBtn'); const closeBtn = document.querySelector('.mapSelectorCloseBtn'); if (confirmBtn) confirmBtn.classList.remove('disabled'); if (closeBtn) closeBtn.classList.remove('disabled'); }); } replaceDrawIcons() { const iconMappings = { '.leaflet-draw-draw-polygon': '', '.leaflet-draw-draw-rectangle': '', '.leaflet-draw-draw-circle': '', '.leaflet-draw-edit-edit': '', '.leaflet-draw-edit-remove': '' }; Object.entries(iconMappings).forEach(([selector, html]) => { const element = document.querySelector(selector); if (element) element.innerHTML = html; }); this.mapSelector.map.on(L.Draw.Event.DRAWSTART, () => { setTimeout(() => this.replaceActionIcons(), 100); }); } replaceActionIcons() { const actionMappings = { 'Cancel': ' Annuler', 'Finish': ' Terminer', 'Delete last point': ' Supprimer dernier point' }; const actionButtons = document.querySelectorAll('.leaflet-draw-actions a'); actionButtons.forEach(btn => { const text = btn.textContent.trim(); if (actionMappings[text]) { btn.innerHTML = actionMappings[text]; } }); } _handleDrawCreated(event) { const layer = event.layer; const type = event.layerType; let geoJSON = layer.toGeoJSON(); if (type === 'circle') { this._setupCircleProperties(layer, geoJSON); } this.mapSelector.drawnItems.addLayer(layer); this.mapSelector.selectedAreas.push(geoJSON); this.mapSelector.uiManager.updateSelectedAreasList(); } _setupCircleProperties(layer, geoJSON) { const radius = layer.getRadius(); geoJSON.properties = geoJSON.properties || {}; geoJSON.properties.radius = radius; geoJSON.properties.type = 'circle'; const radiusText = this.mapSelector.geoJSONHandler._formatRadiusText(radius); layer.bindPopup(`Rayon: ${radiusText}`); layer.on('edit', (e) => this._handleCircleEdit(e, geoJSON)); } _handleCircleEdit(e, geoJSON) { const newRadius = e.target.getRadius(); const index = this.mapSelector.selectedAreas.findIndex(area => area.geometry.coordinates[0] === geoJSON.geometry.coordinates[0] && area.geometry.coordinates[1] === geoJSON.geometry.coordinates[1] ); if (index >= 0) { this.mapSelector.selectedAreas[index].properties.radius = newRadius; } const newRadiusText = this.mapSelector.geoJSONHandler._formatRadiusText(newRadius); e.target.setPopupContent(`Rayon: ${newRadiusText}`); this.mapSelector.uiManager.updateSelectedAreasList(); } _handleDrawDeleted(event) { const layers = event.layers; layers.eachLayer((layer) => { const geoJSON = layer.toGeoJSON(); this.mapSelector.selectedAreas = this.mapSelector.selectedAreas.filter(area => JSON.stringify(area) !== JSON.stringify(geoJSON) ); }); this.updateMultiPolygonState(); this.mapSelector.uiManager.updateSelectedAreasList(); } _handleDrawEdited(event) { const layers = event.layers; layers.eachLayer((layer) => { const geoJSON = layer.toGeoJSON(); if (layer instanceof L.Circle) { this._updateCircleProperties(layer, geoJSON); } else { this._updatePolygonProperties(geoJSON); } }); this.mapSelector.uiManager.updateSelectedAreasList(); } _updateCircleProperties(layer, geoJSON) { const radius = layer.getRadius(); const center = layer.getLatLng(); geoJSON.properties = geoJSON.properties || {}; geoJSON.properties.radius = radius; geoJSON.properties.type = 'circle'; const newRadiusText = this.mapSelector.geoJSONHandler._formatRadiusText(radius); const areaInSqMeters = Math.PI * Math.pow(radius, 2); const areaText = this.mapSelector.geoJSONHandler._formatAreaText(areaInSqMeters); layer.setPopupContent(`Rayon: ${newRadiusText}
Surface: ${areaText}`); for (let i = 0; i < this.mapSelector.selectedAreas.length; i++) { const area = this.mapSelector.selectedAreas[i]; if (this._isMatchingCircle(area, center)) { this.mapSelector.selectedAreas[i].properties.radius = radius; this.mapSelector.selectedAreas[i].geometry.coordinates = [center.lng, center.lat]; break; } } } _isMatchingCircle(area, center) { if ((area.geometry.type === 'Point' && area.properties && (area.properties.type === 'circle' || area.properties.radius))) { const areaLat = area.geometry.coordinates[1]; const areaLng = area.geometry.coordinates[0]; return Math.abs(areaLat - center.lat) < 0.1 && Math.abs(areaLng - center.lng) < 0.1; } return false; } _updatePolygonProperties(geoJSON) { for (let i = 0; i < this.mapSelector.selectedAreas.length; i++) { const area = this.mapSelector.selectedAreas[i]; if (area.geometry.type === geoJSON.geometry.type) { this.mapSelector.selectedAreas[i].geometry = geoJSON.geometry; break; } } } // ... autres méthodes de gestion du dessin }