У меня возникла проблема с рендерингом многоугольника из источника векторного фрагмента при высоких уровнях масштабирования. Я использую https://github.com/NetTopologySuite/NetTopologySuite.IO.VectorTiles для создания плиток и подтвердил с помощью простого vuejs, используя пакет npm @mapbox/vector-tile, что я вижу то, что ожидается ( простой четырехгранный многоугольник), поэтому я уверен, что векторные плитки мапбокса сгенерированы правильно.
Я добавил 3 разных образца полигонов, которые я создал как отдельную коллекцию объектов в файле json, преобразовал в векторный файл и визуализировал с помощью простого HTML для карт Azure с одним источником векторных листов плюс слоем линии/заливки. Страница также отображает сетку плиток и отображает информацию о плитке.
Каждый образец представляет собой один и тот же многоугольник, но каждый раз немного длиннее. Как показано на изображениях, рендеринг ухудшается с увеличением размера многоугольника.
Моя интуиция подсказывает, что генерация плитки может быть неправильной, но просмотр плитки в отдельном приложении vuejs, похоже, опровергает эту мысль. Конечно, я могу ошибаться, и мне кажется невероятным, что такой простой многоугольник может стать проблемой для azuremaps/maplibre.
Любые идеи, что может быть не так, пожалуйста, поскольку я застрял на этом этапе.
Редактировать:
Я загрузил те же файлы mvt sample3 в qgis (3.36.3), и они отлично отрисовываются. Тогда это будет означать, что с генерацией тайлов все в порядке, и проблема в рендеринге в Maplibre?
Редактировать 2:
Вот репозиторий плиток для sample3.json: Репозиторий тестовых файлов MVT
Кажется, что Sample1 работает нормально:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": 1,
"featureName": "pedestrian"
},
"geometry": {
"coordinates": [
[
[
153.02303214664835,
-27.47153798017556
],
[
153.02361397317628,
-27.472110106801587
],
[
153.02413908737213,
-27.471707568508087
],
[
153.02356566267133,
-27.471135439790835
],
[
153.02303214664835,
-27.47153798017556
]
]
],
"type": "Polygon"
}
}
]
}
Sample2 начинает видеть некоторые проблемы с рендерингом:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": 1,
"featureName": "pedestrian"
},
"geometry": {
"coordinates": [
[
[
153.02303214664835,
-27.47153798017556
],
[
153.0239584480898,
-27.472482826140364
],
[
153.02448566274165,
-27.472082152801704
],
[
153.02356566267133,
-27.471135439790835
],
[
153.02303214664835,
-27.47153798017556
]
]
],
"type": "Polygon"
}
}
]
}
Sample3 сейчас довольно плох:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"id": 1,
"featureName": "pedestrian"
},
"geometry": {
"coordinates": [
[
[
153.02303214664835,
-27.47153798017556
],
[
153.0243377004698,
-27.472866763505785
],
[
153.0248843639639,
-27.47245746377172
],
[
153.02356566267133,
-27.471135439790835
],
[
153.02303214664835,
-27.47153798017556
]
]
],
"type": "Polygon"
}
}
]
}





Azure Maps использует MapLibre для рендеринга векторных плиток под обложками, а MapLibre — это ответвление MapBox GL JS, поэтому я был бы удивлен, если бы проблема возникла именно здесь.
Я подозреваю, что проблема связана с библиотекой NetTopologySuite.IO.VectorTiles. Заглянув в этот репозиторий, я вижу запрос на включение проблемы, которая кажется связанной: https://github.com/NetTopologySuite/NetTopologySuite.IO.VectorTiles/pull/30
Эта проблема также может быть связана: https://github.com/NetTopologySuite/NetTopologySuite.IO.VectorTiles/issues/29
Обновлять:
Когда я изначально попробовал использовать данные GeoJSON для создания плиток, у меня они сработали нормально. Вот почему я попросил вашу плитку. Покопавшись в этом, я обнаружил, что почти каждый рендеринг векторных тайлов, использующий JavaScript/WebGL, имеет проблемы с рендерингом этих тайлов. Осматривая плитку, кажется, что каждая плитка содержит полный исходный многоугольник. Обычно при создании векторных плиток данные, добавляемые в плитку, обрезаются до области, немного превышающей ограничивающую рамку плитки (обычно на несколько пикселей, чтобы обеспечить визуализацию контуров без появления швов плитки). При осмотре ваших плиток кажется, что каждая плитка представляет собой полноугольную форму, что необычно. При увеличении масштаба многоугольник пересекает несколько плиток. Чтобы правильно отобразиться на карте, карта должна обрезать многоугольник в JavaScript. Карта использует библиотеку Earcut, чтобы сделать это быстро, однако она не так точна, как библиотеки, которые обычно используются при создании тайлов. Это компромисс ради производительности. Когда полигоны между тайлами немного перекрываются, этот метод выреза работает нормально, однако, когда перекрытие сильное, как в этом случае, возникают артефакты, которые вы видите. Это также объясняет, почему эти плитки отлично работают в QGIS, поскольку это собственное настольное приложение, которое использует более мощные библиотеки для обрезки полигонов и может выполнять это намного быстрее, чем JavaScript.
Итак, решение этой проблемы — обрезать данные многоугольника в ограничивающую рамку, размер которой немного больше, чем каждый фрагмент, к которому они добавляются. Я делаю это автоматически при создании тайлов просто для повышения производительности, поскольку большинство моих полигонов имеют более 4 координат, поэтому их обрезка снижает сложность данных в каждом тайле и обычно делает их намного меньшими по размеру файла. Я предполагаю, что у вас уже есть код для импорта вашего GeoJSON и чтения его как функций NetTopologySuite. Вот краткий пример того, как взять функцию NetTopologySuite, вырезать ее геометрию и записать ее в плитку.
//Define the tile info.
var tileInfo = new NetTopologySuite.IO.VectorTiles.Tiles.Tile(x, y, zoom);
//Create vector tile for the tile info. Normally you woult use VectorTileTree if creating a tiles over an area.
var vectorTile = new NetTopologySuite.IO.VectorTiles.VectorTile(){
TileId = tileInfo.Id
};
//Add a layer to the vector tile.
//As an optimization, you could wait to see if any polygons intersect the tile before adding a layer.
var myDataLayer = new NetTopologySuite.IO.VectorTiles.Layer()
{
Name = "myDataLayer"
};
vectorTile.Layers.Add(myDataLayer);
//Decide how much to buffer the bounding box of a tile, in percentage.
//Usually a number between 2 and 5 is plenty for lines and polygons.
//For points, you may want to use a higher number depending on size of icons being used.
var tileBufferPercentage = 3;
//Get a polygon for a buffered bounding box of the tile.
var tilePolygon = tileInfo.ToPolygon(tileBufferPercentage);
//Check to see if the polygon intersects the tile. No sense adding polygon to tile otherwise.
if (polygonFeature.Geometry.Intersects(tilePolygon))
{
//Clip the polygon to the input polygon, by finding the intersection.
//Don't overwrite the polygonFeature.Geometry otherwise it will cause issues for other tiles.
var clippedPolygon = polygonFeature.Geometry.Intersection(tilePolygon);
//Add the clipped polygon to the layer.
myDataLayer.Features.Add(new NetTopologySuite.Features.Feature(clippedPolygon, polygonFeature.Attributes));
}
Я обновил вопрос информацией о тесте qgis, который работает нормально. Можете ли вы протестировать векторную визуализацию полигона образца 3 с помощью z19 на картах Azure и qgis для сравнения?
Не могли бы вы предоставить векторные тайлы для тестирования? Либо в качестве включенной конечной точки COR, либо в виде загружаемого файла где-нибудь (OneDrive, Dropbox...)
Я добавил репозиторий с файлами mvt, сгенерированными из ветки Issue29 — см. Редактирование 2, о котором идет речь. Спасибо, что заглянули.
Обновленный пост с решением
Потрясающее объяснение. Я просто предположил, что геометрия обрезается. Я попробую клип и отмечу ваше решение как ответ. Спасибо за вашу помощь в этом.
Я согласен с вами @rbrundritt, очень сомнительно, что это Maplibre/mapbox. Это, безусловно, связано с этой проблемой, и именно поэтому я тоже попробовал код извлечения (на самом деле это показанные плитки), но, похоже, не решил проблему, которую я вижу.