Lý lịch
Từ một điểm đã biết, tôi yêu cầu thiết lập "chu vi có thể nhìn thấy" gần nhất dựa vào bảng MultiLineStrings, như thể hiện trên sơ đồ.
Tôi đã tìm kiếm trang web này với một số thuật ngữ (ví dụ: cạnh tối thiểu, chu vi tối thiểu, hàng xóm gần nhất, clip, chứa đa giác, khả năng hiển thị, snap, cắt nút, theo dõi tia, lấp lũ, ranh giới bên trong, định tuyến, vỏ lõm) nhưng không thể tìm thấy bất kỳ câu hỏi trước đó có vẻ phù hợp với kịch bản này.
Biểu đồ
- Vòng tròn màu xanh lá cây là Điểm được biết đến.
- Các đường màu đen là MultiLineStrings được biết đến.
- Các đường màu xám là một dấu hiệu của một quét xuyên tâm từ Điểm đã biết.
- Các điểm màu đỏ là giao điểm gần nhất của quét xuyên tâm và MultiLineStrings.
Thông số
- Điểm sẽ không bao giờ giao nhau với MultiLineStrings.
- Điểm sẽ luôn được đặt ở vị trí trung tâm trong MultiLineStrings.
- MultiLineStrings sẽ không bao giờ bao gồm đầy đủ Điểm, do đó chu vi sẽ là MultiLineString.
- Sẽ có một bảng chứa khoảng 1.000 MultiLineStrings (thông thường chứa một dòng duy nhất khoảng 100 điểm).
Phương pháp luận được xem xét
- Thực hiện quét xuyên tâm bằng cách xây dựng một loạt các đường từ Điểm đã biết (tại, giả sử, tăng 1 độ).
- Thiết lập điểm giao nhau gần nhất của mỗi đường quét hướng tâm với MultiLineStrings.
- Khi một trong các đường quét hướng tâm không giao nhau với bất kỳ MultiLineStrings nào, điều này sẽ chỉ ra một khoảng trống trong chu vi sẽ được cung cấp trong cấu trúc MultiLineString theo chu vi.
Tóm lược
Trong khi kỹ thuật này sẽ tìm thấy các giao điểm gần nhất, nó sẽ không nhất thiết tìm thấy tất cả các điểm nút chu vi gần nhất, phụ thuộc vào độ phân giải của quét xuyên tâm. Bất cứ ai cũng có thể đề xuất một phương pháp thay thế để thiết lập tất cả các điểm chu vi hoặc bổ sung kỹ thuật quét xuyên tâm bằng một số hình thức đệm, phân vùng hoặc bù đắp?
Phần mềm
Sở thích của tôi là sử dụng SpatiaLite và / hoặc Shapely cho giải pháp nhưng sẽ hoan nghênh mọi đề xuất có thể được thực hiện bằng phần mềm nguồn mở.
Chỉnh sửa: Giải pháp làm việc (dựa trên câu trả lời của @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}})