Как получить маркеры или проверить их наличие в произвольном полигоне в библиотеке "vue-yandex-maps": "^2.0.0-rc.14"?

Опишу суть задачи. Мне нужно реализовать выделение какой-то области с помощью "лассо" на карте, и получить все маркеры в выделенной области(полигоне), с реализацией выделения области с помощью лассо я разобрался и теперь мне нужно каким то образом получить эти маркеры

Использую последнюю версию библиотеки vue-yandex-maps, поэтому используется API яндекс карт 3 версии, поэтому варианты по проверке наличия маркера в области полигона из 2 версий, не подойдут, я пытался...

Map.vue

<template>
    <div class="map">
        <MapTop
            v-if="props.isSelectSeveral"
            :drawButtonActive="drawButtonActive"
            @drawButton="(status) => drawButton(status)"
        />

        <div class="map__wrapper">
            <YandexMap
                v-model="map"
                :settings="{
                    location: {
                      center: [37.54770, 55.643393],
                      zoom: 15,
                    }
                }"
                width="100%"
                height="382px"
            >
                <YandexMapDefaultSchemeLayer />
                <YandexMapDefaultFeaturesLayer />

                <YandexMapMarker
                    v-for="(marker, index) in props.markers"
                    :key="index"
                    :settings="{
                        coordinates: marker.label.coords,
                    }"
                >
                    <div class="marker"></div>
                </YandexMapMarker>

                <YandexMapControls :settings="{ position: 'left' }">
                    <YandexMapZoomControl :settings="{ easing: 'linear' }"/>
                </YandexMapControls>

                <YandexMapControls v-if="aloneItem && !props.isSelectSeveral" :settings="{ position: 'bottom right' }">
                    <YandexMapControlButton>
                        <a
                            :href="`https://maps.yandex.ru/?text=${aloneItem == null ? '55.755864+37.617698' : aloneItem.label.coords.join('+')}`"
                            target="_blank"
                        >
                            Открыть в Яндекс.Картах
                        </a>
                    </YandexMapControlButton>
                </YandexMapControls>

                <YandexMapFeature
                    v-model="polygon"
                    :settings="{
                        id: 'one',
                        geometry: {
                            type: 'Polygon',
                            coordinates: [polygonCoords],
                        },
                        style: {
                            fill: 'rgba(56, 56, 219, 0.5)',
                            stroke: [{ color: '#f00', width: 4 }],
                        }
                    }"
                />
            </YandexMap>

            <canvas
                v-if="props.isSelectSeveral"
                :style="drawButtonActive ? 'display: block' : 'display: none'"
                class="map__canvas"
                ref="mapCanvasRef"
            />
        </div>
    </div>
</template>

<script setup>
    import './Map.scss'

    import {
        YandexMap,
        YandexMapControlButton, YandexMapControls,
        YandexMapDefaultFeaturesLayer,
        YandexMapDefaultSchemeLayer, YandexMapFeature, YandexMapMarker, YandexMapZoomControl
    } from "vue-yandex-maps";

    import {computed, onMounted, ref, shallowRef, toRaw, watch} from "vue";
    import MapTop from "@/components/AppMap/Map/MapTop/MapTop.vue";

    const props = defineProps({
        markers: {
            default: [],
            type: Array
        },
        isSelectSeveral: {
            default: false,
            type: Boolean
        }

    })

    const aloneItem = computed(() => {
        return props.markers.length === 1 ? props.markers[0] : null
    })

    const map = shallowRef(null)

    const drawButtonActive = ref(false)

    const canvasOptions = {
        strokeStyle: '#0000ff',
        lineWidth: 4,
        opacity: 0.7
    };

    const polygon = ref(null)
    const polygonCoords = ref([])
    const tableDataCoords = ref([])
    const mapCanvasRef = ref(null)
    const dataSource = ref(null)

    const drawButton = (status) => {
        if (status) {
            drawButtonActive.value = true
            drawLineOverMap()
                .then(function (coordinates) {
                    // Переводим координаты из 0..1 в географические.
                    coordinates = coordinates.map(function (x) {
                        return [
                            // Широта (latitude).
                            // Y переворачивается, т.к. на canvas'е он направлен вниз.
                            bounds[0][0] + x[0] * (bounds[1][0] - bounds[0][0]),
                            // Долгота (longitude).
                            bounds[0][1] + x[1] * (bounds[1][1] - bounds[0][1]),
                        ];
                    });

                    // Тут надо симплифицировать линию.

                    coordinates = coordinates.filter(function (_, index) {
                        return index % 3 === 0;
                    });

                    // Удаляем старый полигон.
                    if (polygonCoords.value.length > 0) {
                        polygonCoords.value = []
                    }

                    polygonCoords.value = coordinates

                    drawButtonActive.value = false
                });
        } else {
            drawButtonActive.value = false
        }
    }

    const drawLineOverMap = () => {
        const canvas = mapCanvasRef.value
        const ctx2d = canvas.getContext('2d');
        let drawing = false;
        let coordinates = [];

        // Задаем размеры канвасу как у карты.
        const rect = map.value.container.getBoundingClientRect();
        canvas.style.width = rect.width + 'px';
        canvas.style.height = rect.height + 'px';
        canvas.width = rect.width;
        canvas.height = rect.height;

        // Применяем стили.
        ctx2d.strokeStyle = canvasOptions.strokeStyle;
        ctx2d.lineWidth = canvasOptions.lineWidth;
        canvas.style.opacity = canvasOptions.opacity;

        ctx2d.clearRect(0, 0, canvas.width, canvas.height);

        canvas.onmousedown = function (e) {
            // При нажатии мыши запоминаем, что мы начали рисовать и координаты.
            drawing = true;
            coordinates.push([e.offsetX, e.offsetY]);
        };

        canvas.onmousemove = function (e) {
            // При движении мыши запоминаем координаты и рисуем линию.
            if (drawing) {
                const last = coordinates[coordinates.length - 1];
                ctx2d.beginPath();
                ctx2d.moveTo(last[0], last[1]);
                ctx2d.lineTo(e.offsetX, e.offsetY);
                ctx2d.stroke();

                coordinates.push([e.offsetX, e.offsetY]);
            }
        };

        return new Promise(function (resolve) {
            // При отпускании мыши запоминаем координаты и скрываем канвас.
            canvas.onmouseup = function (e) {
                coordinates.push([e.offsetX, e.offsetY]);
                drawing = false;

                coordinates = coordinates.map(function (x) {
                    return [x[0] / canvas.width, x[1] / canvas.height];
                });
                resolve(coordinates);
            };
        });
    }
</script>

Ответы (1 шт):

Автор решения: Виктор Карев

В 3-й версии карт функции определения наличия маркера в полигоне отсутствует, поэтому приходится определять это самостоятельно.

function pointIsInPoly(p, polygon) {
    var isInside = false;
    var minX = polygon[0][0], maxX = polygon[0][0];
    var minY = polygon[0][1], maxY = polygon[0][1];
    for (var n = 1; n < polygon.length; n++) {
        var q = polygon[n];
        minX = Math.min(q[0], minX);
        maxX = Math.max(q[0], maxX);
        minY = Math.min(q[1], minY);
        maxY = Math.max(q[1], maxY);
    }

    if (p[0] < minX || p[0] > maxX || p[1] < minY || p[1] > maxY) {
        return false;
    }

    var i = 0, j = polygon.length - 1;
    for (i, j; i < polygon.length; j = i++) {
        if ((polygon[i][1] > p[1]) !== (polygon[j][1] > p[1]) &&
                p[0] < (polygon[j][0] - polygon[i][0]) * (p[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1]) + polygon[i][0]) {
            isInside = !isInside;
        }
    }

    return isInside;
}

Пример использования, если полигонов несколько:

for (var i = 0; i < markers.length; i++) {
   var point = markers[i].geometry.coordinates;
   if (markers[i].found) {
      var found = false;
      for (var j = 0; j < polygons.length; j++) {
         var polygon = polygons[j].geometry.coordinates[0]; // полигоны без дырок
         if (pointIsInPoly(point, polygon)) {
            found = true;
            break;
         }
      }
      if (!found) {
         markers[i].found = false;
      }
   }
}
→ Ссылка