diff --git a/docs/MAP_SYSTEM_UPDATE_PLAN.md b/docs/MAP_SYSTEM_UPDATE_PLAN.md new file mode 100644 index 0000000..b01093c --- /dev/null +++ b/docs/MAP_SYSTEM_UPDATE_PLAN.md @@ -0,0 +1,788 @@ +# Map System - Comprehensive Update & Fix Plan + +Based on layer testing results from LAYER_NOTES.md +Date: January 16, 2026 + +--- + +## Executive Summary + +**Current Status:** +- โœ… **6/7 base layers working** (1 broken: Polish Orthophoto High Resolution) +- โš ๏ธ **2/9 overlay layers working** (2 very slow, 5 not tested, 2 broken) +- ๐ŸŽฏ **Priority:** Fix broken layers, optimize slow WMS services, remove LP-Portal layers + +**Key Issues Identified:** +1. Polish Orthophoto High Resolution completely broken +2. Polish Cadastral Data servers extremely slow (both servers) +3. Polish Spatial Planning layer not working +4. LP-Portal layers not tested/documented - likely region-specific +5. No caching or performance optimization for WMS layers +6. Missing zoom level restrictions causing tile request failures + +--- + +## Phase 1: Critical Fixes (Week 1) + +### 1.1 Fix Polish Orthophoto High Resolution +**Issue:** Doesn't load at all +**Root Cause:** Likely incorrect WMTS parameters or service endpoint change + +**Action Plan:** +1. Test GetCapabilities response: + ```bash + curl "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/HighResolution?Service=WMTS&Request=GetCapabilities" + ``` +2. Compare with Standard Resolution working configuration +3. Check for: + - Different tile matrix sets + - Different available zoom levels + - Format differences (jpeg vs png) + - Authentication requirements + +**Implementation:** +```javascript +// Test if service requires different parameters +{ + name: "๐Ÿ‡ต๐Ÿ‡ฑ Polish Orthophoto (High Resolution)", + url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/HighResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=EPSG:3857&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image/jpeg", + maxZoom: 19, // May need adjustment based on GetCapabilities + minZoom: 15, // High-res often only available at higher zoom +} +``` + +**Success Criteria:** Layer loads tiles without errors + +--- + +### 1.2 Fix Polish Spatial Planning Layer +**Issue:** Doesn't work or extremely slow +**Service:** `https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego` + +**Action Plan:** +1. Verify service is still active via GetCapabilities +2. Test with simplified layer list (may be requesting too many layers) +3. Check if service moved to new endpoint +4. Test with different WMS versions (1.1.1 vs 1.3.0) + +**Implementation:** +```javascript +// Simplified layer request +{ + name: "๐Ÿ—๏ธ Polish Spatial Planning", + type: "wms", + url: "https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego", + params: { + layers: "raster", // Start with just raster + format: "image/png", + transparent: true, + version: "1.3.0", + }, + maxZoom: 18, // Limit to prevent overload +} +``` + +**Success Criteria:** Layer loads or is removed if permanently unavailable + +--- + +### 1.3 Optimize Polish Cadastral Data Performance +**Issue:** Both servers very slow, currently only work up to zoom 18 +**Impact:** Core functionality for land surveying projects + +**Action Plan:** +1. Implement tile loading indicators +2. Add request debouncing +3. Consider caching strategy +4. Test alternate GUGiK services +5. (Future) Enable zoom 19-20 with proper optimization + +**Implementation:** +```javascript +// Update both cadastral servers with performance optimizations +{ + name: "๐Ÿ“‹ Polish Cadastral Data (Dziaล‚ki) - Server 2", + type: "wms", + url: "https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow", + params: { + layers: "dzialki,numery_dzialek,budynki", // Simplified - remove slow layers + format: "image/png", + transparent: true, + version: "1.3.0", + }, + maxZoom: 18, // Current working limit (TODO: extend to 20 with optimization) + minZoom: 13, // Don't load at far zoom levels + opacity: 0.8, +} +``` + +**Additional Optimizations:** +- Add WMS tiled parameter: `tiled: true` +- Reduce requested layers to essential only +- Implement progressive loading (load parcels first, then details) + +**Success Criteria:** Acceptable load times (<3s) at zoom 15-18, prepare for zoom 20 support + +--- + +## Phase 2: Layer Management (Week 2) + +### 2.1 Remove/Document LP-Portal Layers +**Issue:** 4 LP-Portal layers never tested, likely region-specific (Nowy Sฤ…cz) + +**Action Plan:** +1. Test if LP-Portal layers work outside Nowy Sฤ…cz region +2. If region-specific: Move to separate optional configuration +3. Document geographic limitations +4. Consider conditional loading based on map center coordinates + +**Options:** + +**Option A - Remove Entirely:** +```javascript +// Remove from mapLayers.overlays array: +// - LP-Portal Roads +// - LP-Portal Street Names +// - LP-Portal Parcels +// - LP-Portal Survey Markers +``` + +**Option B - Conditional Loading:** +```javascript +// Only show LP-Portal layers when in Nowy Sฤ…cz region +const isInNowySecz = (lat, lng) => { + return lat >= 49.5 && lat <= 49.7 && lng >= 20.5 && lng <= 20.8; +}; + +// Filter overlays based on location +const availableOverlays = mapLayers.overlays.filter(layer => { + if (layer.name.includes('LP-Portal')) { + return isInNowySecz(mapCenter[0], mapCenter[1]); + } + return true; +}); +``` + +**Recommendation:** Option B - Keep but make conditional + +**Success Criteria:** Only relevant layers shown to users + +--- + +### 2.2 Reorganize Layer Categories +**Current:** Mixed organization, no clear hierarchy +**Proposed:** Clear categorization with user-friendly names + +**New Structure:** +```javascript +export const mapLayers = { + base: [ + // International Base Maps + { name: "OpenStreetMap", ... }, + { name: "๐ŸŒ Google Satellite", ... }, + { name: "๐ŸŒ Google Hybrid", ... }, + { name: "๐Ÿ—บ๏ธ Esri Satellite", ... }, + { name: "๐Ÿ—บ๏ธ Topographic (CARTO)", ... }, + + // Polish Aerial Imagery + { name: "๐Ÿ‡ต๐Ÿ‡ฑ Orthophoto (Standard)", ... }, + { name: "๐Ÿ‡ต๐Ÿ‡ฑ Orthophoto (High-Res)", ... }, // After fix + ], + + overlays: { + government: [ + { name: "๐Ÿ“‹ Cadastral Data (Official)", ... }, + { name: "๐Ÿ—๏ธ Spatial Planning", ... }, + ], + utility: [ + { name: "๐Ÿ›ฃ๏ธ Google Roads", ... }, + ], + regional: [ // Only shown in specific regions + { name: "๐Ÿ˜๏ธ LP-Portal Roads", region: "nowysacz", ... }, + { name: "๐Ÿ˜๏ธ LP-Portal Street Names", region: "nowysacz", ... }, + { name: "๐Ÿ˜๏ธ LP-Portal Parcels", region: "nowysacz", ... }, + { name: "๐Ÿ˜๏ธ LP-Portal Survey Markers", region: "nowysacz", ... }, + ] + } +}; +``` + +**Success Criteria:** Clearer user experience, better organization + +--- + +## Phase 3: Performance Optimization (Week 3) + +### 3.1 Implement Tile Caching +**Goal:** Reduce redundant WMS requests + +**Implementation:** +```javascript +// Add to WMSLayer component +const WMSLayer = ({ url, params, opacity, attribution }) => { + const map = useMap(); + + useEffect(() => { + const wmsOptions = { + // ... existing options ... + // Add caching headers + crossOrigin: true, + updateWhenIdle: true, + updateWhenZooming: false, + keepBuffer: 2, // Keep tiles loaded from 2 screens away + }; + + const wmsLayer = L.tileLayer.wms(url, wmsOptions); + wmsLayer.addTo(map); + + return () => map.removeLayer(wmsLayer); + }, [map, url, params, opacity, attribution]); +}; +``` + +**Success Criteria:** 30% reduction in WMS requests on pan/zoom + +--- + +### 3.2 Add Loading States +**Goal:** User feedback during slow WMS loads + +**Implementation:** +```javascript +// New LoadingOverlay component +function MapLoadingOverlay({ isLoading }) { + if (!isLoading) return null; + + return ( +
+
+
+ Loading map layers... +
+
+ ); +} + +// Track loading state in LeafletMap +const [isLoading, setIsLoading] = useState(false); + +useEffect(() => { + map.on('layeradd', () => setIsLoading(true)); + map.on('load', () => setIsLoading(false)); +}, [map]); +``` + +**Success Criteria:** Visual feedback for all layer loads + +--- + +### 3.3 Implement Progressive Layer Loading +**Goal:** Load essential layers first, details later + +**Strategy:** +1. **Zoom 1-12:** Base map only +2. **Zoom 13-15:** + Basic cadastral boundaries +3. **Zoom 16-18:** + Parcel numbers, buildings +4. **Zoom 19-20:** + Survey markers, detailed overlays + +**Implementation:** +```javascript +// Auto-enable/disable overlays based on zoom +function ZoomBasedOverlayManager() { + const map = useMap(); + const [currentZoom, setCurrentZoom] = useState(map.getZoom()); + + useEffect(() => { + map.on('zoomend', () => { + const zoom = map.getZoom(); + setCurrentZoom(zoom); + + // Auto-manage overlay visibility + if (zoom < 13) { + // Disable all overlays at far zoom + disableAllOverlays(); + } else if (zoom >= 16) { + // Enable cadastral at close zoom + enableCadastralLayer(); + } + }); + }, [map]); +} +``` + +**Success Criteria:** Smooth performance at all zoom levels + +--- + +## Phase 4: Enhanced Features (Week 4) + +### 4.1 Dynamic Opacity Controls +**Goal:** User-adjustable layer transparency + +**Implementation:** +```javascript +// LayerOpacityControl component +function LayerOpacityControl({ layerName, currentOpacity, onOpacityChange }) { + return ( +
+ + onOpacityChange(e.target.value / 100)} + className="flex-1 h-1" + /> + + {Math.round(currentOpacity * 100)}% + +
+ ); +} + +// Add to layer control + + + + + + +``` + +**Success Criteria:** User can adjust opacity for all overlay layers + +--- + +### 4.2 Layer Information Panels +**Goal:** Show layer metadata, legends, data source info + +**Implementation:** +```javascript +// Layer metadata structure +const layerMetadata = { + "Polish Cadastral Data": { + title: "Polish Cadastral Data (Dziaล‚ki)", + description: "Official land parcel boundaries and property information from GUGiK", + dataSource: "Gล‚รณwny Urzฤ…d Geodezji i Kartografii", + updateFrequency: "Daily", + coverage: "Poland nationwide", + legend: "/images/legends/cadastral.png", + moreInfo: "https://www.gugik.gov.pl/", + usageNotes: "Best viewed at zoom levels 15-18. Performance may vary.", + } +}; + +// InfoButton component next to layer name + + + ๐Ÿ“‹ Cadastral Data + + + }> + ... + + +``` + +**Success Criteria:** Users understand what each layer shows + +--- + +### 4.3 Error Handling & Fallbacks +**Goal:** Graceful degradation when layers fail + +**Implementation:** +```javascript +// WMSLayer with error handling +function WMSLayer({ url, params, opacity, attribution, fallbackLayer }) { + const map = useMap(); + const [hasError, setHasError] = useState(false); + + useEffect(() => { + const wmsLayer = L.tileLayer.wms(url, wmsOptions); + + // Track tile errors + wmsLayer.on('tileerror', (error) => { + console.error(`WMS tile error for ${params.layers}:`, error); + setHasError(true); + + // Show user notification + showNotification({ + type: 'warning', + message: `Layer "${params.layers}" is experiencing issues`, + duration: 5000 + }); + }); + + wmsLayer.addTo(map); + + // If too many errors, switch to fallback + if (hasError && fallbackLayer) { + setTimeout(() => { + map.removeLayer(wmsLayer); + fallbackLayer.addTo(map); + }, 3000); + } + + return () => map.removeLayer(wmsLayer); + }, [map, url, params, hasError]); +} +``` + +**Success Criteria:** No silent failures, users informed of issues + +--- + +## Phase 5: Code Quality (Week 5) + +### 5.1 Consolidate Map Components +**Current Issue:** Multiple similar map components (ComprehensivePolishMap, ImprovedPolishOrthophotoMap, etc.) + +**Action Plan:** +1. Audit all map components: + - LeafletMap.js (main) + - ProjectMap.js (wrapper) + - ComprehensivePolishMap.js + - ImprovedPolishOrthophotoMap.js + - PolishOrthophotoMap.js + - AdvancedPolishOrthophotoMap.js + - TransparencyDemoMap.js + - CustomWMTSMap.js + - EnhancedLeafletMap.js + +2. Determine which are: + - Production (keep) + - Deprecated (remove) + - Experimental (move to /docs/examples) + +**Recommendation:** +``` +KEEP: +- LeafletMap.js (main production component) +- ProjectMap.js (SSR wrapper) + +MOVE TO /docs/examples: +- TransparencyDemoMap.js (example of opacity controls) +- CustomWMTSMap.js (example of custom WMTS) + +DEPRECATE/REMOVE: +- ComprehensivePolishMap.js (superseded by LeafletMap) +- ImprovedPolishOrthophotoMap.js (experimental) +- PolishOrthophotoMap.js (old version) +- AdvancedPolishOrthophotoMap.js (experimental) +- EnhancedLeafletMap.js (duplicate?) +``` + +**Success Criteria:** Single source of truth for map rendering + +--- + +### 5.2 Improve WMTS Capabilities Parsing +**Current Issue:** wmtsCapabilities.js has placeholder code + +**Options:** + +**Option A - Complete XML Parsing:** +```javascript +export async function parseWMTSCapabilities(url) { + const response = await fetch(`${url}?Service=WMTS&Request=GetCapabilities`); + const xmlText = await response.text(); + const parser = new DOMParser(); + const xml = parser.parseFromString(xmlText, 'text/xml'); + + const layers = Array.from(xml.querySelectorAll('Layer')).map(layer => ({ + id: layer.querySelector('Identifier')?.textContent, + title: layer.querySelector('Title')?.textContent, + formats: Array.from(layer.querySelectorAll('Format')).map(f => f.textContent), + tileMatrixSets: Array.from(layer.querySelectorAll('TileMatrixSet')).map(t => t.textContent), + })); + + return { layers }; +} +``` + +**Option B - Remove and Document:** +- Remove wmtsCapabilities.js +- Document WMTS configuration in MAP_LAYERS.md +- Use manual configuration (current working approach) + +**Recommendation:** Option B - Keep it simple, current approach works + +**Success Criteria:** No dead code, clear documentation + +--- + +### 5.3 Add TypeScript/JSDoc Types +**Goal:** Better IDE support and type safety + +**Implementation:** +```javascript +/** + * @typedef {Object} LayerConfig + * @property {string} name - Display name for the layer + * @property {'tile'|'wms'} type - Layer type + * @property {string} url - Service URL + * @property {string} attribution - Attribution HTML + * @property {number} [maxZoom=20] - Maximum zoom level + * @property {number} [minZoom=0] - Minimum zoom level + * @property {number} [opacity=1.0] - Layer opacity (0-1) + * @property {boolean} [checked=false] - Default enabled state + * @property {Object} [params] - WMS parameters (for WMS layers) + */ + +/** + * @typedef {Object} MapLayersConfig + * @property {LayerConfig[]} base - Base layer options + * @property {LayerConfig[]} overlays - Overlay layer options + */ + +/** @type {MapLayersConfig} */ +export const mapLayers = { + base: [...], + overlays: [...] +}; +``` + +**Success Criteria:** Better autocomplete and error detection + +--- + +## Phase 6: Testing & Documentation (Week 6) + +### 6.1 Create Layer Test Suite +**Goal:** Automated testing of layer availability + +**Implementation:** +```javascript +// __tests__/map-layers.test.js +describe('Map Layers', () => { + describe('Base Layers', () => { + test('OSM tiles are accessible', async () => { + const response = await fetch('https://a.tile.openstreetmap.org/15/17560/11326.png'); + expect(response.status).toBe(200); + }); + + test('Polish Orthophoto Standard is accessible', async () => { + const url = 'https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?Service=WMTS&Request=GetCapabilities'; + const response = await fetch(url); + expect(response.status).toBe(200); + }); + }); + + describe('WMS Overlays', () => { + test('Cadastral WMS GetCapabilities works', async () => { + const url = 'https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow?Service=WMS&Request=GetCapabilities'; + const response = await fetch(url); + expect(response.status).toBe(200); + expect(response.headers.get('content-type')).toContain('xml'); + }); + }); +}); +``` + +**Success Criteria:** All layers validated before deployment + +--- + +### 6.2 Update Documentation +**Files to Update:** +1. MAP_LAYERS.md - Add troubleshooting section +2. LAYER_NOTES.md - Keep updated with testing +3. README.md - Add maps usage section + +**New Documentation:** +```markdown +## Troubleshooting Map Layers + +### Slow Loading Cadastral Data +- **Cause:** GUGiK WMS servers are resource-limited +- **Solution:** Only enable at zoom 15+, limit to essential layers +- **Alternative:** Pre-cache frequently used areas + +### Polish Orthophoto Not Loading +- **Check:** Zoom level (works up to 19, not 20) +- **Check:** Network connectivity to geoportal.gov.pl +- **Alternative:** Use Google Satellite or Esri + +### Layer Control Not Showing +- **Cause:** Map container too small +- **Solution:** Minimum map height of 400px recommended +``` + +**Success Criteria:** Users can self-service common issues + +--- + +## Implementation Priority Matrix + +| Priority | Phase | Task | Impact | Effort | Status | +|----------|-------|------|--------|--------|--------| +| ๐Ÿ”ด P0 | 1 | Fix Polish Orthophoto High-Res | High | Low | Not Started | +| ๐Ÿ”ด P0 | 1 | Add zoom restrictions to Cadastral | High | Low | Not Started | +| ๐ŸŸก P1 | 1 | Fix/Remove Spatial Planning | Medium | Medium | Not Started | +| ๐ŸŸก P1 | 2 | Document LP-Portal region limits | Medium | Low | Not Started | +| ๐ŸŸก P1 | 3 | Add loading indicators | Medium | Low | Not Started | +| ๐ŸŸข P2 | 2 | Reorganize layer categories | Low | Medium | Not Started | +| ๐ŸŸข P2 | 4 | Add opacity controls | Low | Medium | Not Started | +| ๐ŸŸข P2 | 4 | Add layer info panels | Low | High | Not Started | +| ๐ŸŸข P3 | 5 | Consolidate map components | Low | High | Not Started | +| ๐ŸŸข P3 | 6 | Add automated tests | Low | Medium | Not Started | + +--- + +## Quick Wins (Do First) + +These can be implemented in 1-2 hours with immediate impact: + +1. **Add minZoom to performance-heavy layers** + - Prevent loading at far zoom levels (minZoom: 13 for Cadastral) + - Reduce unnecessary requests at distant zoom + +2. **Optimize Cadastral layer requests** + - Reduce number of requested WMS layers + - Add tiled parameter for better performance + +3. **Remove broken Spatial Planning layer** + - If GetCapabilities fails, just remove it + - Better than showing broken functionality + +4. **Update layer names for clarity** + - "Polish Orthophoto Standard" โ†’ "๐Ÿ‡ต๐Ÿ‡ฑ Aerial Imagery (Standard)" + - Better user understanding + +5. **Add loading spinner to ProjectMap** + - Copy LoadingOverlay component + - Better UX during slow loads + +6. **Verify current zoom limits** + - Document actual working zoom ranges per layer + - Note: Goal is zoom 20 for all layers (future optimization) + +--- + +## Success Metrics + +### Performance +- [ ] All base layers load in <2 seconds +- [ ] Cadastral overlays load in <5 seconds at zoom 15-18 +- [ ] No console errors for working layers +- [ ] 90%+ tile success rate + +### User Experience +- [ ] Layer control accessible on all screen sizes +- [ ] Clear feedback during loading +- [ ] No broken/blank layers in production +- [ ] Layer purposes clear from names/descriptions + +### Code Quality +- [ ] Single production map component +- [ ] All map files under 500 lines +- [ ] JSDoc types for all exports +- [ ] 80%+ test coverage for layer configs + +--- + +## Rollout Plan + +### Week 1: Emergency Fixes +- Fix critical broken layers +- Add zoom restrictions +- Remove non-working layers + +### Week 2: Optimization +- Implement caching +- Add loading states +- Progressive loading + +### Week 3: Features +- Opacity controls +- Layer info panels +- Error handling + +### Week 4: Cleanup +- Consolidate components +- Remove experimental code +- Update documentation + +### Week 5: Testing +- Automated tests +- User acceptance testing +- Performance benchmarking + +### Week 6: Release +- Deploy to production +- Monitor performance +- Gather user feedback + +--- + +## Rollback Strategy + +If issues occur: +1. **Keep old mapLayers.js** as `mapLayers.backup.js` +2. **Feature flags** for new functionality +3. **Incremental rollout** - enable for admin users first +4. **Quick disable** - config flag to revert to old layers + +--- + +## Future Considerations + +### Potential New Features +- [ ] **Universal zoom 20 support for all layers** + - Optimize WMS services to handle zoom 19-20 + - Implement tile prefetching and caching + - Add progressive detail loading at high zoom +- [ ] Save user layer preferences +- [ ] Share map view URLs (with layers/zoom) +- [ ] Export map as image/PDF +- [ ] Offline tile caching +- [ ] Custom layer upload (GeoJSON, KML) + +### Alternative Services to Explore +- [ ] Planet imagery (if budget allows) +- [ ] Bing Maps aerial imagery +- [ ] Additional Polish regional services +- [ ] CORS proxies for restricted services + +### Advanced Optimizations +- [ ] Service worker for tile caching +- [ ] WebGL rendering for better performance +- [ ] Vector tiles instead of raster +- [ ] CDN for frequently accessed tiles + +--- + +## Notes + +- LP-Portal layers appear to be **Nowy Sฤ…cz specific** - need regional filtering +- Polish government servers are **consistently slow** - can't fix, only mitigate +- Google services are **unofficial** - may break without notice +- WMTS is more performant than WMS - prefer when available +- **Zoom 20 support:** Long-term goal for all layers; currently some layers work only to zoom 18-19 + - Requires server-side optimization or caching strategy + - May need to implement client-side tile scaling/interpolation +- Keep LAYER_NOTES.md updated as testing continues + +--- + +## Approval & Sign-off + +- [ ] Technical review completed +- [ ] Performance benchmarks met +- [ ] Documentation updated +- [ ] Stakeholder approval +- [ ] Ready for production deployment + +**Last Updated:** January 16, 2026 +**Next Review:** After Phase 1 completion