Làm cách nào để xác định id gạch lân cận trong QGIS?


11

Tôi đã được hỏi trong một khóa đào tạo gần đây nếu QGIS có thể tự động tính toán số trang tiếp theo / trước và trên / dưới cho một cuốn sách bản đồ được tạo bằng trình tạo bản đồ. Tôi đã quản lý để tìm ra một biểu thức nhãn khá hợp lý cho lưới thông thường nếu bạn biết chiều rộng và chiều cao của lưới.

Nhưng sau đó chúng tôi bắt đầu nghĩ về các ví dụ thực tế nơi chúng tôi không muốn vẽ các trang không chứa quận quan tâm của chúng tôi, chẳng hạn như đây là một trong những quận nhà của tôi:

nhập mô tả hình ảnh ở đây

Vì vậy, chiều nay tôi đã chơi một kịch bản python để tìm ra 4 người hàng xóm mà tôi quan tâm cho từng ô lưới và thêm các giá trị đó vào lưới của tôi (điều này chủ yếu dựa trên hướng dẫn của Ujaval Gandhi ):

for f in feature_dict.values():
    print 'Working on %s' % f[_NAME_FIELD]
    geom = f.geometry()
    # Find all features that intersect the bounding box of the current feature.
    # We use spatial index to find the features intersecting the bounding box
    # of the current feature. This will narrow down the features that we need
    # to check neighboring features.
    intersecting_ids = index.intersects(geom.boundingBox())
    # Initalize neighbors list and sum
    neighbors = []
    neighbors_sum = 0
    for intersecting_id in intersecting_ids:
        # Look up the feature from the dictionary
        intersecting_f = feature_dict[intersecting_id]
        int_geom = intersecting_f.geometry()
        centroid = geom.centroid()
        height = geom.boundingBox().height()
        width = geom.boundingBox().width()
        # For our purpose we consider a feature as 'neighbor' if it touches or
        # intersects a feature. We use the 'disjoint' predicate to satisfy
        # these conditions. So if a feature is not disjoint, it is a neighbor.
        if (f != intersecting_f and
            not int_geom.disjoint(geom)):
            above_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()+height))
            below_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()-height))
            left_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()-width,
               centroid.asPoint().y()))
            right_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()+width,
               centroid.asPoint().y()))
            above = int_geom.contains(above_point)   
            below = int_geom.contains(below_point)   
            left = int_geom.contains(left_point)
            right = int_geom.contains(right_point)
            if above:
                print "setting %d as above %d"%(intersecting_f['id'],f['id'])
                f['above']=intersecting_f['id']

            if below:
                print "setting %d as below %d"%(intersecting_f['id'],f['id'])
                f['below']=intersecting_f['id']

            if left:
                print "setting %d as left of %d"%(intersecting_f['id'],f['id'])
                f['left']=intersecting_f['id']

            if right:
                print "setting %d as right of %d"%(intersecting_f['id'],f['id'])
                f['right']=intersecting_f['id']

    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()

Điều này chỉ hoạt động tốt.

nhập mô tả hình ảnh ở đây

Nhưng thành thật mà nói, toàn bộ việc tạo ra một điểm kiểm tra về phía Bắc và sau đó kiểm tra tất cả các nước láng giềng có thể có vẻ sai. Tuy nhiên, sau một buổi chiều vắt óc, tôi không thể nghĩ ra cách nào tốt hơn để xác định đâu là hàng xóm phía bắc của một tế bào lưới cụ thể?

Lý tưởng nhất là tôi muốn một cái gì đó đủ đơn giản để đặt vào hộp văn bản của nhà soạn nhạc in, nhưng tôi nghi ngờ đó là quá nhiều để yêu cầu.


Nếu không có hàng xóm ở một bên. Bạn có muốn giá trị của ô đóng cửa theo một hướng hoặc bạn sẽ để lại một khoảng trống?
radouxju

Tôi rất vui vì null trong trường hợp đó, tôi có thể dễ dàng đặt nhãn thành chỉ hiển thị khi không null hoặc trống.
Ian Turton

Câu trả lời:


3

Nếu bạn không khớp chính xác từng phạm vi trang (từ lớp chỉ mục) chính xác vào trình soạn thảo, nhưng thay vào đó có các viền chồng chéo với các trang liền kề (như được hiển thị trong ảnh chụp màn hình thứ hai của bạn), thì bạn có thể sử dụng nhãn từ lớp chỉ mục, với nhược điểm là họ sẽ ở trong biên giới bản đồ.

Nếu không có sự trùng lặp nào, thì bạn có thể sao chép một kỹ thuật mà tôi đã sử dụng thành công trong quá khứ (trùng hợp ngẫu nhiên trên E & W Sussex!) Trong MapInfo, nơi tôi đã viết một tập lệnh nhỏ tạo ra một bộ bốn điểm cho mỗi tính năng chỉ mục , bù vào các tính năng liền kề, với các thuộc tính của cả số trang tính và hướng bù. Lớp điểm sau đó được sử dụng để tạo lại nhãn, với hướng bù cho phép điều chỉnh hướng của nhãn để có hiệu ứng đẹp hơn.

Tôi đã không thử điều này, nhưng bạn có thể tránh việc tạo một lớp dữ liệu riêng biệt trong QGIS thông qua việc sử dụng chức năng tạo kiểu hình học mới, điều này sẽ tạo ra một giải pháp thanh lịch và năng động hơn có thể đạt được trong MapInfo!


Tôi thực sự nên nghĩ về việc chỉ sử dụng nhãn của các đa giác khác! :-) Sau khi thử nghiệm nhanh với Trình tạo hình học, tôi có thể vẽ một hộp giới hạn, nhưng việc xây dựng lưới sẽ khó hơn
Ian Turton

Tôi đã suy nghĩ dọc theo các dòng tạo điểm nhãn bù vào các đa giác liền kề, thay vì các lưới. Một tùy chọn khác là mở rộng MBR của tính năng chỉ mục thành các tính năng liền kề để cho phép các nhãn được rút ra.
Andy Harfoot

Mới chơi, và có vẻ như hình học được tạo bởi kiểu dáng của trình tạo hình học không được gắn nhãn, vì vậy đó không phải là giải pháp thanh lịch hơn mà tôi đã hy vọng.
Andy Harfoot

8

Trên thực tế, bạn đã thực hiện hầu hết các công việc cần thiết để xác định các ô mà bạn muốn in bằng cách sử dụng tập bản đồ. Nhưng vấn đề là làm thế nào để điều chỉnh mọi thứ cùng nhau để chỉ hiển thị ID gạch mà bạn cần. Để thể hiện ý tưởng của mình, tôi sẽ sử dụng trong ví dụ này một hình ảnh DEM và tệp vectơ lưới, như bạn có thể thấy dưới đây:

nhập mô tả hình ảnh ở đây

Đầu tiên chúng ta cần hiển thị nhãn của mỗi lưới.

Trong chế độ xem bố cục, tôi đã sử dụng lưới làm lớp phủ trong tập bản đồ, tôi đã tạo hai bản đồ: bản đồ cửa sổ chế độ xem chính và bản đồ chỉ mục chỉ hiển thị lưới, như bạn có thể thấy bên dưới:

nhập mô tả hình ảnh ở đây

Sau đó, tôi đã làm như sau:

  1. Tôi đã điều chỉnh tỷ lệ của bản đồ chỉ mục để hiển thị toàn bộ phạm vi lưới sau đó tôi đã sửa tỷ lệ
  2. Tôi đã sửa phạm vi xem để ngăn bản đồ lia máy khi sử dụng Preview atlas
  3. Tôi đã kích hoạt Overviewđể xem phạm vi và vị trí của bản đồ chế độ xem chính, như bạn có thể thấy bên dưới:

nhập mô tả hình ảnh ở đây

Đối với bản đồ cửa sổ chế độ xem chính, tôi đã sửa tỷ lệ theo phạm vi của từng khối lưới, để chắc chắn rằng tỷ lệ sẽ không bị thay đổi nếu có bất cứ điều gì xảy ra, như bạn có thể thấy bên dưới;

nhập mô tả hình ảnh ở đây

Sử dụng bản đồ chỉ mục, bạn có thể dễ dàng xem ID và vị trí của từng ô có tham chiếu đến ô khác, ngay cả khi bạn tắt lưới từ cửa sổ bản đồ xem chính. Ví dụ: bản đồ sau có ID hình xếp = 14 và bạn có thể thấy ID hình xếp xung quanh.

nhập mô tả hình ảnh ở đây

Cập nhật :

Tôi sẽ cập nhật câu trả lời của mình vì tôi nhận ra rằng bạn muốn hiển thị chỉ mục số trang của các bố cục xung quanh chứ không phải ID của các bố cục xung quanh.

Để dễ hiểu hơn về quy trình, tôi sẽ cập nhật số ID trong bản đồ chỉ mục để hiển thị số trang bố cục, như được hiển thị bên dưới:

nhập mô tả hình ảnh ở đây

Vì các ID mà tôi đã bắt đầu từ 0 (Không), ID của lưới đầu tiên được hiển thị trên bản đồ chỉ mục sẽ bắt đầu từ 3. Do đó, tôi muốn thay đổi số trang để bắt đầu từ 1 bằng cách trừ 2 từ số ID trong Atlas: Page number: ID -2, sau đó tôi sẽ sử dụng số trang hiện tại làm tham chiếu trong biểu thức để tạo nhãn cho trang hiện tại, trang trước, trang tiếp theo, trang lên và trang bên dưới, như sau:

nhập mô tả hình ảnh ở đây

  • Trang hiện tại có biểu thức này trong hộp văn bản nhãn: Current Page Number: [%@atlas_pagename%]

  • Biểu thức trang trước: [%if((@atlas_pagename = 1), Null, '↑ Page Number: ' || (@atlas_pagename - 1))%]vì không có trang nào trước 1

  • Biểu thức trang tiếp theo: [%if( (@atlas_pagename = 25), Null, '↓ Page Number: ' || (@atlas_pagename + 1))%]vì không có trang nào sau 25

  • Biểu thức trang lên: [%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]vì không có trang nào trước 6 ở hướng trên

  • Bên dưới Biểu thức trang: [%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]vì không có trang nào sau 20 theo hướng thấp hơn

Một số kết quả đầu ra:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


Mặc dù hữu ích, điều này không trả lời câu hỏi của anh ấy.
Victor

@Victor Cảm ơn bình luận của bạn, tôi đã cập nhật câu trả lời của tôi.
ahmadhanb

điều này hoạt động trong ví dụ của bạn (và của anh ấy), vì các cạnh của sơ đồ / lưới là thường xuyên. Nếu chúng không thẳng, nó sẽ không hoạt động vì số cần cộng hoặc trừ (6 trong ví dụ của bạn) sẽ khác nhau tùy thuộc vào trang atlas bạn đang truy cập.
Victor

2
Tôi đồng ý với bạn. Nếu lưới không thường xuyên, quá trình sẽ phức tạp hơn. Nhưng vì anh ta muốn áp dụng nó trên một lưới thông thường, phương pháp được áp dụng trong giải pháp đề xuất của tôi sẽ hoạt động.
ahmadhanb

chỉ cần lưu ý thực tế, trong trường hợp bạn có một ý tưởng tốt! Đặc biệt là vì lưới của tôi không thường xuyên!
Victor

2

Giải pháp này sẽ hoạt động cho lưới hình chữ nhật và nó tự động (nên hoạt động cho mọi tình huống mà không cần điều chỉnh thủ công).

Giả sử bạn có một lưới với số trang. Bạn có thể chạy tập lệnh Xử lý của tôi chọn lớp lưới và trường số trang của nó làm tham số. Kịch bản tạo bốn trường ( right, left, above, below) trong lớp lưới và tính toán id trang lân cận tương ứng cho mỗi ô lưới. Sau đó, bạn có thể sử dụng biểu thức của mình (ví dụ [% if( "left" is not NULL, 'to page' || "left", "" ) %]:) để hiển thị nhãn trang lân cận.

Chỉ cần thêm kho lưu trữ của tôi ( https://github.com/gacarrillor/QGIS-Resource.git ) từ plugin Chia sẻ tài nguyên của QGIS và cài đặt tập lệnh: nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Làm thế nào nó hoạt động

Kịch bản xác định mối quan hệ (phải, trái, trên hoặc dưới) bằng cách so sánh tọa độ các hộp giới hạn từ cả ô lưới hiện tại và từng ô giao nhau. Nó chỉ ra rằng đối với mỗi mối quan hệ, một trong các tọa độ bị thiếu.

Nếu mối quan hệ là above, tọa độ bị thiếu yMin, tức là, tất cả 3 tọa độ khác từ hộp giới hạn của ô lưới hiện tại sẽ có mặt trong hộp giới hạn của ô trên. Hãy nhớ rằng các hộp giới hạn của QGIS được xác định theo thứ tự này : [xMin, yMin, xMax, yMax].

Đối với một ví dụ số, hãy lấy các hình chữ nhật có cạnh dài 1. Nói hộp giới hạn của ô hiện tại được định nghĩa là bbox1=[0,0,1,1]. Hộp giới hạn của ô trên sẽ được định nghĩa là bbox2=[0,1,1,2]. Các tọa độ X từ bbox1 có trong bbox2, trong khi bbox1 yMinbị thiếu trong tọa độ Y của bbox2.

Chúng tôi có thể xác định 4 mối quan hệ của mình theo cách này (o: hiện tại, #: mất tích):

right: [#,o,o,o]
above: [o,#,o,o]
left:  [o,o,#,o]
below: [o,o,o,#]

Như bạn có thể thấy, chỉ số còn thiếu cung cấp cho chúng tôi tất cả thông tin chúng tôi cần.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.