Границы полей редко поступают в идеальном виде. Launch Pad пропускает каждую границу через автоматический конвейер коррекции геометрии, который обнаруживает некорректные фигуры и исправляет их до начала планирования, поэтому планы проходов всегда строятся на чистой, корректной геометрии.
Некорректная геометрия на удивление часто встречается в реальных данных о границах, и в большинстве случаев её не видно на карте: самопересечение может скрываться в одной-единственной вершине. Большинство клиентов даже не догадываются о таких проблемах в своих границах, потому что Launch Pad исправляет их автоматически. Если вы интегрируетесь с API и не понимаете, почему полученная обратно граница немного отличается от отправленной, эта страница объясняет, что произошло и почему.
Рисование полигона на карте с последующим добавлением, удалением или перетаскиванием вершин может привнести самопересечения и наложения без каких-либо видимых признаков.
Границы, изменённые подключёнными платформами (например, John Deere Operations Center), могут возвращаться топологически некорректными.
Загруженные файлы иногда содержат лишние точки, линии или коллекции геометрий вместо чистых полигонов.
Большинство ГИС-платформ исправляют повреждённую геометрию одной операцией "make valid" (автоматическим приведением геометрии к корректному виду). Она устраняет топологическую ошибку, но действует грубо и никак не учитывает, насколько пригодной окажется граница поля после исправления. Launch Pad вместо этого применяет последовательность целевых исправлений, а общее исправление "make valid" оставляет как запасной вариант для случаев, с которыми целевые методы не справляются.
Точки, линии и другая неплощадная геометрия удаляются, чтобы дальше проходили только полигоны.
Самопересекающиеся внешние границы разделяются на отдельные корректные полигоны вместо отбрасывания части поля.
Перекрывающиеся или пересекающиеся отверстия объединяются в одно отверстие, как того требует спецификация.
Кольца буферизуются с небольшим допуском, чтобы отверстия никогда не имели общих рёбер с внешней границей.
Отверстия вычитаются из внешних границ для пересборки чистого MultiPolygon, при этом любое отверстие, выходящее за пределы своей оболочки, обрезается.
Мелкие фрагменты площадью меньше минимальной отбрасываются, если только они не являются единственной частью поля.
Порядок обхода колец соответствует правилу правой руки GeoJSON, координаты приводятся к 2D, а любые значения высоты удаляются.
Универсальное исправление "make valid" обрабатывает самопересечения и другие ошибки, которые остаются после целевых шагов.
Результатом работы конвейера всегда является валидный MultiPolygon, соответствующий правилам валидности полигонов и MultiPolygon согласно OGC Simple Features Specification:
Внешняя граница полигона. У каждого полигона она ровно одна.
Внутренняя граница, вырезанная из полигона, например заболоченный участок или груда камней. У полигона может быть много отверстий.
Набор полигонов. Поле из двух отдельных участков представляет собой один MultiPolygon с двумя полигонами.
Операция объединения геометрий: слияние перекрывающихся фигур в одну.
Если входные данные невозможно спасти, например когда после удаления некорректных частей ничего не остаётся, Launch Pad сообщает об ошибке, а не придумывает фигуру, и каждый шаг коррекции записывается в журнал, чтобы результат можно было проверить.
Примечание: Обработка выполняется в проекционной системе координат, где расстояния измеряются в метрах, а результат преобразуется обратно в WGS84. Именно поэтому допуски буферизации задаются в метрах, а не в градусах.
Пять характерных случаев некорректной входной геометрии (синим) и исправленного результата (жёлтым). Разверните WKT, чтобы увидеть точные координаты.
На входе вместо MultiPolygon поступает GeometryCollection, и наряду с самим полигоном она содержит LineString и Point. Линия и точка удаляются, а из полигона извлекается внешнее кольцо.
GEOMETRYCOLLECTION (LINESTRING (131 125, 305 326),
POINT (260 130),
POLYGON ((130 330, 223 330, 223 245, 130 245, 130 330)))
MULTIPOLYGON (((130 330, 223 330, 223 245, 130 245, 130 330)))
Внешнее кольцо пересекает само себя, образуя фигуру в виде бабочки. Это не корректный полигон, и многие планировщики отклонили бы его или молча отбросили бы одну из долей. Механизм очистки разделяет кольцо в точке пересечения на два корректных полигона, сохраняя всю нарисованную область.
POLYGON ((120 110, 120 360, 340 130, 310 360, 120 110))
MULTIPOLYGON (((120 110, 120 360, 225.87639311043566 249.3110435663627, 120 110)),
((225.87639311043566 249.3110435663627, 310 360, 340 130, 225.87639311043566 249.3110435663627)))
Два внутренних кольца пересекаются друг с другом, что запрещено спецификацией. Отверстия объединяются в одно, и полигон пересоздаётся с единственным объединённым отверстием.
-- outer boundary
POLYGON ((130 460, 550 460, 550 30, 130 30, 130 460))
-- inner boundary
MULTIPOLYGON (((230 110, 410 290, 470 100, 230 110)),
((370 380, 400 140, 200 200, 370 380)))
MULTIPOLYGON (((130 460, 550 460, 550 30, 130 30, 130 460),
(292.3076923076923 172.30769230769232, 200 200, 370 380, 384.44444444444446 264.44444444444446, 410 290, 470 100, 230 110, 292.3076923076923 172.30769230769232)))
Несколько внешних колец перекрываются и самопересекаются, замыкая при этом пустую область. Кольца буферизуются и объединяются в единый контур, а замкнутая область сохраняется как полноценное отверстие.
MULTIPOLYGON (((107 153, 134.3 153, 134.3 121.6, 107 121.6, 107 153),
(120 147, 120 176.2, 130.5 176.2, 130.5 147, 120 147)),
((125 174, 163 174, 163 168, 125 168, 125 174)),
((157.5 178.6, 191 178.6, 191 156, 157.5 156, 157.5 178.6),
(170 166, 185 166, 185 135, 170 135, 170 166)),
((180 140, 180 136, 120 136, 120 140, 180 140)))
MULTIPOLYGON (((170 136, 134.3 136, 134.3 121.6, 107 121.6, 107 153, 120 153, 120 176.2, 130.5 176.2, 130.5 174, 157.5 174, 157.5 178.6, 191 178.6, 191 156, 185 156, 185 135, 170 135, 170 136),
(130.5 168, 130.5 153, 134.3 153, 134.3 140, 170 140, 170 156, 157.5 156, 157.5 168, 130.5 168)))
У поля два отдельных внешних кольца, и отверстия их не учитывают: одно отверстие перекрывает промежуток между двумя оболочками, а другие выступают за края. Каждая оболочка пересобирается отдельно, и каждое отверстие обрезается по содержащей его оболочке, с небольшим буфером, чтобы ни одно отверстие не имело общего ребра со своей оболочкой.
-- outer boundary
MULTIPOLYGON (((104 199, 165 199, 165 125, 104 125, 104 199)),
((170 150, 195 150, 195 132, 170 132, 170 150)))
-- inner boundary
MULTIPOLYGON (((158.44444444444446 144.33333333333334, 174 144.33333333333334, 174 139, 158.44444444444446 139, 158.44444444444446 144.33333333333334)),
((101 169, 159 169, 159 165, 101 165, 101 169)),
((136 122, 109.44444444444444 122, 109.44444444444444 151.55555555555554, 136 151.55555555555554, 136 122)))
MULTIPOLYGON (((170 150, 195 150, 195 132, 170 132, 170 150),
(170.0010000000475 144.33333333333334, 174 144.33333333333334, 174 139, 170.0010000000475 139, 170.0010000000475 144.33333333333334)),
((104 199, 165 199, 165 125, 104 125, 104 199),
(109.44444444444444 125.0010000000475, 109.44444444444444 151.55555555555554, 136 151.55555555555554, 136 125.0010000000475, 109.44444444444444 125.0010000000475),
(164.9989999999525 139, 158.44444444444446 139, 158.44444444444446 144.33333333333334, 164.9989999999525 144.33333333333334, 164.9989999999525 139),
(104.0010000000475 169, 159 169, 159 165, 104.0010000000475 165, 104.0010000000475 169)))