Làm cách nào để làm gián đoạn các đường đồng mức bên dưới nhãn độ cao (thay vì sử dụng bộ đệm nhãn)?


32

Có cách nào để làm gián đoạn một đường viền bên dưới nhãn độ cao không?

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


ArcGIS? Quốc gia? Tập quán?
Ragi Yaser Burhum

1
Tôi sử dụng qgis cho ghi nhãn đường viền
MAP

Bạn có chấp nhận câu trả lời yêu cầu PostGIS không?
Scro

3
thật đáng tiếc: không :) Nhưng, có cách nào để giải quyết vấn đề với PostGIS không?
MAP

Câu trả lời:


22

Vâng, có thể làm được. Thông thường tôi sẽ đề xuất một bộ đệm trong suốt một phần, nhưng tôi thấy lý do tại sao bạn muốn làm điều này theo bản đồ.

Điều này có thể chậm và bạn cần quyết định thủ công nơi bạn muốn nhãn đi - nhưng nói theo bản đồ, đó không phải là điều xấu!

Đây là một ảnh chụp màn hình ...

Như bạn thấy, không có bộ đệm. Các raster bên dưới không bị ảnh hưởng. Tôi đã bao gồm các đường viền trung gian mỏng hơn và tạo kiểu cho chúng để chúng chỉ được hiển thị khi ELEV% 50 <> 0

ví dụ về các đường đồng mức bị gián đoạn

Tôi đã thực hiện điều này trong QGIS 2.12 ... số dặm của bạn có thể thay đổi theo các phiên bản trước.

Tôi giả sử ở đây bạn có trường "ELEV" trên mỗi đường đồng mức.

Phân đoạn các đường viền

  1. Sử dụng xử lý và thuật toán GRASS v.split.length để chia các đường viền của bạn thành các đoạn có độ dài bằng nhau. Bạn cần chọn độ dài gần với kích thước nhãn của bạn theo đơn vị bản đồ, giả sử bạn đang sử dụng mét. Ở đây tôi dùng 200m.

    Hãy cẩn thận với điều này vì nó sẽ làm cho tệp của bạn lớn hơn nhiều (lưu ý tính năng được tính trong ảnh chụp màn hình).

    Để giải quyết vấn đề này, bạn có thể chỉ muốn tạo các đường viền mà bạn muốn tạo kiểu (ví dụ: cứ sau 50 hoặc 100 mét) để tránh xử lý tất cả các đường đồng mức trung gian.

  2. Đối với lớp này, thêm trường số nguyên 1 chữ số được gọi là showLabel . Mặc định là 0 hoặc NULL.

  3. Thay đổi nhãn thành chỉ hiển thị trên một phân đoạn trong đó trường này được đặt thành 1. Sử dụng nhãn này cho biểu thức văn bản nhãn ...

    if ( "showlabel" is not null, "ELEV", "")
    

    Tôi nghĩ rằng nếu (biểu thức, giá trị đúng, giá trị sai) là khá mới; nếu sử dụng phiên bản cũ hơn, bạn có thể sử dụng CASE-ELSE

  4. Thay đổi kiểu đường kẻ để tất cả các phân đoạn có độ dài cố định được vẽ, ngoại trừ các phân đoạn nơi nhãn được hiển thị. Vì vậy, sử dụng kết xuất dựa trên quy tắc với hai quy tắc

    Rule 1: "showLabel" is null
    Black, 0% transparent
    
    Rule 2: "showLabel" is not null
    Any colour, 100% transparent
    

    Bây giờ, tất cả các đường viền sẽ hiển thị theo mặc định, nhưng không có nhãn.

    Chỉnh sửa thủ công các phân đoạn mà bạn muốn hiển thị nhãn

    Chuyển sang chế độ chỉnh sửa và chọn thủ công các phân đoạn mà bạn muốn các giá trị đường viền hiển thị và đặt giá trị là showLabel1 cho các tính năng được chọn. Bạn có thể sử dụng Ctrl+ select (trên Ubuntu / Win, Cmd+ Ctrl+ Click / trên Mac?) Để phân đoạn nhiều lựa chọn để tăng tốc mọi thứ.

    Điều này bây giờ sẽ 'cắt' các đường viền nơi bạn muốn nhãn hiển thị và các nhãn sẽ hiển thị trong các khoảng trống.

Trong trường hợp này, cài đặt nhãn của tôi là:

CRS: EPSG 27700 (Local UTM for UK, in meters)
Text size: 50 map units
Placement: Parallel, On Line

Mong rằng sẽ giúp!


5
Đây là giải pháp làm việc đầy đủ duy nhất tôi có thể tưởng tượng. Mặc dù rất đau đớn nếu có nhiều nhãn hiệu, tôi không thể tưởng tượng được việc thực hiện tất cả các bản đồ đầu nguồn nước ngầm của mình (hàng ngàn mỗi năm) theo cách này. Sẽ là tuyệt vời nếu trong tương lai điều này có thể đạt được thông qua phong cách - vì tốt nhất sẽ là mẫu dòng tùy chỉnh và nhãn lặp lại + offset.
Miro

2
Chỉ cần một số ý tưởng để giảm bớt tác vụ: Để chọn nhiều phân đoạn để vẽ nhãn, Chọn theo Đa giác hoặc Chọn theo Freehand có thể tiện dụng. Ngoài ra, một aproach khác sẽ tạo một lớp đường cào để vẽ các đường chặn các đường viền và sau đó thực hiện Chọn theo vị trí.
Alexandre Neto

7

Tôi sử dụng tùy chọn "Bộ đệm" trên tab "Cài đặt nhãn". (Sử dụng nút nhãn, không phải tùy chọn nhãn cũ trên hộp thoại thuộc tính lớp.) Điều này không xóa sạch đường viền, như tôi tưởng tượng bạn đang muốn làm, nhưng nó làm cho nhãn dễ đọc.


4
Tôi chưa bao giờ nghĩ về nó trước đây, nhưng sẽ thuận tiện nếu thay vì chỉ định màu cho bộ đệm, bạn có thể chọn áp dụng nó như một 'loại trực tiếp' cho các lớp được chọn.
Scro

5
Phiên bản mới nhất của QGIS có bộ đệm trong suốt để bạn có thể giảm tác động đến các phần khác của bản đồ.
Nathan W

1
@MAP Một loại trực tiếp xóa các pixel bên dưới nó. Nếu đó là một tùy chọn, trong trường hợp này, bạn sẽ chọn loại bỏ lớp đường viền.
Scro

1
loại trực tiếp - thuật ngữ esri là "che giấu" tài
mike

1
@MAP - Tài trợ cho nhà phát triển hoặc gửi yêu cầu tính năng và chờ đợi lòng nhân từ của người khác. :)
Scro

5

Tôi nghĩ rằng cách gần nhất có thể có với các khả năng hiện tại của QGIS là sử dụng hiệu ứng hào quang (hoặc nền) với màu có nguồn gốc từ bảng sẽ dựa trên giá trị độ cao và bảng màu giống như được sử dụng cho lưới bên dưới. Tất nhiên điều này sẽ không tính đến độ dốc và mọi thứ khác bên dưới quầng sáng trên bản đồ. Ví dụ màu ngẫu nhiên: màu sắc ngẫu nhiên cho hiệu ứng hào quang của nhãn Với một số đoạn mã, điều này có thể được viết lại dưới dạng hàm để phản ánh màu lưới.

Về lý thuyết, có thể sử dụng mô hình dòng tùy chỉnh và nhãn lặp lại + offset . Thật không may, không có thiết lập bù nhãn.

  • sau một số thử nghiệm, không thể buộc QGIS phải nghiêm ngặt với việc đặt các nhãn trong khoảng thời gian chính xác và không ở đâu khác (dù sao cũng bắt đầu thiếu)
  • Không thể tạo mẫu đường tùy chỉnh với 0 mm cho không gian để bắt đầu bù như 20 dòng - 10 không gian - 70 dòng - 0 không gian - vì vậy nhãn sẽ được đặt mỗi 100mm với độ lệch 30 mm ở đầu - có nghĩa là nhãn sẽ ở trong giữa mỗi lỗ 10 mm.

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


2

Sau khi gặp vấn đề tương tự gần đây, tôi đã tập hợp một kịch bản Python của QGIS để thực hiện việc nâng vật nặng. Tập lệnh bao gồm một số dữ liệu thử nghiệm (UK), Readme (Hướng dẫn) và biểu định kiểu được sử dụng có thể được tìm thấy tại https://github.com/pjgeng/Contour-Labels

Nói tóm lại, tập lệnh sử dụng hai lớp vectơ làm đầu vào - lớp đường viền có chú thích và lớp "hướng dẫn". Loại thứ hai bao gồm các polylines giao nhau với các đường viền tại các vị trí nhãn mong muốn.

Tập lệnh sau đó xử lý dựa trên khoảng cách giữa các đường viền và khoảng cách đường viền chỉ định nhãn sẽ áp dụng, thêm giá trị xoay cho các điểm nhãn và cuối cùng cắt lớp đường viền ban đầu để tạo ra các khoảng trống.

Cận cảnh kết quả cuối cùng.

Cách tiếp cận hoạt động đặc biệt tốt nếu người dùng cần tạo bản đồ đường viền ở các khoảng khác nhau trong cùng một khu vực (nghĩa là hướng dẫn không thay đổi). Một nhược điểm là không thể thay đổi vị trí nhãn sau khi tập lệnh kết thúc. Đối với điều này, người dùng sẽ phải điều chỉnh các dòng hướng dẫn và chạy lại tập lệnh theo đầu vào ban đầu. Trước đây tôi đã làm việc với các bộ đệm xung quanh nhãn rất nhiều để tạo hiệu ứng bị gián đoạn, nhưng điều này hóa ra là khó chịu về mặt thẩm mỹ trên các bản đồ điều khiển dữ liệu vector.

Thật không may, tôi không thể thêm bất kỳ hình ảnh nào vào lúc này để ghi lại hoặc minh họa quá trình này.

PS: Nếu sử dụng các lớp kiểu được cung cấp trong kho lưu trữ, người dùng có thể cần phải "kích hoạt" các trường tùy chỉnh cho "Xoay vòng", "Hiển thị nhãn" và "Luôn hiển thị" trong menu ghi nhãn. Trên một số cài đặt của QGIS, chúng được áp dụng tự động từ biểu định kiểu - Tôi chưa tìm ra nguyên nhân nào gây ra điều này.


2

Đây là một giải pháp khác cho vấn đề che dấu đường viền của QGIS, trong đó tôi tận dụng chức năng Spatialite của QGIS (hiện tại là QGIS 3.x) cùng với một trình tạo hình học cho vị trí nhãn.

Giải pháp rất năng động này cho phép chúng tôi thay đổi tất cả các kích thước văn bản nhãn và vị trí nhãn ngay lập tức và thậm chí còn tồn tại khi xuất vectơ PDF!

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

Để thực hiện điều này, chúng ta cần các phần sau:

  1. Một lớp vectơ LINE LINEING và hoặc MULTILINESTRING được gọi là đường viền trực tuyến với 2 trường: Phong fid Cảnh (Interger64 - khóa chính), đường cao tốc (Chuỗi)
  2. Một lớp vectơ LINE LINEING có tên gọi là Scratch Scratch_lines '(xem các dòng màu đỏ trong hình)
  3. Một bảng không có hình học được gọi là Cài đặt hình học, để lưu trữ kích thước nhãn đường viền toàn cầu (đây là một cách giải quyết đơn giản, vì bây giờ, QGIS không thể sử dụng các biến dự án trong các truy vấn SQL): Tạm thời fid ((Integer64 - khóa chính) (Chuỗi), giá trị của người nổi tiếng (Chuỗi)

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

  1. Một lớp ảo được gọi là tức là contours_with_labels 'với kiểu dáng dựa trên quy tắc:

    • Quy tắc 1: Nhãn mác tinh = 1 dòng đơn giản, độ mờ 0%
    • Quy tắc 2: Dòng đơn giản ELSE

    • và một văn bản nhãn có điều kiện cho Quy tắc 1:

      TRƯỜNG HỢP KHI nhãn = 1 THEN nâng ELSE '' END

    • với một trình tạo hình học để đặt văn bản:

      make_line (start_point ($ hình học), end_point ($ hình học))

    • và một chuỗi biểu thức cho kích thước văn bản biến:

      thuộc tính (get_feature ('settings', 'biến', 'contourlabel_size'), 'value')

và cuối cùng nhưng không kém phần quan trọng, ở đây có truy vấn SQL cho lớp ảo:

------------------------------------------------------------------------
-- select all contour lines that do not intersect any scratch lines
------------------------------------------------------------------------
select c.geometry,c.elev,0 as label 
from contours c,
       (select st_union(geometry) as geom from scratch_lines) as scr 
where not st_intersects(c.geometry,scr.geom)
------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all scratch lines (bufferwidth = length(elevation_text) * txtsize/3),
-- get st_difference between contour lines and buffers
-- and set attribute "label" to 0
--------------------------------------------------------------------------------------------------------
select st_difference(c.geometry,buf.geom) as geom,c.elev,0 as label 
from 
  (select c.fid,st_union(st_buffer(scr.geometry,length(c.elev) * txtsize.value / 3)) as geom 
      from scratch_lines scr, 
              contours c, 
              (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
      where st_intersects(scr.geometry,c.geometry) 
      group by c.fid) as buf,
  contours c 
where c.fid = buf.fid
group by c.fid
--------------------------------------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all scratch lines (bufferwidth = length(elevation_text) * txtsize/3),
-- get st_intersection between contour lines and buffers
-- and set attribute "label" to 1
--------------------------------------------------------------------------------------------------------
select st_intersection(st_buffer(scr.geometry,length(c.elev) * txtsize.value / 3),c.geometry) as geom,c.elev,1 as label 
from scratch_lines scr,
        contours c,
        (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
where st_intersects(c.geometry,scr.geometry)

Đó là nó.

Rất cám ơn tất cả những người nhiệt tình đã làm điều này có thể!


Tôi phải nói rằng, tôi rất ấn tượng với kết quả này. Cho đến khi chúng tôi có được một tùy chọn tích hợp (nếu có), đây chắc chắn là cách sạch nhất. Các lớp ảo để giải cứu, một lần nữa.
Gabriel C.

Tôi thực sự ấn tượng bởi chính mình. Nhưng, nó có thể đứng các lớp đường viền thực sự lớn?
christoph

Và tôi rất vui, sau khi thử nghiệm nó, nó cũng hoạt động với dữ liệu trong GeoPackages! Tôi muốn xác minh vì nó dựa trên Spatialite. Ước gì tôi có thể bỏ phiếu nhiều hơn một lần ...
Gabriel C.

IMHO, nó độc lập với bất kỳ định dạng tệp nào, bởi vì truy vấn đang chạy bên trong QGIS. Vì vậy, nó thậm chí sẽ làm việc với CSV.
christoph

1

Bạn có nhớ chủ đề này Martin? Cách duy nhất tôi có thể nghĩ ra để đến gần một giải pháp cho vấn đề của bạn là phủ lớp đường viền của bạn với lớp đường viền bị cắt, sử dụng cách này để dán nhãn và thay đổi màu đường thành màu trung tính che giấu các đường viền dưới nhãn, một hy vọng mà không quá xâm phạm. N

Đã thêm sau: có thể cũng đáng xem chủ đề này , câu trả lời thứ hai. Có lẽ phá vỡ các đường viền có thể là một câu trả lời, có lẽ sử dụng lớp đệm được sử dụng để cắt các đường viền?


0

Mục nhập blog ESRI: http://bloss.esri.com/esri/arcgis/2011/11/11/variable-depth-masking-contour-label-example/

Mặt nạ biến đổi độ sâu cho nhãn đường viền bao gồm ba bước:

Tạo một chú thích từ các nhãn, sử dụng công cụ Mặt nạ phác thảo tính năng để tạo mặt nạ và 3 cách sử dụng Tùy chọn bản vẽ nâng cao> Cài đặt mặt nạ để chỉ định lớp nào mặt nạ sẽ che đi.


Điều này cho thấy làm thế nào nó có thể được thực hiện, nhưng nó không thực sự trả lời câu hỏi.
underdark

0

Để làm cho các nhãn hoàn hảo hơn, tôi đã thay đổi truy vấn SQL của lớp ảo để tôn trọng các đường cào chạy song song với các đường viền (xem giải pháp bên dưới):

Phiên bản cũ nhập mô tả hình ảnh ở đây

Phiên bản mới nhập mô tả hình ảnh ở đây

Và đây là SQL mới cho lớp ảo:

------------------------------------------------------------------------
-- select all contour lines that do not intersect any scratch lines
------------------------------------------------------------------------
select c.geometry,c.elev,0 as label 
from contours c,
   (select st_union(geometry) as geom from scratch_lines) as scr 
where not st_intersects(c.geometry,scr.geom)
------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all intersection points (bufferwidth = length(elevation_text) * txtsize/2.5),
-- get st_difference between contour lines and buffers
-- and set attribute "label" to 0
--------------------------------------------------------------------------------------------------------
select st_difference(c.geometry,buf.geom) as geom,c.elev,0 as label 
from contours c,
(select c.fid,st_union(st_buffer(st_intersection(c.geometry,scr.geometry),length(c.elev) * txtsize.value / 3)) as geom
from contours c, scratch_lines scr, (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize
where st_intersects(c.geometry,scr.geometry)
group by c.fid) as buf
where c.fid = buf.fid
--------------------------------------------------------------------------------------------------------

UNION

--------------------------------------------------------------------------------------------------------
-- create buffers around all intersection points (bufferwidth = length(elevation_text) * txtsize/2.5),
-- get st_intersection between contour lines and buffers
-- and set attribute "label" to 1
--------------------------------------------------------------------------------------------------------
select st_intersection(c.geometry,st_buffer(st_intersection(c.geometry,scr.geometry),length(c.elev) * txtsize.value / 3)) as geom,c.elev,1 as label 
from contours c, 
 scratch_lines scr,
 (select cast(value as integer) as value from settings where variable = 'contourlabel_size') txtsize 
where st_intersects(c.geometry,scr.geometry)

0

Một phụ lục nhỏ liên quan đến câu hỏi ban đầu.

Đối với tất cả những người không nhận thức được thực tế rằng chúng ta có thể sử dụng kiểu dáng "Trình tạo hình học" để đơn giản hóa và làm mịn các đường đồng mức của chúng tôi trong QGIS 3.10:

mịn (đơn giản hóa ($ hình học, 2), 2)

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

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.