infelizmente: não :) Mas, existe uma maneira de resolver o problema com o PostGIS?
MAP
Respostas:
22
Sim, factível. Normalmente, sugiro um buffer parcialmente transparente, mas vejo por que você deseja fazer isso cartograficamente.
Isso pode ser lento, e você precisa decidir manualmente para onde deseja que os rótulos cheguem - mas cartograficamente falando, isso não é uma coisa ruim!
Aqui está uma captura de tela ...
Como você pode ver, não há buffers. A varredura abaixo não é afetada. Incluí linhas de contorno intermediárias mais finas e as denomino para que sejam exibidas apenas quando ELEV% 50 <> 0
Fiz isso no QGIS 2.12 ... sua milhagem pode variar com as versões anteriores.
Presumo que aqui você tenha um campo "ELEV" em cada linha de contorno.
Segmentar as linhas de contorno
Use o processamento e o algoritmo GRASS v.split.length para dividir seus contornos em segmentos de igual comprimento. Você precisa escolher um comprimento que seja próximo ao tamanho da sua etiqueta nas unidades do mapa, supondo que você esteja usando medidores. Aqui eu usei 200m.
Tenha cuidado com isso, pois ele tornará seu arquivo muito, muito maior (observe o recurso na captura de tela).
Para contornar isso, você pode gerar apenas as linhas de contorno que deseja estilizar (por exemplo, a cada 50 ou 100 metros) para evitar o processamento de todas as linhas de contorno intermediárias.
Para essa camada, adicione um campo inteiro de 1 dígito chamado showLabel . O padrão é 0 ou NULL.
Altere o rótulo para mostrar apenas em um segmento em que esse campo esteja definido como 1. Use isso para a expressão de texto do rótulo ...
if ( "showlabel" is not null, "ELEV", "")
Eu acho que se (expressão, valor verdadeiro, valor falso) é relativamente novo; se estiver usando uma versão mais antiga, você poderá usar o CASE-ELSE
Altere o estilo da linha para que todos os segmentos de comprimento fixo sejam desenhados, exceto os segmentos em que o rótulo é exibido. Portanto, use a renderização baseada em regras com duas regras
Rule 1: "showLabel" is null
Black, 0% transparent
Rule 2: "showLabel" is not null
Any colour, 100% transparent
Agora, todos os contornos serão mostrados por padrão, mas nenhum rótulo.
Edite manualmente os segmentos nos quais deseja mostrar rótulos
Entre no modo de edição e selecione manualmente os segmentos onde deseja que os valores do contorno sejam exibidos e defina o valor showLabelcomo 1 para os recursos selecionados. Você pode usar Ctrl+ select (no Ubuntu / Win, Cmd+ Ctrl+ Click / no Mac?) Para selecionar vários segmentos para acelerar as coisas.
Agora, isso deve "recortar" os contornos onde você deseja que os rótulos sejam exibidos, e os rótulos aparecerão nas lacunas.
Nesse caso, minhas configurações de etiqueta foram:
CRS: EPSG 27700 (Local UTM for UK, in meters)
Text size: 50 map units
Placement: Parallel, On Line
Esta é a única solução totalmente funcional que posso imaginar. Muito doloroso, porém, se houver muitos rótulos, não consigo imaginar fazer todos os meus mapas das cabeças de águas subterrâneas (milhares por ano) dessa maneira. Seria ótimo se, no futuro, isso for possível através do estilo - pois o melhor seria o padrão de linha personalizado e a repetição e deslocamento da etiqueta.
Miro
2
Apenas algumas idéias para facilitar a tarefa: Para selecionar os vários segmentos para desenhar o rótulo, Selecionar por polígono ou Selecionar à mão livre pode ser útil. Além disso, outra abordagem seria criar uma camada de linha de rascunho para desenhar linhas que interceptem os contornos e, em seguida, selecione Selecionar por local.
Alexandre Neto
7
Eu uso a opção "Buffer" na guia "Configuração da etiqueta". (Usando o botão de etiquetas, não a opção de etiquetas antigas na caixa de diálogo de propriedades da camada.) Isso não apaga a linha de contorno, como eu imagino que você queira, mas torna a etiqueta legível.
Eu nunca pensei nisso antes, mas seria conveniente se, em vez de atribuir uma cor ao buffer, você pudesse aplicá-lo como um 'nocaute' nas camadas selecionadas.
Scro
5
A versão mais recente do QGIS possui buffers transparentes para que você possa reduzir o impacto em outras partes do mapa.
23713 Nathan W
1
@ MAP Um nocaute apaga os pixels abaixo dele. Se isso fosse uma opção, nesse caso, você escolheria nocautear a camada de contorno.
@MAP - Patrocine um desenvolvedor ou envie uma solicitação de recurso e aguarde a benevolência de outros. :)
Scro 27/02
5
Acho que o mais próximo possível das habilidades atuais do QGIS é usar o efeito halo (ou plano de fundo) com cores originadas da tabela, que serão baseadas no valor de elevação e no esquema de cores iguais aos usados na grade subjacente. É claro que isso não levaria em conta a colina e tudo o mais abaixo da auréola no mapa. Exemplo aleatório de cores:
Com um pouco de código, isso pode ser reescrito como função para refletir a cor da grade.
Em teoria, deve ser possível usar padrão de linha personalizado e repetição de etiqueta + deslocamento . Infelizmente, não há configuração de deslocamento de etiqueta.
após alguns testes, é impossível forçar o QGIS a ser rigoroso ao colocar os rótulos no intervalo exato e em nenhum outro lugar (+ ausência do deslocamento inicial de qualquer maneira)
é impossível criar um padrão de linha personalizado com zero mm para que o espaço tenha deslocamento inicial como 20 linhas - 10 espaços - 70 linhas - 0 espaço - para que a etiqueta seja colocada a cada 100 mm com deslocamento de 30 mm no início - o que significa que a etiqueta estaria em no meio de cada furo de 10 mm.
Depois de encontrar o mesmo problema recentemente, montei um script QGIS Python para realizar o trabalho pesado. O script, incluindo alguns dados de teste (REINO UNIDO), Leia-me (Guia) e folhas de estilos usadas, pode ser encontrado em https://github.com/pjgeng/Contour-Labels
Em resumo, o script usa duas camadas de vetor como entrada - a camada de contorno anotada e uma camada "guias". O último consiste em polilinhas que cruzam os contornos nos locais de etiqueta desejados.
O script então funciona com base na distância entre os contornos e o intervalo de contorno do índice que os rótulos serão aplicados, adiciona um valor de rotação aos pontos do rótulo e, eventualmente, corta a camada de contorno original para produzir as lacunas.
A abordagem funciona particularmente bem caso o usuário precise produzir mapas de contorno em intervalos diferentes na mesma área (ou seja, os guias não mudam). Uma desvantagem é a incapacidade de alterar a posição do rótulo após a conclusão do script. Para isso, o usuário teria que ajustar as linhas de guia e executar novamente o script em relação à entrada original. Anteriormente, eu trabalhei muito com buffers em torno de rótulos para criar o efeito interrompido, mas isso acabou sendo esteticamente desagradável em mapas acionados por dados vetoriais.
Infelizmente, não posso adicionar mais fotos no momento para documentar ou ilustrar o processo.
PS: Se usar as camadas de estilo fornecidas no repositório, os usuários podem precisar "ativar" os campos personalizados para "Rotação", "Mostrar etiqueta" e "Sempre mostrar" no menu de etiquetas. Em algumas instalações do QGIS, elas são aplicadas automaticamente a partir da folha de estilo - ainda não descobri o que causa isso.
Aqui está outra solução para o problema de mascaramento de etiqueta de contorno do QGIS, em que aproveito a funcionalidade Spatialite do QGIS (atualmente QGIS 3.x) junto com um gerador de geometria para a colocação da etiqueta.
Esta solução muito dinâmica nos permite alterar todos os tamanhos de texto e posições de etiqueta imediatamente e até sobreviver a uma exportação de vetor em PDF!
Para tornar isso possível, precisamos das seguintes partes:
Uma camada vetorial "LINESTRING" ou "MULTILINESTRING" denominada "contornos" com 2 campos: "fid" (Interger64 - chave primária), "elev" (String)
Uma camada vetorial "LINESTRING" chamada "scratch_lines" (veja linhas vermelhas na figura)
Uma tabela sem geometria chamada “settings” para armazenar o tamanho global do rótulo de contorno (esta é uma solução simples, porque o QGIS não pode usar variáveis de projeto em consultas SQL agora): “fid” (Integer64 - chave primária), “variable” (String), "valor" (String)
Uma camada virtual chamada ie "contours_with_labels" com estilo baseado em regras:
Regra 1: “label” = 1… linha simples, opacidade 0%
Regra 2: ELSE ... linha simples
e um texto de rótulo condicional para a Regra 1:
CASE WHEN label = 1 THEN elev ELSE '' END
com um gerador de geometria para posicionamento do texto:
e por último mas não menos importante, aqui está a consulta SQL para a camada virtual:
------------------------------------------------------------------------
-- 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)
É isso aí.
Muito obrigado a todas essas pessoas entusiasmadas que tornam isso possível!
Devo dizer que estou impressionado com o resultado. Até que tenhamos uma opção integrada (se alguma vez), essa é definitivamente a maneira mais limpa. Camadas virtuais para o resgate, novamente.
Gabriel C.
Fiquei realmente impressionado comigo mesmo. Mas, pode suportar realmente grandes camadas de contorno?
christoph
E fico muito feliz, depois de testá-lo, que ele também funcione com dados nos GeoPackages! Eu queria verificar, pois é baseado no Spatialite. Gostaria de poder votar mais de uma vez ...
Gabriel C.
IMHO, é independente de qualquer formato de arquivo, porque a consulta está sendo executada dentro do QGIS. Por isso, deve até funcionar com CSV.
christoph
Parece que não é o fim da história. Após uma pesquisa de hoje, percebi que podemos usar as funções de expressão QGIS dentro da consulta SQL da camada virtual: gis.stackexchange.com/questions/320991/… . Portanto, há muito mais por vir, o que acelerará o mascaramento de rótulos (estou pensando em consultas dependentes de escala ou melhor uso de índices espaciais).
christoph
1
Você se lembra dessa discussão Martin? A única maneira de pensar em chegar perto de uma solução para o seu problema seria sobrepor sua camada de contorno com uma camada de contorno cortada, use isso para rotular e altere a cor da linha para algo neutro que oculte os contornos sob os rótulos, espera-se sem ser muito intrusivo. N.
Adicionado mais tarde: pode valer a pena olhar também para este tópico , a segunda resposta. Talvez quebrar as linhas de contorno possa ser uma resposta, talvez usando a camada de buffer usada para cortar os contornos?
O mascaramento de profundidade variável para etiquetas de contorno envolve três etapas:
1criando anotações nas etiquetas, 2utilizando a ferramenta Máscaras de estrutura de tópicos para criar máscaras e 3utilizando as opções Opções avançadas de desenho> Configurações de máscara para especificar quais camadas as máscaras irão mascarar.
Isso mostra como ele poderia ser implementado, mas na verdade não responde à pergunta.
underdark
0
Para tornar os rótulos mais perfeitos, alterei a consulta SQL da camada virtual para respeitar as linhas de arranque paralelas às linhas de contorno (consulte a solução abaixo):
Versão antiga
Nova versão
E aqui está o novo SQL para a camada virtual:
------------------------------------------------------------------------
-- 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)
Um pequeno adendo relacionado à pergunta original.
Para todos aqueles que não estão cientes do fato de que podemos usar o estilo "Gerador de geometria" para simplificar e suavizar nossas linhas de contorno no QGIS 3.10:
Respostas:
Sim, factível. Normalmente, sugiro um buffer parcialmente transparente, mas vejo por que você deseja fazer isso cartograficamente.
Isso pode ser lento, e você precisa decidir manualmente para onde deseja que os rótulos cheguem - mas cartograficamente falando, isso não é uma coisa ruim!
Aqui está uma captura de tela ...
Como você pode ver, não há buffers. A varredura abaixo não é afetada. Incluí linhas de contorno intermediárias mais finas e as denomino para que sejam exibidas apenas quando ELEV% 50 <> 0
Fiz isso no QGIS 2.12 ... sua milhagem pode variar com as versões anteriores.
Presumo que aqui você tenha um campo "ELEV" em cada linha de contorno.
Segmentar as linhas de contorno
Use o processamento e o algoritmo GRASS v.split.length para dividir seus contornos em segmentos de igual comprimento. Você precisa escolher um comprimento que seja próximo ao tamanho da sua etiqueta nas unidades do mapa, supondo que você esteja usando medidores. Aqui eu usei 200m.
Tenha cuidado com isso, pois ele tornará seu arquivo muito, muito maior (observe o recurso na captura de tela).
Para contornar isso, você pode gerar apenas as linhas de contorno que deseja estilizar (por exemplo, a cada 50 ou 100 metros) para evitar o processamento de todas as linhas de contorno intermediárias.
Para essa camada, adicione um campo inteiro de 1 dígito chamado showLabel . O padrão é 0 ou NULL.
Altere o rótulo para mostrar apenas em um segmento em que esse campo esteja definido como 1. Use isso para a expressão de texto do rótulo ...
Eu acho que se (expressão, valor verdadeiro, valor falso) é relativamente novo; se estiver usando uma versão mais antiga, você poderá usar o CASE-ELSE
Altere o estilo da linha para que todos os segmentos de comprimento fixo sejam desenhados, exceto os segmentos em que o rótulo é exibido. Portanto, use a renderização baseada em regras com duas regras
Agora, todos os contornos serão mostrados por padrão, mas nenhum rótulo.
Edite manualmente os segmentos nos quais deseja mostrar rótulos
Entre no modo de edição e selecione manualmente os segmentos onde deseja que os valores do contorno sejam exibidos e defina o valor
showLabel
como 1 para os recursos selecionados. Você pode usar Ctrl+ select (no Ubuntu / Win, Cmd+ Ctrl+ Click / no Mac?) Para selecionar vários segmentos para acelerar as coisas.Agora, isso deve "recortar" os contornos onde você deseja que os rótulos sejam exibidos, e os rótulos aparecerão nas lacunas.
Nesse caso, minhas configurações de etiqueta foram:
Espero que ajude!
fonte
Eu uso a opção "Buffer" na guia "Configuração da etiqueta". (Usando o botão de etiquetas, não a opção de etiquetas antigas na caixa de diálogo de propriedades da camada.) Isso não apaga a linha de contorno, como eu imagino que você queira, mas torna a etiqueta legível.
fonte
Acho que o mais próximo possível das habilidades atuais do QGIS é usar o efeito halo (ou plano de fundo) com cores originadas da tabela, que serão baseadas no valor de elevação e no esquema de cores iguais aos usados na grade subjacente. É claro que isso não levaria em conta a colina e tudo o mais abaixo da auréola no mapa. Exemplo aleatório de cores: Com um pouco de código, isso pode ser reescrito como função para refletir a cor da grade.
Em teoria, deve ser possível usar padrão de linha personalizado e repetição de etiqueta + deslocamento . Infelizmente, não há configuração de deslocamento de etiqueta.
fonte
Depois de encontrar o mesmo problema recentemente, montei um script QGIS Python para realizar o trabalho pesado. O script, incluindo alguns dados de teste (REINO UNIDO), Leia-me (Guia) e folhas de estilos usadas, pode ser encontrado em https://github.com/pjgeng/Contour-Labels
Em resumo, o script usa duas camadas de vetor como entrada - a camada de contorno anotada e uma camada "guias". O último consiste em polilinhas que cruzam os contornos nos locais de etiqueta desejados.
O script então funciona com base na distância entre os contornos e o intervalo de contorno do índice que os rótulos serão aplicados, adiciona um valor de rotação aos pontos do rótulo e, eventualmente, corta a camada de contorno original para produzir as lacunas.
A abordagem funciona particularmente bem caso o usuário precise produzir mapas de contorno em intervalos diferentes na mesma área (ou seja, os guias não mudam). Uma desvantagem é a incapacidade de alterar a posição do rótulo após a conclusão do script. Para isso, o usuário teria que ajustar as linhas de guia e executar novamente o script em relação à entrada original. Anteriormente, eu trabalhei muito com buffers em torno de rótulos para criar o efeito interrompido, mas isso acabou sendo esteticamente desagradável em mapas acionados por dados vetoriais.
Infelizmente, não posso adicionar mais fotos no momento para documentar ou ilustrar o processo.
PS: Se usar as camadas de estilo fornecidas no repositório, os usuários podem precisar "ativar" os campos personalizados para "Rotação", "Mostrar etiqueta" e "Sempre mostrar" no menu de etiquetas. Em algumas instalações do QGIS, elas são aplicadas automaticamente a partir da folha de estilo - ainda não descobri o que causa isso.
fonte
Aqui está outra solução para o problema de mascaramento de etiqueta de contorno do QGIS, em que aproveito a funcionalidade Spatialite do QGIS (atualmente QGIS 3.x) junto com um gerador de geometria para a colocação da etiqueta.
Esta solução muito dinâmica nos permite alterar todos os tamanhos de texto e posições de etiqueta imediatamente e até sobreviver a uma exportação de vetor em PDF!
Para tornar isso possível, precisamos das seguintes partes:
Uma camada virtual chamada ie "contours_with_labels" com estilo baseado em regras:
Regra 2: ELSE ... linha simples
e um texto de rótulo condicional para a Regra 1:
e por último mas não menos importante, aqui está a consulta SQL para a camada virtual:
É isso aí.
Muito obrigado a todas essas pessoas entusiasmadas que tornam isso possível!
fonte
Você se lembra dessa discussão Martin? A única maneira de pensar em chegar perto de uma solução para o seu problema seria sobrepor sua camada de contorno com uma camada de contorno cortada, use isso para rotular e altere a cor da linha para algo neutro que oculte os contornos sob os rótulos, espera-se sem ser muito intrusivo. N.
Adicionado mais tarde: pode valer a pena olhar também para este tópico , a segunda resposta. Talvez quebrar as linhas de contorno possa ser uma resposta, talvez usando a camada de buffer usada para cortar os contornos?
fonte
Entrada do blog da ESRI: http://blogs.esri.com/esri/arcgis/2011/11/28/variable-depth-masking-contour-label-example/
O mascaramento de profundidade variável para etiquetas de contorno envolve três etapas:
1criando anotações nas etiquetas, 2utilizando a ferramenta Máscaras de estrutura de tópicos para criar máscaras e 3utilizando as opções Opções avançadas de desenho> Configurações de máscara para especificar quais camadas as máscaras irão mascarar.
fonte
Para tornar os rótulos mais perfeitos, alterei a consulta SQL da camada virtual para respeitar as linhas de arranque paralelas às linhas de contorno (consulte a solução abaixo):
Versão antiga
Nova versão
E aqui está o novo SQL para a camada virtual:
fonte
Um pequeno adendo relacionado à pergunta original.
Para todos aqueles que não estão cientes do fato de que podemos usar o estilo "Gerador de geometria" para simplificar e suavizar nossas linhas de contorno no QGIS 3.10:
fonte