Точка (лінії рядка) в полігоні за допомогою ogr та Python


10

Зараз я працюю над проектом, в якому мені потрібно побудувати топологічну мережу з особливостей геометрії, які я знаходжу у форм-файлах. Поки що, використовуючи проект з відкритим кодом Бена Рейлі, мені вдалося перетворити рядки рядків у країx networkx, а також виявити тісні функції (як говорять інші рядки) та додати їх до найближчої точки, щоб я міг запускати алгоритми найкоротшого шляху.

Але це добре для одного формату. Однак зараз мені потрібно з'єднати функції з різних форм-файлів у великий мережевий графік. Так, наприклад, якщо точка знаходиться в полігоні, я би з'єднав її (під підключенням я маю на увазі додати мережевий край - add_edge (g.GetPoint (1), g.GetPoint (2)) з точкою в наступному форматі, що також знаходиться в межах багатокутника, який поділяє аналогічний атрибут (скажімо, ID). Зверніть увагу, що багатокутники в різних shps мають лише однакові ідентифікатори, а не координати. Точки, які потрапляють у полігони, також не мають однакових координат.

Моє рішення цієї проблеми полягало в тому, щоб визначити точку, яка перебуває у багатокутнику, зберегти її, знайти крапку в наступному форм-файлі, який знаходиться в полігоні з тим же ідентифікатором, а потім додати край networkx між ними.

Як дізнатися, чи знаходиться точка знаходиться в полігоні? Ну, є добре відомий алгоритм: алгоритм RayCasting , який це робить. Тут я фактично застряг, тому що для реалізації алгоритму мені потрібні координати багатокутника, і я не знаю, як отримати доступ до них прямо зараз, навіть після проглядання документації з геометрії OGR. Отже, питання, яке я задаю, полягає в тому, як отримати доступ до точок багатокутника чи координат АБО чи є простіший спосіб виявити, чи впадає точка в полігон? Використовуючи python з бібліотекою osgeo.ogr, я кодував таке:

 if g.GetGeometryType() == 3: #polygon
                c = g.GetDimension()
                x = g.GetPointCount()
                y = g.GetY()
                z = g.GetZ()

див. зображення для кращого розуміння мого питання. alt текст

[EDIT] Поки я намагався зберігати всі об'єкти багатокутника у списку, з яким я б потім порівняв першу та останню точку рядків . Але приклад Паоло пов'язаний з використанням посилання на об'єкт точки і посилання на об'єкт полігона, який би не працював з посиланням на об'єкт лінії, оскільки не вся лінія знаходиться в полігоні, а скоріше перша чи остання точка його рядкової лінії.

[EDIT3] Створення нового об’єкта точки Геометрії за координатами першої та останньої точки рядкової лінії, а потім їх використання для порівняння з об'єктами геометрії полігона, збереженими у списку, здається, працює нормально:

for findex in xrange(lyr.GetFeatureCount()):
    f = lyr.GetFeature(findex)
    flddata = getfieldinfo(lyr,f,fields)
    g = f.geometry()
    if g.GetGeometryType() == 2:
        for j in xrange(g.GetPointCount()):
            if j == 0 or j == g.GetPointCount():
                point = ogr.Geometry(ogr.wkbPoint)
                point.AddPoint(g.Getx(j),g.GetY(j))
                if point.Within(Network.polygons[x][0].GetGeometryRef()):
    print g.GetPoint(j)

Дякую Паоло та Крису за підказки.

Відповіді:


11

Shapely - це круто і елегантно, але чому б не використовувати нерухомий ogr з його просторовими операторами (у класі OGRGeometry)?

зразок коду:

from osgeo import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')
polyshp = driver.Open('/home/pcorti/data/shapefile/multipoly.shp')
polylyr = polyshp.GetLayer(0)
pointshp = driver.Open('/home/pcorti/data/shapefile/point.shp')
pointlyr = pointshp.GetLayer(0)
point = pointlyr.GetNextFeature()
polygon = polylyr.GetNextFeature()
point_geom = point.GetGeometryRef()
polygon_geom = polygon.GetGeometryRef()
print point_geom.Within(polygon_geom)

Зауважте, що вам потрібно компілювати GDAL із підтримкою GEOS.


grzie Paolo, але те, що мені справді потрібно, - це не порівнювати об'єктні посилання точки з посиланнями на багатокутник, а останню та першу точку рядкової лінії, до якої я зараз отримую доступ із GetPoint. Немає жодного GetPointRef, якого я помітив. Як би я міг реалізувати це?
користувач39901230

1
linestring - це ітерабельна колекція геометрії точки (вершини), ви можете легко отримати доступ до першої та останньої з них.
capooti

Я намагався зберігати об'єкти багатокутника у списку, який я згодом використовував би для перевірки першої та останньої точки рядкової лінії. Однак до списку точок у полігонах чомусь не додано балів: подивіться тут: codepad.org/Cm2BV5mp
користувач39901230

8

Я не знайомий з networkx, але якби я правильно зрозумів ваше запитання, ви можете використовувати shapely та OGR lib для пошуку точки в багатокутнику з shapefile. Ось один приклад, як це працює для пошуку, якщо одна точка (2000,1200) не вдається вилучити будь-який багатокутник з одного файлу форми. Для цього він друкує координати цього багатокутника.

from shapely.geometry import Point, Polygon
from shapely.wkb import loads
from osgeo import ogr

file1 = ogr.Open("d:\\fileWithData.shp")
layer1 = file1.GetLayerByName("fileWithData")

point1 = Point(2000,1200)

polygon1 = layer1.GetNextFeature()

while polygon1 is not None:
    geomPolygon = loads(polygon1.GetGeometryRef().ExportToWkb())
    if geomPolygon.contains(point1):
        xList,yList = geomPolygon.exterior.xy
        print xList
        print yList
    polygon1 = layer1.GetNextFeature()

Я сподіваюся, що це допомагає.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.