배경
알려진 지점에서 다이어그램에 표시된 것처럼 MultiLineStrings 테이블에 대해 가장 가까운 주변 "가시 둘레"를 설정해야합니다.
이 사이트에서 여러 용어 (예 : 최소 모서리, 최소 둘레, 가장 가까운 이웃, 클립, 다각형 포함, 가시성, 스냅, 컷 노드, 광선 추적, 홍수 채우기, 내부 경계, 라우팅, 오목 선체)를 사용하여이 사이트를 검색했습니다. 이 시나리오와 일치하는 이전 질문을 찾을 수 없습니다.
도표
- 녹색 원은 알려진 포인트입니다.
- 검은 선은 알려진 MultiLineString입니다.
- 회색 선은 알려진 점에서 방사형 스윕을 나타냅니다.
- 빨간색 점은 방사형 스윕과 MultiLineString의 가장 가까운 교차점입니다.
매개 변수
- Point는 MultiLineString과 교차하지 않습니다.
- Point는 항상 MultiLineStrings의 중심에 위치합니다.
- MultiLineString은 Point를 완전히 둘러싸 지 않으므로 둘레는 MultiLineString입니다.
- 약 1,000 개의 MultiLineString을 포함하는 테이블이 있습니다 (일반적으로 약 100 포인트의 단일 라인을 포함 함).
고려 된 방법론
- 알려진 점에서 일련의 선을 구성하여 방사형 스윕을 수행합니다 (예 : 1 도씩 증가).
- MultiLineString과 각 방사형 스윕 라인의 가장 가까운 교차점을 설정하십시오.
- 방사형 스윕 라인 중 하나가 MultiLineString과 교차하지 않는 경우 이는 경계 MultiLineString 구성에 수용 될 경계의 간격을 나타냅니다.
요약
이 기술은 가장 가까운 교차점을 찾는 반면, 방사형 스위프의 해상도에 따라 가장 가까운 주변 노드 지점을 반드시 찾을 필요는 없습니다. 누구든지 모든 주변 지점을 설정하거나 일부 형태의 버퍼링, 섹터 화 또는 오프셋으로 방사형 스윕 기술을 보완하는 대체 방법을 추천 할 수 있습니까?
소프트웨어
필자는 솔루션에 SpatiaLite 및 / 또는 Shapely를 사용하지만 오픈 소스 소프트웨어를 사용하여 구현할 수있는 제안을 환영합니다.
편집 : 작업 솔루션 (@gene의 답변을 기반으로 함)
from shapely.geometry import Point, LineString, mapping, shape
from shapely.ops import cascaded_union
from shapely import affinity
import fiona
sweep_res = 10 # sweep resolution (degrees)
focal_pt = Point(0, 0) # radial sweep centre point
sweep_radius = 100.0 # sweep radius
# create the radial sweep lines
line = LineString([(focal_pt.x,focal_pt.y), \
(focal_pt.x, focal_pt.y + sweep_radius)])
sweep_lines = [affinity.rotate(line, i, (focal_pt.x, focal_pt.y)) \
for i in range(0, 360, sweep_res)]
radial_sweep = cascaded_union(sweep_lines)
# load the input lines and combine them into one geometry
input_lines = fiona.open("input_lines.shp")
input_shapes = [shape(f['geometry']) for f in input_lines]
all_input_lines = cascaded_union(input_shapes)
perimeter = []
# traverse each radial sweep line and check for intersection with input lines
for radial_line in radial_sweep:
inter = radial_line.intersection(all_input_lines)
if inter.type == "MultiPoint":
# radial line intersects at multiple points
inter_dict = {}
for inter_pt in inter:
inter_dict[focal_pt.distance(inter_pt)] = inter_pt
# save the nearest intersected point to the sweep centre point
perimeter.append(inter_dict[min(inter_dict.keys())])
if inter.type == "Point":
# radial line intersects at one point only
perimeter.append(inter)
if inter.type == "GeometryCollection":
# radial line doesn't intersect, so skip
pass
# combine the nearest perimeter points into one geometry
solution = cascaded_union(perimeter)
# save the perimeter geometry
schema = {'geometry': 'MultiPoint', 'properties': {'test': 'int'}}
with fiona.open('perimeter.shp', 'w', 'ESRI Shapefile', schema) as e:
e.write({'geometry':mapping(solution), 'properties':{'test':1}})
일반적으로 방사형 스윕에는 의미있는 "해상도"가 없습니다. 이벤트는 하나의 "이벤트"에서 다음 이벤트로 순서대로 스캔합니다. 여기서 이벤트는 폴리 라인의 원래 노드와 상호 교차로 구성됩니다 (원래의 스윕 중 동적으로 찾을 수 있음) 노드). 출력은 완벽하게 정확합니다.
—
whuber