feat: Add Improved Polish Orthophoto Map component with WMTS support
- Introduced ImprovedPolishOrthophotoMap component for displaying Polish orthophoto layers using WMTS. - Implemented custom WMTSLayer for handling tile requests. - Added Google Satellite and OpenStreetMap layers for comparison. - Included debug information for network requests to Geoportal. - Enhanced LeafletMap to support WMS overlays and improved layer control. - Created PolishGeoLayers module for easy access to various Polish geospatial layers. - Added TransparencyDemoMap for adjustable layer opacity controls. - Updated mapLayers configuration to include new Polish orthophoto layers and WMS overlays. - Refactored wmtsCapabilities to use updated URLs and parameters for better compatibility.
This commit is contained in:
254
src/components/ui/AdvancedPolishOrthophotoMap.js
Normal file
254
src/components/ui/AdvancedPolishOrthophotoMap.js
Normal file
@@ -0,0 +1,254 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, WMSTileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import proj4 from 'proj4';
|
||||
|
||||
// Define Polish coordinate system EPSG:2180
|
||||
proj4.defs("EPSG:2180", "+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
|
||||
|
||||
// Fix for default markers in react-leaflet
|
||||
const fixLeafletIcons = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
||||
iconUrl: '/leaflet/marker-icon.png',
|
||||
shadowUrl: '/leaflet/marker-shadow.png',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Polish Geoportal Orthophoto - Standard Resolution
|
||||
function PolishOrthophotoStandardLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Polish Geoportal Orthophoto - High Resolution
|
||||
function PolishOrthophotoHighResLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Polish Land Records (Cadastral) - using WMS
|
||||
function PolishCadastralLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.gugik.gov.pl/">GUGiK</a>'
|
||||
url="https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki',
|
||||
styles: ',,,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Polish Spatial Planning (MPZT) - WMS
|
||||
function PolishSpatialPlanningLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice',
|
||||
styles: ',,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// LP-Portal Roads Layer
|
||||
function LPPortalRoadsLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_6_mapainteraktywna_drogi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// LP-Portal Street Names Layer
|
||||
function LPPortalStreetNamesLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Google Maps layers
|
||||
function GoogleSatelliteLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleRoadsLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AdvancedPolishOrthophotoMap({
|
||||
center = [50.0647, 19.9450], // Default to Krakow, Poland
|
||||
zoom = 13,
|
||||
markers = [],
|
||||
showLayerControl = true
|
||||
}) {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
setMapLoaded(true);
|
||||
}, []);
|
||||
|
||||
const { BaseLayer, Overlay } = LayersControl;
|
||||
|
||||
if (!mapLoaded) {
|
||||
return <div>Loading map...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
{showLayerControl ? (
|
||||
<LayersControl position="topright">
|
||||
{/* Base Layers */}
|
||||
<BaseLayer name="OpenStreetMap">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer checked name="Polish Geoportal Orthophoto (Standard)">
|
||||
<PolishOrthophotoStandardLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Geoportal Orthophoto (High Resolution)">
|
||||
<PolishOrthophotoHighResLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Satellite">
|
||||
<GoogleSatelliteLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Roads">
|
||||
<GoogleRoadsLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Esri Satellite">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.esri.com/">Esri</a> — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||||
url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer> {/* Overlay Layers */}
|
||||
<Overlay name="📋 Polish Cadastral Data (Działki)">
|
||||
<PolishCadastralLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏗️ Polish Spatial Planning (MPZT)">
|
||||
<PolishSpatialPlanningLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🛣️ LP-Portal Roads">
|
||||
<LPPortalRoadsLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏷️ LP-Portal Street Names">
|
||||
<LPPortalStreetNamesLayer />
|
||||
</Overlay>
|
||||
</LayersControl>
|
||||
) : (
|
||||
// Default to Polish orthophoto when no layer control
|
||||
<PolishOrthophotoStandardLayer />
|
||||
)}
|
||||
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position}>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
322
src/components/ui/ComprehensivePolishMap.js
Normal file
322
src/components/ui/ComprehensivePolishMap.js
Normal file
@@ -0,0 +1,322 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, WMSTileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import proj4 from 'proj4';
|
||||
|
||||
// Define Polish coordinate system EPSG:2180
|
||||
proj4.defs("EPSG:2180", "+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
|
||||
|
||||
// Fix for default markers in react-leaflet
|
||||
const fixLeafletIcons = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
||||
iconUrl: '/leaflet/marker-icon.png',
|
||||
shadowUrl: '/leaflet/marker-shadow.png',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Polish Geoportal Orthophoto - Standard Resolution
|
||||
function PolishOrthophotoStandardLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 2. Polish Geoportal Orthophoto - High Resolution
|
||||
function PolishOrthophotoHighResLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 3. Polish Cadastral Data (Działki) - WMS Transparent Overlay
|
||||
function PolishCadastralLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.gugik.gov.pl/">GUGiK</a>'
|
||||
url="https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki',
|
||||
styles: ',,,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.8} // Semi-transparent for overlay
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 4. Polish Spatial Planning (MPZT) - WMS Transparent Overlay
|
||||
function PolishSpatialPlanningLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice',
|
||||
styles: ',,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.7} // Semi-transparent for overlay
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 5. LP-Portal Roads Layer - Transparent Overlay
|
||||
function LPPortalRoadsLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_6_mapainteraktywna_drogi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={0.9} // Mostly opaque for roads
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 6. LP-Portal Street Names Layer - Transparent Overlay
|
||||
function LPPortalStreetNamesLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={1.0} // Fully opaque for text labels
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 7. LP-Portal Property Parcels (Działki) - Transparent Overlay
|
||||
function LPPortalParcelsLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'dzialki',
|
||||
styles: '',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.6} // Semi-transparent for property boundaries
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 8. LP-Portal Survey Markers (Pikietarz) - Transparent Overlay
|
||||
function LPPortalSurveyMarkersLayer() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_2_view_geop_odcinek_pikietaz_glob_multi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
width: 256,
|
||||
height: 256,
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={0.8} // Semi-transparent for survey markers
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Google Maps layers for comparison
|
||||
function GoogleSatelliteLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleRoadsLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ComprehensivePolishMap({
|
||||
center = [50.0647, 19.9450], // Default to Krakow, Poland
|
||||
zoom = 13,
|
||||
markers = [],
|
||||
showLayerControl = true
|
||||
}) {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
setMapLoaded(true);
|
||||
}, []);
|
||||
|
||||
const { BaseLayer, Overlay } = LayersControl;
|
||||
|
||||
if (!mapLoaded) {
|
||||
return <div>Loading comprehensive Polish map...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
{showLayerControl ? (
|
||||
<LayersControl position="topright">
|
||||
{/* Base Layers */}
|
||||
<BaseLayer name="OpenStreetMap">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer checked name="Polish Orthophoto (Standard)">
|
||||
<PolishOrthophotoStandardLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Orthophoto (High Resolution)">
|
||||
<PolishOrthophotoHighResLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Satellite">
|
||||
<GoogleSatelliteLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Roads">
|
||||
<GoogleRoadsLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Esri Satellite">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.esri.com/">Esri</a> — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||||
url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
{/* Polish Government Overlay Layers */}
|
||||
<Overlay name="📋 Polish Cadastral Data (Działki)">
|
||||
<PolishCadastralLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏗️ Polish Spatial Planning (MPZT)">
|
||||
<PolishSpatialPlanningLayer />
|
||||
</Overlay>
|
||||
|
||||
{/* LP-Portal Overlay Layers */}
|
||||
<Overlay name="🛣️ LP-Portal Roads">
|
||||
<LPPortalRoadsLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏷️ LP-Portal Street Names">
|
||||
<LPPortalStreetNamesLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="📐 LP-Portal Property Parcels">
|
||||
<LPPortalParcelsLayer />
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="📍 LP-Portal Survey Markers">
|
||||
<LPPortalSurveyMarkersLayer />
|
||||
</Overlay>
|
||||
</LayersControl>
|
||||
) : (
|
||||
// Default to Polish orthophoto when no layer control
|
||||
<PolishOrthophotoStandardLayer />
|
||||
)}
|
||||
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position}>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
@@ -48,14 +48,13 @@ export default function CustomWMTSMap({ center, zoom = 13, markers = [] }) {
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Geoportal ORTO (WMTS)">
|
||||
<CustomWMTSLayer
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution"
|
||||
layer="ORTO"
|
||||
style="default"
|
||||
tilematrixSet="EPSG:3857"
|
||||
format="image/jpeg"
|
||||
<BaseLayer name="Polish Geoportal ORTO (Working)">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/REST/StandardResolution/tile/{z}/{y}/{x}.png"
|
||||
maxZoom={19}
|
||||
tileSize={512}
|
||||
zoomOffset={-1}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
|
||||
213
src/components/ui/DebugPolishOrthophotoMap.js
Normal file
213
src/components/ui/DebugPolishOrthophotoMap.js
Normal file
@@ -0,0 +1,213 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import proj4 from 'proj4';
|
||||
|
||||
// Define Polish coordinate system EPSG:2180 (from your OpenLayers code)
|
||||
proj4.defs("EPSG:2180", "+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
|
||||
|
||||
// Fix for default markers in react-leaflet
|
||||
const fixLeafletIcons = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
||||
iconUrl: '/leaflet/marker-icon.png',
|
||||
shadowUrl: '/leaflet/marker-shadow.png',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Multiple attempts at Polish Geoportal Orthophoto URLs
|
||||
function PolishOrthophotoOption1() {
|
||||
console.log("Loading Polish Orthophoto Option 1: WMTS KVP Standard");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a> (Option 1 - WMTS KVP)'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PolishOrthophotoOption2() {
|
||||
console.log("Loading Polish Orthophoto Option 2: WMTS KVP with EPSG:2180");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a> (Option 2 - WMTS EPSG:2180)'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=EPSG:2180&TILEMATRIX=EPSG:2180:{z}&TILEROW={y}&TILECOL={x}&FORMAT=image/jpeg"
|
||||
maxZoom={16}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PolishOrthophotoOption3() {
|
||||
console.log("Loading Polish Orthophoto Option 3: Alternative WMTS URL");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a> (Option 3 - Alt WMTS)'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image/jpeg"
|
||||
maxZoom={19}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PolishOrthophotoOption4() {
|
||||
console.log("Loading Polish Orthophoto Option 4: PNG format");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a> (Option 4 - PNG)'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=EPSG:3857&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image/png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Working Google Maps layers for comparison
|
||||
function GoogleSatelliteLayer() {
|
||||
console.log("Loading Google Satellite (known working)");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleRoadsLayer() {
|
||||
console.log("Loading Google Roads (known working)");
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DebugPolishOrthophotoMap({
|
||||
center = [50.0647, 19.9450], // Krakow, Poland
|
||||
zoom = 13,
|
||||
markers = []
|
||||
}) {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
const [debugInfo, setDebugInfo] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
setMapLoaded(true);
|
||||
|
||||
// Add debug logging
|
||||
const originalFetch = window.fetch;
|
||||
window.fetch = function(...args) {
|
||||
const url = args[0];
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.log('Geoportal request:', url);
|
||||
setDebugInfo(prev => [...prev, `Request: ${url}`]);
|
||||
}
|
||||
return originalFetch.apply(this, args)
|
||||
.then(response => {
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.log('Geoportal response status:', response.status, 'for:', url);
|
||||
setDebugInfo(prev => [...prev, `Response: ${response.status} for ${url}`]);
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(error => {
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.error('Geoportal error:', error, 'for:', url);
|
||||
setDebugInfo(prev => [...prev, `Error: ${error.message} for ${url}`]);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.fetch = originalFetch;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const { BaseLayer } = LayersControl;
|
||||
|
||||
if (!mapLoaded) {
|
||||
return <div>Loading debug map...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', width: '100%' }}>
|
||||
{/* Debug Info Panel */}
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: '10px',
|
||||
left: '10px',
|
||||
background: 'rgba(255,255,255,0.9)',
|
||||
padding: '10px',
|
||||
maxWidth: '300px',
|
||||
maxHeight: '200px',
|
||||
overflow: 'auto',
|
||||
zIndex: 1000,
|
||||
fontSize: '12px',
|
||||
borderRadius: '5px'
|
||||
}}>
|
||||
<strong>Debug Info:</strong>
|
||||
{debugInfo.slice(-10).map((info, index) => (
|
||||
<div key={index}>{info}</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
<LayersControl position="topright">
|
||||
{/* Working layers first for comparison */}
|
||||
<BaseLayer checked name="Google Satellite (Working)">
|
||||
<GoogleSatelliteLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Roads (Working)">
|
||||
<GoogleRoadsLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="OpenStreetMap (Working)">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
{/* Different Polish Geoportal attempts */}
|
||||
<BaseLayer name="Polish Ortho - Option 1 (REST Standard)">
|
||||
<PolishOrthophotoOption1 />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Ortho - Option 2 (XYZ Direct)">
|
||||
<PolishOrthophotoOption2 />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Ortho - Option 3 (WMTS)">
|
||||
<PolishOrthophotoOption3 />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish Ortho - Option 4 (Alt REST)">
|
||||
<PolishOrthophotoOption4 />
|
||||
</BaseLayer>
|
||||
</LayersControl>
|
||||
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position}>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import { MapContainer, TileLayer, WMSTileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect } from 'react';
|
||||
import { mapLayers } from './mapLayers';
|
||||
@@ -29,8 +29,7 @@ export default function EnhancedLeafletMap({
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
}, []);
|
||||
|
||||
const { BaseLayer } = LayersControl;
|
||||
const { BaseLayer, Overlay } = LayersControl;
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
@@ -41,6 +40,7 @@ export default function EnhancedLeafletMap({
|
||||
>
|
||||
{showLayerControl ? (
|
||||
<LayersControl position="topright">
|
||||
{/* Base Layers */}
|
||||
{mapLayers.base.map((layer, index) => (
|
||||
<BaseLayer
|
||||
key={index}
|
||||
@@ -55,6 +55,32 @@ export default function EnhancedLeafletMap({
|
||||
/>
|
||||
</BaseLayer>
|
||||
))}
|
||||
{/* Overlay Layers */}
|
||||
{mapLayers.overlays && mapLayers.overlays.map((layer, index) => (
|
||||
<Overlay
|
||||
key={`overlay-${index}`}
|
||||
checked={layer.checked}
|
||||
name={layer.name}
|
||||
>
|
||||
{layer.type === "wms" ? (
|
||||
<WMSTileLayer
|
||||
attribution={layer.attribution}
|
||||
url={layer.url}
|
||||
params={layer.params}
|
||||
format={layer.params.format}
|
||||
transparent={layer.params.transparent}
|
||||
opacity={layer.opacity}
|
||||
/>
|
||||
) : (
|
||||
<TileLayer
|
||||
attribution={layer.attribution}
|
||||
url={layer.url}
|
||||
maxZoom={layer.maxZoom}
|
||||
opacity={layer.opacity}
|
||||
/>
|
||||
)}
|
||||
</Overlay>
|
||||
))}
|
||||
</LayersControl>
|
||||
) : (
|
||||
// Default layer when no layer control
|
||||
|
||||
167
src/components/ui/ImprovedPolishOrthophotoMap.js
Normal file
167
src/components/ui/ImprovedPolishOrthophotoMap.js
Normal file
@@ -0,0 +1,167 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { WMTSLayer } from './WMTSLayer';
|
||||
|
||||
// Fix for default markers in react-leaflet
|
||||
const fixLeafletIcons = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
||||
iconUrl: '/leaflet/marker-icon.png',
|
||||
shadowUrl: '/leaflet/marker-shadow.png',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Custom layer wrapper for WMTS
|
||||
function PolishWMTSLayer({ tilematrixSet = 'EPSG:3857', format = 'image/jpeg' }) {
|
||||
return (
|
||||
<WMTSLayer
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution"
|
||||
layer="ORTO"
|
||||
style="default"
|
||||
tilematrixSet={tilematrixSet}
|
||||
format={format}
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
maxZoom={19}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Working Google Maps layers for comparison
|
||||
function GoogleSatelliteLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ImprovedPolishOrthophotoMap({
|
||||
center = [50.0647, 19.9450], // Krakow, Poland
|
||||
zoom = 13,
|
||||
markers = []
|
||||
}) {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
const [debugInfo, setDebugInfo] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
setMapLoaded(true);
|
||||
|
||||
// Debug network requests
|
||||
const originalFetch = window.fetch;
|
||||
window.fetch = function(...args) {
|
||||
const url = args[0];
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.log('Geoportal WMTS request:', url);
|
||||
setDebugInfo(prev => [...prev.slice(-5), `Request: ${url.split('?')[1]}`]);
|
||||
}
|
||||
return originalFetch.apply(this, args)
|
||||
.then(response => {
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.log('Geoportal response:', response.status, response.statusText);
|
||||
setDebugInfo(prev => [...prev.slice(-5), `Response: ${response.status} ${response.statusText}`]);
|
||||
}
|
||||
return response;
|
||||
})
|
||||
.catch(error => {
|
||||
if (typeof url === 'string' && url.includes('geoportal.gov.pl')) {
|
||||
console.error('Geoportal error:', error);
|
||||
setDebugInfo(prev => [...prev.slice(-5), `Error: ${error.message}`]);
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.fetch = originalFetch;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const { BaseLayer } = LayersControl;
|
||||
|
||||
if (!mapLoaded) {
|
||||
return <div>Loading improved map...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', width: '100%' }}>
|
||||
{/* Debug Info Panel */}
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
top: '10px',
|
||||
left: '10px',
|
||||
background: 'rgba(255,255,255,0.95)',
|
||||
padding: '10px',
|
||||
maxWidth: '400px',
|
||||
maxHeight: '150px',
|
||||
overflow: 'auto',
|
||||
zIndex: 1000,
|
||||
fontSize: '11px',
|
||||
borderRadius: '5px',
|
||||
boxShadow: '0 2px 5px rgba(0,0,0,0.2)'
|
||||
}}>
|
||||
<strong>WMTS Debug Info:</strong>
|
||||
{debugInfo.map((info, index) => (
|
||||
<div key={index} style={{ marginTop: '2px', wordBreak: 'break-all' }}>
|
||||
{info}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
<LayersControl position="topright">
|
||||
{/* Working reference layer */}
|
||||
<BaseLayer checked name="Google Satellite (Working Reference)">
|
||||
<GoogleSatelliteLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="OpenStreetMap">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
{/* WMTS layers with custom implementation */}
|
||||
<BaseLayer name="Polish WMTS (EPSG:3857, JPEG)">
|
||||
<PolishWMTSLayer tilematrixSet="EPSG:3857" format="image/jpeg" />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish WMTS (EPSG:3857, PNG)">
|
||||
<PolishWMTSLayer tilematrixSet="EPSG:3857" format="image/png" />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish WMTS (EPSG:4326, JPEG)">
|
||||
<PolishWMTSLayer tilematrixSet="EPSG:4326" format="image/jpeg" />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Polish WMTS (EPSG:2180, JPEG)">
|
||||
<PolishWMTSLayer tilematrixSet="EPSG:2180" format="image/jpeg" />
|
||||
</BaseLayer>
|
||||
</LayersControl>
|
||||
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position}>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
MapContainer,
|
||||
TileLayer,
|
||||
WMSTileLayer,
|
||||
Marker,
|
||||
Popup,
|
||||
LayersControl,
|
||||
@@ -80,8 +81,7 @@ export default function EnhancedLeafletMap({
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
}, []);
|
||||
|
||||
const { BaseLayer } = LayersControl;
|
||||
const { BaseLayer, Overlay } = LayersControl;
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
@@ -94,6 +94,7 @@ export default function EnhancedLeafletMap({
|
||||
|
||||
{showLayerControl ? (
|
||||
<LayersControl position="topright">
|
||||
{/* Base Layers */}
|
||||
{mapLayers.base.map((layer, index) => (
|
||||
<BaseLayer
|
||||
key={index}
|
||||
@@ -107,6 +108,32 @@ export default function EnhancedLeafletMap({
|
||||
tileSize={layer.tileSize || 256}
|
||||
/>
|
||||
</BaseLayer>
|
||||
))}
|
||||
{/* Overlay Layers */}
|
||||
{mapLayers.overlays && mapLayers.overlays.map((layer, index) => (
|
||||
<Overlay
|
||||
key={`overlay-${index}`}
|
||||
checked={layer.checked}
|
||||
name={layer.name}
|
||||
>
|
||||
{layer.type === "wms" ? (
|
||||
<WMSTileLayer
|
||||
attribution={layer.attribution}
|
||||
url={layer.url}
|
||||
params={layer.params}
|
||||
format={layer.params.format}
|
||||
transparent={layer.params.transparent}
|
||||
opacity={layer.opacity}
|
||||
/>
|
||||
) : (
|
||||
<TileLayer
|
||||
attribution={layer.attribution}
|
||||
url={layer.url}
|
||||
maxZoom={layer.maxZoom}
|
||||
opacity={layer.opacity}
|
||||
/>
|
||||
)}
|
||||
</Overlay>
|
||||
))}
|
||||
</LayersControl>
|
||||
) : (
|
||||
|
||||
271
src/components/ui/PolishGeoLayers.js
Normal file
271
src/components/ui/PolishGeoLayers.js
Normal file
@@ -0,0 +1,271 @@
|
||||
"use client";
|
||||
|
||||
import { WMSTileLayer, TileLayer } from 'react-leaflet';
|
||||
|
||||
// Collection of all Polish geospatial layers from your OpenLayers implementation
|
||||
// These can be imported individually and used in any map component
|
||||
|
||||
// 1. Polish Orthophoto Layers (WMTS)
|
||||
export function PolishOrthophotoStandard() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function PolishOrthophotoHighRes() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 2. Polish Government WMS Layers - All transparent overlays
|
||||
export function PolishCadastralData() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.gugik.gov.pl/">GUGiK</a>'
|
||||
url="https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki',
|
||||
styles: ',,,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857'
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.8} // Semi-transparent overlay for property boundaries
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function PolishSpatialPlanning() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice',
|
||||
styles: ',,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.7} // Semi-transparent overlay for planning zones
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 3. LP-Portal Municipal Layers - Transparent overlays with different opacity levels
|
||||
export function LPPortalRoads() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_6_mapainteraktywna_drogi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={0.9} // Mostly opaque for road visibility
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function LPPortalStreetNames() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={1.0} // Fully opaque for text readability
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function LPPortalParcels() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'dzialki',
|
||||
styles: '',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png"
|
||||
transparent={true}
|
||||
opacity={0.6} // Semi-transparent for parcel boundaries
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function LPPortalSurveyMarkers() {
|
||||
return (
|
||||
<WMSTileLayer
|
||||
attribution='© <a href="https://lp-portal.pl/">LP-Portal</a>'
|
||||
url="https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms"
|
||||
params={{
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_2_view_geop_odcinek_pikietaz_glob_multi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
}}
|
||||
format="image/png8"
|
||||
transparent={true}
|
||||
opacity={0.8} // Semi-transparent for survey markers
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 4. Utility Google Maps Layers for comparison
|
||||
export function GoogleSatellite() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function GoogleRoads() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Layer configuration for easy integration with transparency settings
|
||||
export const polishLayerConfigs = {
|
||||
base: [
|
||||
{
|
||||
name: "Polish Orthophoto (Standard)",
|
||||
component: PolishOrthophotoStandard,
|
||||
description: "High-quality aerial imagery from Polish Geoportal",
|
||||
opacity: 1.0,
|
||||
transparent: false
|
||||
},
|
||||
{
|
||||
name: "Polish Orthophoto (High Resolution)",
|
||||
component: PolishOrthophotoHighRes,
|
||||
description: "Ultra-high resolution aerial imagery",
|
||||
opacity: 1.0,
|
||||
transparent: false
|
||||
},
|
||||
{
|
||||
name: "Google Satellite",
|
||||
component: GoogleSatellite,
|
||||
description: "Google satellite imagery for comparison",
|
||||
opacity: 1.0,
|
||||
transparent: false
|
||||
},
|
||||
{
|
||||
name: "Google Roads",
|
||||
component: GoogleRoads,
|
||||
description: "Google road overlay",
|
||||
opacity: 1.0,
|
||||
transparent: false
|
||||
}
|
||||
],
|
||||
overlays: [
|
||||
{
|
||||
name: "📋 Polish Cadastral Data",
|
||||
component: PolishCadastralData,
|
||||
description: "Property boundaries and parcel information",
|
||||
opacity: 0.8,
|
||||
transparent: true,
|
||||
category: "government"
|
||||
},
|
||||
{
|
||||
name: "🏗️ Polish Spatial Planning",
|
||||
component: PolishSpatialPlanning,
|
||||
description: "Zoning and urban planning data",
|
||||
opacity: 0.7,
|
||||
transparent: true,
|
||||
category: "government"
|
||||
},
|
||||
{
|
||||
name: "🛣️ LP-Portal Roads",
|
||||
component: LPPortalRoads,
|
||||
description: "Detailed road network",
|
||||
opacity: 0.9,
|
||||
transparent: true,
|
||||
category: "municipal"
|
||||
},
|
||||
{
|
||||
name: "🏷️ LP-Portal Street Names",
|
||||
component: LPPortalStreetNames,
|
||||
description: "Street names and descriptions",
|
||||
opacity: 1.0,
|
||||
transparent: true,
|
||||
category: "municipal"
|
||||
},
|
||||
{
|
||||
name: "📐 LP-Portal Parcels",
|
||||
component: LPPortalParcels,
|
||||
description: "Municipal property parcels",
|
||||
opacity: 0.6,
|
||||
transparent: true,
|
||||
category: "municipal"
|
||||
},
|
||||
{
|
||||
name: "📍 LP-Portal Survey Markers",
|
||||
component: LPPortalSurveyMarkers,
|
||||
description: "Survey markers and reference points",
|
||||
opacity: 0.8,
|
||||
transparent: true,
|
||||
category: "municipal"
|
||||
}
|
||||
]
|
||||
};
|
||||
126
src/components/ui/PolishOrthophotoMap.js
Normal file
126
src/components/ui/PolishOrthophotoMap.js
Normal file
@@ -0,0 +1,126 @@
|
||||
"use client";
|
||||
|
||||
import { MapContainer, TileLayer, Marker, Popup, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { useEffect, useState } from 'react';
|
||||
import proj4 from 'proj4';
|
||||
|
||||
// Define Polish coordinate system EPSG:2180
|
||||
proj4.defs("EPSG:2180", "+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
|
||||
|
||||
// Fix for default markers in react-leaflet
|
||||
const fixLeafletIcons = () => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
delete L.Icon.Default.prototype._getIconUrl;
|
||||
L.Icon.Default.mergeOptions({
|
||||
iconRetinaUrl: '/leaflet/marker-icon-2x.png',
|
||||
iconUrl: '/leaflet/marker-icon.png',
|
||||
shadowUrl: '/leaflet/marker-shadow.png',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Custom tile layer component for Polish Geoportal - WORKING VERSION
|
||||
function PolishOrthophotoLayer({ visible = true }) {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.geoportal.gov.pl/">Geoportal</a>'
|
||||
url="https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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}
|
||||
key="polish-orthophoto"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Google Maps layers as alternatives
|
||||
function GoogleSatelliteLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleRoadsLayer() {
|
||||
return (
|
||||
<TileLayer
|
||||
attribution='© Google'
|
||||
url="http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}"
|
||||
maxZoom={20}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function PolishOrthophotoMap({
|
||||
center = [50.0647, 19.9450], // Default to Krakow, Poland
|
||||
zoom = 13,
|
||||
markers = [],
|
||||
showLayerControl = true
|
||||
}) {
|
||||
const [mapLoaded, setMapLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
setMapLoaded(true);
|
||||
}, []);
|
||||
|
||||
const { BaseLayer } = LayersControl;
|
||||
|
||||
if (!mapLoaded) {
|
||||
return <div>Loading map...</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
{showLayerControl ? (
|
||||
<LayersControl position="topright">
|
||||
<BaseLayer name="OpenStreetMap">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer checked name="Polish Geoportal Orthophoto">
|
||||
<PolishOrthophotoLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Satellite">
|
||||
<GoogleSatelliteLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Google Roads">
|
||||
<GoogleRoadsLayer />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="Esri Satellite">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.esri.com/">Esri</a> — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||||
url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
</LayersControl>
|
||||
) : (
|
||||
// Default to Polish orthophoto when no layer control
|
||||
<PolishOrthophotoLayer />
|
||||
)}
|
||||
|
||||
{markers.map((marker, index) => (
|
||||
<Marker key={index} position={marker.position}>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
166
src/components/ui/TransparencyDemoMap.js
Normal file
166
src/components/ui/TransparencyDemoMap.js
Normal file
@@ -0,0 +1,166 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from 'react';
|
||||
import { MapContainer, TileLayer, LayersControl } from 'react-leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import {
|
||||
PolishOrthophotoStandard,
|
||||
PolishCadastralData,
|
||||
PolishSpatialPlanning,
|
||||
LPPortalRoads,
|
||||
LPPortalStreetNames,
|
||||
LPPortalParcels
|
||||
} from './PolishGeoLayers';
|
||||
|
||||
// Custom layer with adjustable opacity
|
||||
function AdjustableOpacityLayer({ children, opacity = 1.0 }) {
|
||||
return React.cloneElement(children, { opacity });
|
||||
}
|
||||
|
||||
export default function TransparencyDemoMap({
|
||||
center = [50.0647, 19.9450],
|
||||
zoom = 15
|
||||
}) {
|
||||
const [opacitySettings, setOpacitySettings] = useState({
|
||||
cadastral: 0.8,
|
||||
planning: 0.7,
|
||||
roads: 0.9,
|
||||
streetNames: 1.0,
|
||||
parcels: 0.6
|
||||
});
|
||||
|
||||
const { BaseLayer, Overlay } = LayersControl;
|
||||
|
||||
const updateOpacity = (layer, value) => {
|
||||
setOpacitySettings(prev => ({
|
||||
...prev,
|
||||
[layer]: value / 100
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full">
|
||||
{/* Opacity Controls */}
|
||||
<div className="absolute top-4 left-4 z-[1000] bg-white p-4 rounded-lg shadow-lg max-w-xs">
|
||||
<h3 className="font-semibold mb-3">🎨 Layer Transparency Controls</h3>
|
||||
<div className="space-y-3 text-sm">
|
||||
<div>
|
||||
<label className="block text-gray-700 mb-1">📋 Cadastral Data</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={opacitySettings.cadastral * 100}
|
||||
onChange={(e) => updateOpacity('cadastral', e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{Math.round(opacitySettings.cadastral * 100)}%</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-gray-700 mb-1">🏗️ Spatial Planning</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={opacitySettings.planning * 100}
|
||||
onChange={(e) => updateOpacity('planning', e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{Math.round(opacitySettings.planning * 100)}%</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-gray-700 mb-1">🛣️ Roads</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={opacitySettings.roads * 100}
|
||||
onChange={(e) => updateOpacity('roads', e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{Math.round(opacitySettings.roads * 100)}%</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-gray-700 mb-1">🏷️ Street Names</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={opacitySettings.streetNames * 100}
|
||||
onChange={(e) => updateOpacity('streetNames', e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{Math.round(opacitySettings.streetNames * 100)}%</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-gray-700 mb-1">📐 Parcels</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={opacitySettings.parcels * 100}
|
||||
onChange={(e) => updateOpacity('parcels', e.target.value)}
|
||||
className="w-full"
|
||||
/>
|
||||
<span className="text-xs text-gray-500">{Math.round(opacitySettings.parcels * 100)}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MapContainer
|
||||
center={center}
|
||||
zoom={zoom}
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
scrollWheelZoom={true}
|
||||
>
|
||||
<LayersControl position="topright">
|
||||
<BaseLayer checked name="Polish Orthophoto">
|
||||
<PolishOrthophotoStandard />
|
||||
</BaseLayer>
|
||||
|
||||
<BaseLayer name="OpenStreetMap">
|
||||
<TileLayer
|
||||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
maxZoom={19}
|
||||
/>
|
||||
</BaseLayer>
|
||||
|
||||
<Overlay name="📋 Cadastral Data (Adjustable)">
|
||||
<AdjustableOpacityLayer opacity={opacitySettings.cadastral}>
|
||||
<PolishCadastralData />
|
||||
</AdjustableOpacityLayer>
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏗️ Spatial Planning (Adjustable)">
|
||||
<AdjustableOpacityLayer opacity={opacitySettings.planning}>
|
||||
<PolishSpatialPlanning />
|
||||
</AdjustableOpacityLayer>
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🛣️ Roads (Adjustable)">
|
||||
<AdjustableOpacityLayer opacity={opacitySettings.roads}>
|
||||
<LPPortalRoads />
|
||||
</AdjustableOpacityLayer>
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="🏷️ Street Names (Adjustable)">
|
||||
<AdjustableOpacityLayer opacity={opacitySettings.streetNames}>
|
||||
<LPPortalStreetNames />
|
||||
</AdjustableOpacityLayer>
|
||||
</Overlay>
|
||||
|
||||
<Overlay name="📐 Parcels (Adjustable)">
|
||||
<AdjustableOpacityLayer opacity={opacitySettings.parcels}>
|
||||
<LPPortalParcels />
|
||||
</AdjustableOpacityLayer>
|
||||
</Overlay>
|
||||
</LayersControl>
|
||||
</MapContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
156
src/components/ui/WMTSLayer.js
Normal file
156
src/components/ui/WMTSLayer.js
Normal file
@@ -0,0 +1,156 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useMap } from 'react-leaflet';
|
||||
|
||||
// Custom WMTS Layer for Polish Geoportal
|
||||
export function WMTSLayer({
|
||||
url,
|
||||
layer,
|
||||
style = 'default',
|
||||
tilematrixSet = 'EPSG:3857',
|
||||
format = 'image/jpeg',
|
||||
attribution = '',
|
||||
maxZoom = 19
|
||||
}) {
|
||||
const map = useMap();
|
||||
const layerRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
|
||||
// Custom WMTS layer that builds proper KVP URLs
|
||||
const WMTSTileLayer = L.TileLayer.extend({
|
||||
getTileUrl: function(coords) {
|
||||
const tilematrix = tilematrixSet === 'EPSG:2180' ? `EPSG:2180:${coords.z}` : coords.z;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
SERVICE: 'WMTS',
|
||||
REQUEST: 'GetTile',
|
||||
VERSION: '1.0.0',
|
||||
LAYER: layer,
|
||||
STYLE: style,
|
||||
TILEMATRIXSET: tilematrixSet,
|
||||
TILEMATRIX: tilematrix,
|
||||
TILEROW: coords.y,
|
||||
TILECOL: coords.x,
|
||||
FORMAT: format
|
||||
});
|
||||
|
||||
return `${url}?${params.toString()}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Create the layer
|
||||
layerRef.current = new WMTSTileLayer('', {
|
||||
attribution: attribution,
|
||||
maxZoom: maxZoom,
|
||||
tileSize: 256
|
||||
});
|
||||
|
||||
// Add to map
|
||||
map.addLayer(layerRef.current);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
return () => {
|
||||
if (layerRef.current && map) {
|
||||
map.removeLayer(layerRef.current);
|
||||
}
|
||||
};
|
||||
}, [map, url, layer, style, tilematrixSet, format, attribution, maxZoom]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Proj4Leaflet WMTS Layer for Polish projection
|
||||
export function Proj4WMTSLayer({
|
||||
url,
|
||||
layer,
|
||||
style = 'default',
|
||||
tilematrixSet = 'EPSG:2180',
|
||||
format = 'image/jpeg',
|
||||
attribution = '',
|
||||
maxZoom = 16
|
||||
}) {
|
||||
const map = useMap();
|
||||
const layerRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const L = require('leaflet');
|
||||
const proj4 = require('proj4');
|
||||
require('proj4leaflet');
|
||||
|
||||
// Define Polish projection
|
||||
proj4.defs("EPSG:2180", "+proj=tmerc +lat_0=0 +lon_0=19 +k=0.9993 +x_0=500000 +y_0=-5300000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
|
||||
|
||||
// Create CRS for EPSG:2180
|
||||
const crs2180 = new L.Proj.CRS('EPSG:2180', proj4.defs('EPSG:2180'), {
|
||||
resolutions: [
|
||||
2116.6709 * 4,
|
||||
2116.6709 * 2,
|
||||
2116.6709,
|
||||
1058.33545,
|
||||
529.167725,
|
||||
264.5838625,
|
||||
132.29193125,
|
||||
66.145965625,
|
||||
26.458386249999997,
|
||||
13.229193124999998,
|
||||
6.614596562499999,
|
||||
2.645838625,
|
||||
1.3229193125,
|
||||
0.529167725,
|
||||
0.2645838625,
|
||||
0.13229193125,
|
||||
0.13229193125 / 2,
|
||||
],
|
||||
origin: [100000, 850000],
|
||||
bounds: L.bounds([144907.16581514146, 129171.69217334315], [890379.1658151413, 812697.4119729949])
|
||||
});
|
||||
|
||||
// Custom WMTS layer
|
||||
const WMTSTileLayer = L.TileLayer.extend({
|
||||
getTileUrl: function(coords) {
|
||||
const tilematrix = `EPSG:2180:${coords.z}`;
|
||||
|
||||
const params = new URLSearchParams({
|
||||
SERVICE: 'WMTS',
|
||||
REQUEST: 'GetTile',
|
||||
VERSION: '1.0.0',
|
||||
LAYER: layer,
|
||||
STYLE: style,
|
||||
TILEMATRIXSET: tilematrixSet,
|
||||
TILEMATRIX: tilematrix,
|
||||
TILEROW: coords.y,
|
||||
TILECOL: coords.x,
|
||||
FORMAT: format
|
||||
});
|
||||
|
||||
return `${url}?${params.toString()}`;
|
||||
}
|
||||
});
|
||||
|
||||
// Create the layer
|
||||
layerRef.current = new WMTSTileLayer('', {
|
||||
attribution: attribution,
|
||||
maxZoom: maxZoom,
|
||||
tileSize: 512
|
||||
});
|
||||
|
||||
// Add to map (but this won't work properly with EPSG:3857 map)
|
||||
// This is more for demonstration - would need to change map CRS
|
||||
map.addLayer(layerRef.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (layerRef.current && map) {
|
||||
map.removeLayer(layerRef.current);
|
||||
}
|
||||
};
|
||||
}, [map, url, layer, style, tilematrixSet, format, attribution, maxZoom]);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -13,14 +13,32 @@ export const mapLayers = {
|
||||
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
maxZoom: 19
|
||||
},
|
||||
polishOrthophoto,
|
||||
{
|
||||
name: "Polish Land Records (WMS)",
|
||||
attribution: '© <a href="https://www.gugik.gov.pl/">GUGiK</a>',
|
||||
// This is actually a WMS service, not WMTS as discovered from GetCapabilities
|
||||
url: "https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX={bbox-epsg-3857}&CRS=EPSG:3857&WIDTH=256&HEIGHT=256&LAYERS=EGiB&STYLES=&FORMAT=image/png",
|
||||
name: "🇵🇱 Polish Orthophoto (Standard)",
|
||||
attribution: '© <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
|
||||
url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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,
|
||||
tileSize: 256
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "🇵🇱 Polish Orthophoto (High Resolution)",
|
||||
attribution: '© <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
|
||||
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,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "🌍 Google Satellite",
|
||||
attribution: '© Google',
|
||||
url: "http://mt1.google.com/vt/lyrs=s&hl=pl&x={x}&y={y}&z={z}",
|
||||
maxZoom: 20,
|
||||
checked: false
|
||||
}, {
|
||||
name: "🌍 Google Hybrid",
|
||||
attribution: '© Google',
|
||||
url: "http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}",
|
||||
maxZoom: 20,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "Satellite (Esri)",
|
||||
@@ -34,7 +52,131 @@ export const mapLayers = {
|
||||
url: "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
|
||||
maxZoom: 19
|
||||
}
|
||||
].filter(Boolean) // Remove any null entries
|
||||
].filter(Boolean), // Remove any null entries
|
||||
overlays: [
|
||||
{
|
||||
name: "🌍 Google Roads",
|
||||
type: "tile",
|
||||
attribution: '© Google',
|
||||
url: "http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}",
|
||||
maxZoom: 20,
|
||||
opacity: 1.0,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "📋 Polish Cadastral Data",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://www.gugik.gov.pl/">GUGiK</a>',
|
||||
url: "https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki',
|
||||
styles: ',,,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857'
|
||||
},
|
||||
opacity: 0.8,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "🏗️ Polish Spatial Planning",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
|
||||
url: "https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice',
|
||||
styles: ',,,,,,',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
},
|
||||
opacity: 0.7,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "🛣️ LP-Portal Roads",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://lp-portal.pl/">LP-Portal</a>',
|
||||
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_6_mapainteraktywna_drogi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.3.0',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
},
|
||||
opacity: 0.9,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "🏷️ LP-Portal Street Names",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://lp-portal.pl/">LP-Portal</a>',
|
||||
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
},
|
||||
opacity: 1.0,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "📐 LP-Portal Parcels",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://lp-portal.pl/">LP-Portal</a>',
|
||||
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: 'dzialki',
|
||||
styles: '',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
},
|
||||
opacity: 0.6,
|
||||
checked: false
|
||||
},
|
||||
{
|
||||
name: "📍 LP-Portal Survey Markers",
|
||||
type: "wms",
|
||||
attribution: '© <a href="https://lp-portal.pl/">LP-Portal</a>',
|
||||
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
|
||||
params: {
|
||||
service: 'WMS',
|
||||
request: 'GetMap',
|
||||
layers: '00_2_view_geop_odcinek_pikietaz_glob_multi',
|
||||
styles: '',
|
||||
format: 'image/png8',
|
||||
transparent: true,
|
||||
version: '1.1.1',
|
||||
crs: 'EPSG:3857',
|
||||
tiled: true
|
||||
},
|
||||
opacity: 0.8,
|
||||
checked: false
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// WMTS services configuration with GetCapabilities URLs
|
||||
|
||||
@@ -53,13 +53,15 @@ export function buildWMTSTileUrl(config) {
|
||||
export const polishWMTSServices = {
|
||||
orthophoto: {
|
||||
name: "Polish Geoportal Orthophoto",
|
||||
capabilitiesUrl: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution",
|
||||
capabilitiesUrl: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/REST/StandardResolution",
|
||||
layer: "ORTO",
|
||||
style: "default",
|
||||
tilematrixSet: "EPSG:2180",
|
||||
format: "image/jpeg",
|
||||
tilematrixSet: "EPSG:3857", // Changed from EPSG:2180 to EPSG:3857 for better Leaflet compatibility
|
||||
format: "image/png", // Changed from jpeg to png
|
||||
attribution: '© <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
|
||||
maxZoom: 19
|
||||
maxZoom: 19,
|
||||
tileSize: 512,
|
||||
zoomOffset: -1
|
||||
}
|
||||
};
|
||||
|
||||
@@ -75,14 +77,10 @@ export function generateLayerConfig(serviceName) {
|
||||
return {
|
||||
name: service.name,
|
||||
attribution: service.attribution,
|
||||
url: buildWMTSTileUrl({
|
||||
baseUrl: service.capabilitiesUrl,
|
||||
layer: service.layer,
|
||||
style: service.style,
|
||||
tilematrixSet: service.tilematrixSet,
|
||||
format: service.format
|
||||
}),
|
||||
// Use working WMTS KVP URL format
|
||||
url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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: service.maxZoom,
|
||||
tileSize: 256
|
||||
tileSize: 256, // Standard tile size for WMTS
|
||||
checked: false
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user