1

I need to use CRS 2056 with leaflet and maplibre leaflet-maplibre-gl.js to display vector tiles.

Using this code

<html>
<head>
    !-- Version 3.0 --> <!-- full stretch -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"/>
    <style>
        #map {
            bottom: 0;
            left: 0;
            position: absolute;
            right: 0;
            top: 0;
        }
    </style>
</head>
<body>
<div id="map"></div>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.6.0/proj4.js"></script>
<script src="https://unpkg.com/georaster"></script>
<script src="https://unpkg.com/georaster-layer-for-leaflet"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4leaflet/1.0.2/proj4leaflet.min.js"></script>

<script src='https://unpkg.com/[email protected]/dist/maplibre-gl.js'></script>
<script src="https://unpkg.com/@maplibre/[email protected]/leaflet-maplibre-gl.js"></script>
<script src="https://unpkg.com/proj4"></script>




<script>
    // Define custom CRS for EPSG 2056
    var crs2056 = new L.Proj.CRS('EPSG:2056',
        "+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=2600000 +y_0=1200000 +ellps=bessel +towgs84=674.374,15.056,405.346,0,0,0,0 +units=m +no_defs",
        {
            resolutions: [1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25, 0.125, 0.0625],
            origin: [2485071.58, 1299941.79],
        }
    );

    // Initialize Leaflet map with custom CRS
    var map = L.map('map', {
        crs: crs2056
    }).setView([46, 8], 1);
    
    // Initialize Vectortiles
    L.maplibreGL({
    style: 'https://vectortiles.geo.admin.ch/styles/ch.swisstopo.leichte-basiskarte-imagery.vt/style.json',  // Style URL; see our documentation for more options
                
    }).addTo(map);
    // Wait for the style to load
    map.on('styledata', function() {
        // Check if the layer exists
        if (map.hasLayer('swissimage')) {
            // Remove the layer
            map.removeLayer('swissimage');
        }
        
    });
    
    
    // Add WMS Layer
    //var map4 = new L.tileLayer.wms("https://wms.geo.admin.ch/", {
    //    layers: 'ch.swisstopo.pixelkarte-farbe',
    //    format: 'image/png',
    //    transparent: true,
    //    crs: crs2056
    //}).addTo(map);

    const url_to_geotiff_file = new URLSearchParams(location.search).get("url");
    console.log("url_to_geotiff_file:", url_to_geotiff_file);

    if (!url_to_geotiff_file) {
        setTimeout(function() {
            // If no URL is provided, redirect to a sample GeoTIFF
            const parser = new URL(window.location);
            parser.searchParams.set("url", "https://d29cp2gnktw6by.cloudfront.net/data/S2_LEVEL_2A/20240101T102431/S2_L2A_SR_20240101T102431_20240101T102428_10M_run20240102.tif");
            window.location = parser.href;
        }, 2 * 1000);
    } else {
        console.log("url_to_geotiff_file:", url_to_geotiff_file);
        // Parse the GeoTIFF data
        parseGeoraster(url_to_geotiff_file).then(function (georaster) {
            console.log("georaster:", georaster);
            // based on https://custom-scripts.sentinel-hub.com/custom-scripts/sentinel-2/l2a_optimized/    
        
        // Contrast enhance / highlight compress
        const maxR = 3.0; // max reflectance
        const midR = 0.13;
        const sat = 1.2;
        const gamma = 1.8;
        
        
        function evaluatePixel(val0,val1,val2) {
            //console.log("val0:", val0, "val1:", val1, "val2:", val2);
            const rgbLin = satEnh(sAdj(val0), sAdj(val1), sAdj(val2));
            //console.log("rgbLin:", rgbLin);
            //console.log("sRGB0:", sRGB(rgbLin[0]), "sRGB1:", sRGB(rgbLin[1]), "sRGB2:", sRGB(rgbLin[2]));
            return [sRGB(rgbLin[0]), sRGB(rgbLin[1]), sRGB(rgbLin[2])];
        }
        
        function sAdj(a) {
            return adjGamma(adj(a, midR, 1, maxR));
        }

        
        const gOff = 0.01;
        const gOffPow = Math.pow(gOff, gamma);
        const gOffRange = Math.pow(1 + gOff, gamma) - gOffPow;


        function adjGamma(b) {
            return (Math.pow((b + gOff), gamma) - gOffPow) / gOffRange;
        }
        
        // Saturation enhancement
        function satEnh(r, g, b) {
            const avgS = (r + g + b) / 3.0 * (1 - sat);
            return [clip(avgS + r * sat), clip(avgS + g * sat), clip(avgS + b * sat)];
        }

        function clip(s) {
            return s < 0 ? 0 : s > 1 ? 1 : s;
        }

        //contrast enhancement with highlight compression
        function adj(a, tx, ty, maxC) {
            var ar = clip(a / maxC, 0, 1);
            return ar * (ar * (tx / maxC + ty - 1) - ty) / (ar * (2 * tx / maxC - 1) - tx / maxC);
        }

        const sRGB = (c) => c <= 0.0031308 ? (12.92 * c) : (1.055 * Math.pow(c, 0.41666666666) - 0.055);


            const layer = new GeoRasterLayer({
                attribution: "Contains modified Copernicus Sentinel data 2024",
                debugLevel: 0,
                georaster,
                resolution: 128,
                opacity:1,
                resampleMethod: "nearest",
                pixelValuesToColorFn: values => {
                    // Check if any of the bands have a value of 9999 or 0
                    if (values.some(value => value === 9999 )) {
                    //if (values.some(value => value === 9999 || value === 0)) {
                        // If any band has a value of 9999 or 0, return transparent color
                        return 'rgba(0, 0, 0, 0)'; // Transparent color
                    } else {
                        // Apply min-max normalization to each band
                        const r = Math.round(evaluatePixel(values[0]/10000, values[1]/10000, values[2]/10000)[0] * 255);
                        const g = Math.round(evaluatePixel(values[0]/10000, values[1]/10000, values[2]/10000)[1] * 255);
                        const b = Math.round(evaluatePixel(values[0]/10000, values[1]/10000, values[2]/10000)[2] * 255);


                        // Return RGB color
                        return `rgba(${r},${g},${b},1)`;
                    }
                }
            });

            layer.addTo(map);
            map.fitBounds(layer.getBounds());
        });
    }
</script>
</body>
</html>

The CRS EPSG 2056 breaks the map

Any solution for it?

2

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.