No description
Find a file
2026-02-06 15:21:49 +03:00
docs first commit 2026-02-06 15:21:49 +03:00
.gitignore first commit 2026-02-06 15:21:49 +03:00
error_handling_test.go first commit 2026-02-06 15:21:49 +03:00
example_test.go first commit 2026-02-06 15:21:49 +03:00
geojson_support.go first commit 2026-02-06 15:21:49 +03:00
geojson_support_test.go first commit 2026-02-06 15:21:49 +03:00
go.mod first commit 2026-02-06 15:21:49 +03:00
import_test.go first commit 2026-02-06 15:21:49 +03:00
LICENSE first commit 2026-02-06 15:21:49 +03:00
point_in_ring.go first commit 2026-02-06 15:21:49 +03:00
point_in_ring_test.go first commit 2026-02-06 15:21:49 +03:00
README.md first commit 2026-02-06 15:21:49 +03:00
types.go first commit 2026-02-06 15:21:49 +03:00

geocheck

Минималистичный, суверенный Go-модуль для проверки попадания точки в Polygon и MultiPolygon. Цель: максимальная надёжность, нулевые зависимости, 100% покрытие тестами.

Особенности

  • Проверка принадлежности точки многоугольнику (Polygon) и мульти-многоугольнику (MultiPolygon)
  • Использование классического алгоритма Ray Casting
  • Нулевые внешние зависимости
  • Полностью покрыт unit-тестами
  • Поддержка структур, совместимых с GeoJSON

Установка

go get git.ymnuktech.ru/ymnuk/go-geocheck

Использование

PointInPolygon

package main

import (
    "fmt"
    "git.ymnuktech.ru/ymnuk/go-geocheck"
)

func main() {
    // Пример: проверка точки в прямоугольнике
    point := geocheck.Point{X: 0.5, Y: 0.5}
    rectangle := [][]geocheck.Point{
        {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}, // внешнее кольцо
    }

    inside := geocheck.PointInPolygon(point, rectangle)
    fmt.Printf("Точка внутри прямоугольника: %t\n", inside) // true
    
    // Пример: проверка точки в полигоне с дырой
    pointInHole := geocheck.Point{X: 0.5, Y: 0.5}
    polygonWithHole := [][]geocheck.Point{
        {{0, 0}, {2, 0}, {2, 2}, {0, 2}, {0, 0}},                    // внешнее кольцо
        {{0.25, 0.25}, {0.75, 0.25}, {0.75, 0.75}, {0.25, 0.75}, {0.25, 0.25}}, // дыра
    }
    
    insideHole := geocheck.PointInPolygon(pointInHole, polygonWithHole)
    fmt.Printf("Точка внутри полигона с дырой: %t\n", insideHole) // false, потому что точка в дыре
}

PointInMultiPolygon

package main

import (
    "fmt"
    "git.ymnuktech.ru/ymnuk/go-geocheck"
)

func main() {
    // Пример: проверка точки в мультиполигоне
    point := geocheck.Point{X: 0.5, Y: 0.5}
    multiPolygon := [][][]geocheck.Point{
        {
            {{0, 0}, {1, 0}, {1, 1}, {0, 1}, {0, 0}}, // первый полигон
        },
        {
            {{2, 2}, {3, 2}, {3, 3}, {2, 3}, {2, 2}}, // второй полигон
        },
    }

    inside := geocheck.PointInMultiPolygon(point, multiPolygon)
    fmt.Printf("Точка внутри одного из полигонов мультиполигона: %t\n", inside) // true
}

Алгоритм

Модуль использует классический алгоритм Ray Casting (прострел лучом), основанный на even-odd rule. Алгоритм проверяет, сколько рёбер многоугольника пересекает луч, выпущенный из проверяемой точки. Если количество пересечений нечётное, точка находится внутри многоугольника.

Точка, находящаяся на границе (ребре или вершине) многоугольника, считается внешней.

Поддерживаемые структуры

  • Point: точка с координатами X, Y (float64)
  • PointInPolygon: проверка точки в многоугольнике с возможными дырами
  • PointInMultiPolygon: проверка точки в наборе многоугольников

Ограничения

  • Ожидается, что кольца многоугольников будут замкнуты
  • Координаты обрабатываются как плоские (не учитываются проекции)
  • Не поддерживаются самопересекающиеся полигоны (ожидается валидный GeoJSON)
  • Точки на границах считаются внешними

Лицензия

MIT License