0

As shown in the below posted code, I am trying to overlay particular geomerty/feature with a GeoTIFF, the code posted below succeeded in achieving that. However, as shown in the below posted screen-shot, not only the intersected part of the GeoTIFF and the geomerty/feature is being displayed, but also un-intersected areas which is black.

To eliminate the black regions that do not interesect with the geometry/feature, i set the nodata property to 0, but it has not achieved the task.

What i want to achieve is, to eliminate the black regions from the GeoTIFF and make it transparent, i want to display only the GeoTIFF that intersects with the geomerty/feature.

Can i be done via applying some kind of masking operation?

Code:

addTileLayerToMap(map, source, constrainedExtent) {
    if (source) {
        const tileLayer = new TileLayerWebGL({
            source: source,
        });

        if (tileLayer) {
            map.addLayer(tileLayer);
            map.setView(source.getView().then((v) => {
                v.resolution = v.resolutions[v.zoom];
                // v.extent = constrainedExtent;
                delete v.extent;
                delete v.resolutions;
                delete v.zoom; 
                return v;
            }));
        }
        
    }
}

geoTIFFSource = new GeoTIFF({
    wrapX: false,
    normalize: false,
    sources: [
      {
        blob: res,
        // nodata: 0,
      },
    ],
});

this.#mapBuilderInstance.addTileLayerToMap(
     this.#mapInstance, 
     geoTIFFSource,
     this.listenToExtentOfDigitizedGeomForIndex(this.#featureRecentlyHovered.get(DigitizePolygonConstants.CONST_DIGITIZED_FEATURE_PROPERTY_GEOM_ORDER.description) - 1)
 );

Geometry/feature:

enter image description here

GeoTIFF-overlay:

enter image description here

update:

for the following options of GeoTIFF, when set, i received the output mentioned in section ouput-0. now the black pixel has been eliminated but what overlays the geometry/feature oblitrates the actual contents. how to show the original overlay of the tiff and not just white pixels?

geoTIFFSource = new GeoTIFF({
    wrapX: false,
    normalize: false,
    sources: [
      {
        blob: res,
        nodata: NaN,
      },
    ],
});

ouput-0:

enter image description here

update-2

now with the following options set to GeoTIFF, the result is as shown in output-2:

geoTIFFSource = new GeoTIFF({
    wrapX: false,
    normalize: true,
    sources: [
      {
        blob: res,
        nodata: NaN,
      },
    ],
});

ouput-2:

enter image description here

1 Answer 1

1

If you really want to clip a GeoTIFF to a vector I think the only way to do it is make the GeoTIFF layer the source for a Raster source in an Image layer and use that in the same way as in the OpenLayers vector clipping example https://openlayers.org/en/latest/examples/layer-clipping-vector.html

import GeoJSON from 'ol/format/GeoJSON.js';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {Fill, Style} from 'ol/style.js';
import {GeoTIFF, OSM, Raster, Vector as VectorSource} from 'ol/source.js';
import {
  Image as ImageLayer,
  WebGLTile as TileLayer,
  Vector as VectorLayer,
} from 'ol/layer.js';
import {fromLonLat} from 'ol/proj.js';
import {getVectorContext} from 'ol/render.js';

const background = new TileLayer({
  source: new OSM(),
});

const tilelayer = new TileLayer({
  source: new GeoTIFF({
    sources: [
      {
        url:
          'https://s2downloads.eox.at/demo/EOxCloudless/2020/rgbnir/s2cloudless2020-16bits_sinlge-file_z0-4.tif',
        bands: [1, 2, 3],
        min: 0,
        max: 3000,
      },
    ],
  }),
});

const base = new ImageLayer({
  source: new Raster({
    sources: [tilelayer],
    operation: (a) => a[0],
    resolutions: null,
  }),
});

const clipLayer = new VectorLayer({
  style: null,
  source: new VectorSource({
    url: './data/geojson/switzerland.geojson',
    format: new GeoJSON(),
  }),
});

//Giving the clipped layer an extent is necessary to avoid rendering when the feature is outside the viewport
clipLayer.getSource().on('addfeature', function () {
  base.setExtent(clipLayer.getSource().getExtent());
});

const style = new Style({
  fill: new Fill({
    color: 'black',
  }),
});

base.on('postrender', function (e) {
  const vectorContext = getVectorContext(e);
  e.context.globalCompositeOperation = 'destination-in';
  clipLayer.getSource().forEachFeature(function (feature) {
    vectorContext.drawFeature(feature, style);
  });
  e.context.globalCompositeOperation = 'source-over';
});

const map = new Map({
  layers: [background, base, clipLayer],
  target: 'map',
  view: new View({
    center: fromLonLat([8.23, 46.86]),
    zoom: 7,
  }),
});

Working example https://codesandbox.io/s/layer-clipping-vector-forked-pd2d3f?file=/main.js

If it is simply a matter of eliminating unwanted black and do not know the nodata value it would be better to workaround it by styling the output.

15
  • thank you. do you think that the nodata option does not work due to the contents of the tiff file?i mean, could it be that the tiff file i receive does not have nodata pixel set as undefined?!
    – Amr
    Commented Apr 29 at 11:16
  • 0 and NaN are common values to try, but it could be anything. You could check what values are in that region by using layer.getData() as in openlayers.org/en/latest/examples/cog-math.html You would want the raw values so display using output.textContent = data.join(' '); and normalize: false,
    – Mike
    Commented Apr 29 at 11:32
  • would you please have a look at the update section i added to the question above?
    – Amr
    Commented Apr 29 at 11:50
  • NaN seems to be the correct value to use, but with normalize: false you usually need a style (e.g. a colorramp interpolation) to display the data. To revert to grayscale use normalize: true.
    – Mike
    Commented Apr 29 at 12:09
  • 1
    It works for me codesandbox.io/s/cog-blob-forked-vmnfnc?file=/main.js
    – Mike
    Commented Apr 30 at 11:35

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.