Как точно проверить, перекрывает ли один многоугольник другой, игнорируя границу

У меня есть один вопрос относительно топологии и отношений между полигонами в открытых слоях.

Ситуация такая:  введите описание изображения здесь

Используя https://turfjs.org/, я использую два метода, чтобы проверить, перекрываются ли многоугольники, https://turfjs.org/docs/#booleanOverlap и https://turfjs.org/docs/#booleanWithin, но я получаю странное взаимодействие.

Как видите, в синем прямоугольнике многоугольник привязан к красному многоугольнику, и это нормально, но проблема связана с многоугольниками в желтом прямоугольнике, для них я получаю true и автоматически перекрывающийся красный стиль. Полигоны синего цвета и многоугольники желтого прямоугольника привязаны только к границе красного многоугольника.

Итак, у меня такой вопрос; Можно ли как-то игнорировать границу ограничивающего многоугольника (красный) или мне следует найти другой подход.

Пример кода, который я проверяю, не перекрываются ли многоугольники:

 vectorLayer.getSource().on(OpenLayersEvents.AddFeature, (evt: any) => {


            let feature = evt.feature;


            // clip area function with return geometry value
            let polygon = clipFieldArea(feature, this.myRestrictionVectorLayer);


            let isFeatureOverlappingFlag = false;
            //red polygons
            if (this.restrictiveLayer.getSource().getFeatures().length > 0) {
                isFeatureOverlappingFlag = arePolygonsOverlapping(feature, this.restrictiveLayer); 
            }

            // checks if features are overlapping then set new style
            feature.getGeometry().setCoordinates(polygon.getCoordinates());
            if (isFeatureOverlappingFlag) {
                feature.setStyle(this.featureOverlappingStyle);
            } else {
                feature.setStyle(this.fieldStyle);
            }....

А вот метод arePolygonsOverlapping (), который проверяет топологию.

   let geojsonFormat = new GeoJSON();

    let areOverlapping: boolean = false;

    let flagCheck: boolean = false;
    let restrictionFeatures = restrictionLayer.getSource().getFeatures();

    // create GeoJSON object and transform it in WGS84 for intersect method
    let firstGeometryObject = geojsonFormat.writeFeatureObject(feature, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' });

    for (let featureRestrict of restrictionFeatures) {

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

        areOverlapping = booleanOverlap(firstGeometryObject as unknown as TurfPolygon, secondGeometryObject as unknown as TurfPolygon);

        if (areOverlapping) {
            flagCheck = true;
            break;
        }
    }
    return flagCheck;

ОБНОВЛЕНИЕ

Я попытался поиграть с решением, предложенным Майком, но получаю Uncaught TypeError: ol_proj__WEBPACK_IMPORTED_MODULE_3__.default.Projection is not a constructor

При попытке создать новую проекцию. А вот и обновленный метод

export function arePolygonsOverlapping(feature: any, restrictionLayer: VectorLayer): boolean {

    let areOverlapping: boolean = false;

    let flagCheck: boolean = false;
    let restrictionFeatures = restrictionLayer.getSource().getFeatures();

    //#region "Parameters for scaling down coordinates"
        let viewProjection = Projection.get('EPSG:3857');
        let smallProjection = Projection.get('small');

    if (!smallProjection) {
        smallProjection = new Projection.Projection({
            code: 'small',
            units: 'm'
        });

        Projection.addProjection(smallProjection);

        let scale = Extent.getWidth(viewProjection.getExtent());

        let smallTransform = function (coordinate: [number, number]) {
            return [coordinate[0] / scale, coordinate[1] / scale];
        }

        let normalTransform = function (coordinate: [number, number]) {
            return [coordinate[0] * scale, coordinate[1] * scale];
        }

        Projection.addCoordinateTransforms(viewProjection, smallProjection, smallTransform as any, normalTransform as any);

    }
    //#endregion "Parameters for scaling down coordinates"


    // create GeoJSON object and transform it in WGS84 for intersect method
    let firstGeometryObject = geojsonFormat.writeFeatureObject(feature, { dataProjection: smallProjection, featureProjection: viewProjection  });

    for (let featureRestrict of restrictionFeatures) {

        let secondGeometryObject = geojsonFormat.writeFeatureObject(featureRestrict,
            { dataProjection: smallProjection, featureProjection: viewProjection  });

        areOverlapping = booleanOverlap(firstGeometryObject as unknown as TurfPolygon, secondGeometryObject as unknown as TurfPolygon);

        if (areOverlapping) {
            flagCheck = true;
            break;
        }
    }
    return flagCheck;
}

Вот мой импорт:

import Extent from 'ol/extent';
import Projection from 'ol/proj';

Забыл сказать, что использую v 4.6.2


person Svinjica    schedule 24.09.2019    source источник
comment
Вам нужно изменить проекцию в writeFeatureObject? То, что перекрывается в одной проекции, может не совпадать в другой. - см. gis.stackexchange.com/questions/308871/   -  person Mike    schedule 25.09.2019
comment
@Mike Привет, Майк, спасибо за ответ. Я считаю, что должен, потому что библиотека Turf ожидает, что данные будут стандартными координатами долготы и широты WGS84.   -  person Svinjica    schedule 25.09.2019
comment
Это определенно проблема с некоторыми функциями газона (особенно если они работают с допусками), в то время как другие просто работают с предоставленными числами. при необходимости вы можете определить фиктивную проекцию, которая уменьшает ваши координаты EPSG: 3857 до достаточно малых значений, чтобы turf обрабатывал их WGS84, не влияя на форму, как обычно, как при перепроецировании - см. gis.stackexchange.com/questions/317657/   -  person Mike    schedule 25.09.2019
comment
@Mike Спасибо. Я также думал о другом подходе, скажем, с использованием JSTS или как-то определить, перекрывается ли граница   -  person Svinjica    schedule 25.09.2019
comment
@Mike Mike, просто вставьте свой комментарий в ответ с примером кода, чтобы принять его   -  person Svinjica    schedule 25.09.2019


Ответы (2)


Я тестировал booleanOverlap, и хотя кажется, что он работает с числами из любой проекции, для соответствия спецификации газона было бы целесообразно придерживаться небольших чисел, уменьшая координаты EPSG: 3857 без преобразования в проекцию, которая изменяет полигон. формы. Преобразования масштабирования также могут быть проще, чем в ссылках на комментарии.

import { getWidth } from 'ol/extent';
import { Projection, addCoordinateTransforms, addProjection, get as getProjection } from 'ol/proj';

....
....


let viewProjection = getProjection('EPSG:3857');
let smallProjection = getProjection('small');

if (!smallProjection) {

    smallProjection = new Projection({
        code: 'small',
        units: 'm'
    });
    addProjection(smallProjection);

    let scale = getWidth(viewProjection.getExtent());

    let smallTransform = function(coordinate) {
        return [coordinate[0] / scale, coordinate[1] / scale];
    }

    let normalTransform = function(coordinate) {
        return [coordinate[0] * scale, coordinate[1] * scale];
    }

    addCoordinateTransforms(viewProjection, smallProjection, smallTransform, normalTransform);

}

let geojsonFormat = new GeoJSON();

let areOverlapping: boolean = false;

let flagCheck: boolean = false;
let restrictionFeatures = restrictionLayer.getSource().getFeatures();

// create GeoJSON object and transform it in WGS84 for intersect method
let firstGeometryObject = geojsonFormat.writeFeatureObject(feature, { dataProjection: smallProjection, featureProjection: viewProjection });

for (let featureRestrict of restrictionFeatures) {

    let secondGeometryObject = geojsonFormat.writeFeatureObject(featureRestrict,
        { dataProjection: smallProjection, featureProjection: viewProjection });

    areOverlapping = booleanOverlap(firstGeometryObject as unknown as TurfPolygon, secondGeometryObject as unknown as TurfPolygon);

    if (areOverlapping) {
        flagCheck = true;
        break;
    }
}
return flagCheck;
person Mike    schedule 25.09.2019
comment
Майк, спасибо за ваши усилия, но я получаю сообщение об ошибке при попытке создать новую проекцию. - person Svinjica; 02.10.2019

Хорошо, я выбрал другой путь в этом вопросе. Вместо «исправления» и настройки координат (тем не менее, в ответе Майка было красиво указано, что мы должны уменьшить координаты)

Я просто использовал метод пересечения Turf и проверял, есть ли пересекающиеся объекты с дополнительной проверкой области.

Этот подход охватывает большинство случаев, которые я пробовал.

let isIntersecting: boolean = false;

let flagCheck: boolean = false;
let restrictionFeatures = restrictionLayer.getSource().getFeatures();

// create GeoJSON object and transform it in WGS84 for intersect method
let firstGeometryObject = geojsonFormat.writeFeatureObject(feature, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }) as unknown as TurfPolygon;

for (let featureRestrict of restrictionFeatures) {

    let secondGeometryObject = geojsonFormat.writeFeatureObject(featureRestrict,
        { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' }) as unknown as TurfPolygon;

    // get intersected polgon
    let intersectPolygon = intersect(firstGeometryObject, secondGeometryObject);

    if (intersectPolygon != null) {
        isIntersecting = true;

        // calculate value of intersected area
        let areaValue: number = area(intersectPolygon as unknown as AllGeoJSON);

        // area below 10 meters is considered overlapping
        if (areaValue < 10) {
            isIntersecting = false;
        }
    }

    if (isIntersecting) {
        flagCheck = true;
        break;
    }
}
return flagCheck;

введите описание изображения здесь

person Svinjica    schedule 03.10.2019