Search code examples
openlayersopenlayers-5turfjs

How to clip and show clipped vector geometry in OpenLayers 5.3.0


I have to clip vector layer based on the main/restriction vector layer. Upon drawing, if some part of the drawn layer is outside restriction layer, clip area that is outside restriction layer.

Example 1. As we can see, part of the bottom border is outside restriction (purple layer)

enter image description here

I'm wondering if it is possible upon adding feature to clip area that is outside restriction layer

Example 2. Removing area that is outside restriction layer (green color)

enter image description here

I tried to calculate geometry using bboxPolygon function from (Turf.js) library. Even tried with booleanWithin to detect if the drawn polygon is outside restriction layer but to no avail.

Now, I'm wondering if it is possible to clip area then upon addfeature render clipped area within restriction layer (as shown in example 2)

Here is code snippet that I used to somehow detect if area is clipped or if is it within restriction layer.

// detect if drawn layers is outside restriction layer
vectorDrawLayer.getSource().on('addfeature', (evt) => {
  let feature = evt.feature;
  //let coordinatess = feature.getGeometry().clone().transform('EPSG:3857', 'EPSG:4326').getCoordinates();

  let geojsonFormat = new GeoJSON();

  let firstGeometryObject = {};
  let secondGeometryObject = {};

  if (vectorDrawLayer.getSource().getState() === 'ready') {
    let firstGeometry = vectorDrawLayer.getSource().getFeatures()[0];
    let secondGeometry = restrictionLayer.getSource().getFeatures()[0];

    firstGeometryObject = geojsonFormat.writeFeatureObject(firstGeometry, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });

    secondGeometryObject = geojsonFormat.writeFeatureObject(secondGeometry, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });
  }

  let isWithin = booleanWithin(firstGeometryObject, secondGeometryObject)
  let clipped = bBoxclip(firstGeometryObject, transformedExtent);

  //console.log(JSON.stringify(firstGeometryObject))
  console.log(clipped.geometry.coordinates);
  console.log(isWithin);
})

UPDATE:

I was able to extract only polygon that is within restriction layer using http://turfjs.org/docs/#intersect but now I'm having problem rendering only intersected layer.

Initially, I wanted do delete layer source, then upon getting intersecting polygon coordinates I want to add new intersected polygon geometry (without outside area) but I can't render anything (seems that I'm missing something)

Here is code snippet:

  let geojsonFormat = new GeoJSON();
  let firstGeometryObject = {};
  let secondGeometryObject = {};
  let feature;
  if (vectorDrawLayer.getSource().getState() === 'ready') {

    let firstGeometry = vectorDrawLayer.getSource().getFeatures()[0];
    let secondGeometry = restrictionLayer.getSource().getFeatures()[0];


    firstGeometryObject = geojsonFormat.writeFeatureObject(firstGeometry, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });

    secondGeometryObject = geojsonFormat.writeFeatureObject(secondGeometry, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });

    let intersectTest = intersect(firstGeometryObject, secondGeometryObject);

    let polygon = new Polygon(intersectTest.geometry.coordinates)

    feature = new Feature({
      geometry: polygon,
      name: 'test BlaBla'
    });
    console.log(feature)
    vectorDrawSource.removeFeature(firstGeometry);
    vectorDrawSource.addFeatures(feature);
  }

Here is link to test app (update): https://stackblitz.com/edit/js-vpdnbf


Solution

  • Ok, I've figure it out. Using intersect function I got intersected feature object by passing transformed GeoJSON objects into functions.

    Example:

    let secondGeometryObject = secondGeometryObject = geojsonFormat.writeFeatureObject(secondGeometry, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });
    

    Then creating new polygon using coordinates from intersected feature object.

    let intersectPolygon = intersect(firstGeometryObject, secondGeometryObject);
    
    let polygon = new Polygon(intersectPolygon.geometry.coordinates)
    

    Then, I transformed polygon and fetch transformed coordinates ('EPSG:4326')

    let transformedPoly = polygon.clone().transform('EPSG:4326', 'EPSG:3857').getCoordinates();
    

    And finally set newly fetched coordinates into event feature

    evt.feature.getGeometry().setCoordinates(transformedPoly);
    

    Or, we can use something like this:

    // transforming polygon to epsg:3857
    let transformedPoly = polygon.clone().transform('EPSG:4326', 'EPSG:3857');
    // set newly transformed polygon to feature
    evt.feature.setGeometry(transformedPoly);
    

    Here is fixed solution:

    enter image description here

    If someone is having better idea how to clip and fetch coordinates feel free to post answer, I ll definitely upvote :) Hope it helps someone :)

    Updated link to app is here: https://stackblitz.com/edit/js-vpdnbf