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?
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?
Câu trả lời:
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
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
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.
Đố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.
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
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à showLabel
1 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!
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.
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: 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 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á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.
Đâ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!
Để thực hiện điều này, chúng ta cần các phần sau:
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 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
make_line (start_point ($ hình học), end_point ($ hình học))
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ể!
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?
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.
Để 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):
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)