Existe uma função QGIS ou plugin para desenhar uma linha ondulada?
Eu usei a Spline Tool para desenhar manualmente algumas ondas, mas isso consome tempo. Se possível, eu gostaria de desenhar algo como:
Inkscape Function Plotter
( sin(x)
curva).
Existe uma função QGIS ou plugin para desenhar uma linha ondulada?
Eu usei a Spline Tool para desenhar manualmente algumas ondas, mas isso consome tempo. Se possível, eu gostaria de desenhar algo como:
Inkscape Function Plotter
( sin(x)
curva).
Respostas:
Proponho uma solução usando PyQGIS. Deve funcionar para as camadas Linestring e MultiLineString.
Esta solução é baseada na criação de anéis semicirculares, então você precisa definir um valor para o diâmetro (ou seja, a step
variável no código abaixo). A etapa escolhida não será a real usada, pois é ajustada com base no comprimento da linha (mas seria muito semelhante ao valor definido inicialmente). Você precisa fazer algumas tentativas antes de encontrar o melhor valor para a step
variável.
O código também requer um segundo parâmetro (opcional) (chamado crv_angle
), que ajuda a diminuir ou aumentar a curvatura dos anéis (realizei alguns testes para isso, então sugiro deixar 45 graus como ângulo padrão, pois isso levaria a uma circular real argolas).
Você só precisa executar este código no Python Console:
from math import sin, cos, radians
step = 3 # choose the proper value (e.g. meters or degrees) with reference to the CRS used
crv_angle = 45 # degrees
def segment(polyline):
for x in range(0, len(polyline) - 1):
first_point = polyline[x]
second_point = polyline[x +1]
seg = QgsGeometry.fromPolyline([first_point, second_point])
tmp_azim = first_point.azimuth(second_point)
len_feat = seg.length()
parts = int(len_feat/step)
real_step = len_feat/parts # this is the real step applied
points = []
current = 0
up = True
while current < len_feat:
if up:
round_angle = radians(90 - (tmp_azim - crv_angle))
up = False
else:
round_angle = radians(90 - (tmp_azim + crv_angle))
up = True
first = seg.interpolate(current)
coord_x, coord_y = (first.asPoint().x(), first.asPoint().y())
p1=QgsPointV2(coord_x, coord_y)
dist_x, dist_y = ((real_step*sin(rad_crv_angle))* cos(round_angle), (real_step*sin(rad_crv_angle)) * sin(round_angle))
p2 = QgsPointV2(coord_x + dist_x, coord_y + dist_y)
points.extend([p1, p2])
current += real_step
second = seg.interpolate(current + real_step)
p3=QgsPointV2(second.asPoint().x(), second.asPoint().y())
points.append(p3)
circularRing = QgsCircularStringV2()
circularRing.setPoints(points) # set points for circular rings
fet = QgsFeature()
fet.setGeometry(QgsGeometry(circularRing))
prov.addFeatures([fet])
layer = iface.activeLayer() # load the input layer as you want
crs = layer.crs().toWkt()
rad_crv_angle = radians(crv_angle)
# Create the output layer
outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'wiggly_line' , 'memory')
prov = outLayer.dataProvider()
fields = layer.pendingFields()
prov.addAttributes(fields)
outLayer.updateFields()
for feat in layer.getFeatures():
geom = feat.geometry()
polyline = geom.asPolyline()
segment(polyline)
# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)
e criará uma nova camada de memória de linha com o resultado esperado:
Resposta curta: você pode obtê-lo usando um SVG personalizado. Veja a parte inferior deste post para um.
Resposta longa:
Eu acredito que é melhor representá-lo do que modificar a geometria da linha. Se você deseja mover uma aresta ou executar outras ações na geometria, seria um pesadelo gerenciar se as manobras são parte da geometria, em vez de apenas uma representação de uma linha reta.
Você pode jogar com a linha de marcador de estilo. Existe uma maneira de se aproximar facilmente do que você precisa e, com um pouco mais de esforço, é provável que seja possível obtê-lo exatamente.
Para conseguir isso, você estilizaria a linha com duas linhas de marcador. Cada linha do marcador é composta de um marcador simples, o semicírculo. O primeiro é girado em 180. Ambos estão definidos como transparentes.
Na linha Marcador, você instrui um deles a ser deslocado para que os dois símbolos não sejam desenhados um frente ao outro, mas lado a lado. Se você usar o tamanho do intervalo offest = 1/2 *, a saída será uma curva sinusoidal. Eu sugiro que você brinque com o tamanho do intervalo, deslocamento e tamanho dos símbolos.
A principal limitação dessa abordagem é a linha de diâmetro dos semicírculos, que soma à linha original. Se o fundo for branco (ou qualquer cor lisa), você poderá adicionar uma terceira linha simples usando a cor de fundo.
** EDIT **
Outra opção para se livrar da linha central é criar um novo símbolo SVG. Modifiquei a meia curva, vivendo apenas a parte arredondada. Funciona, embora uma elipse de 1/2 possa ser mais atraente. A captura de tela foi feita usando o tamanho do símbolo 10, intervalo 4, deslocamento 2.
salve o código abaixo em um arquivo half_circle_line.svg e verifique se o caminho para o svg está definido em QGIS // Settings / Options / System / SVG Paths
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="11.2889mm" height="11.2889mm"
viewBox="0 0 32 32"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>Qt Svg Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
<g fill="#ffffff" fill-opacity="0" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal"
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M19.1181,16 C19.1181,16 19.1181,14.2779 17.7221,12.8819 16,12.8819 C14.2779,12.8819 12.8819,14.2779 12.8819,16"/>
</g>
</g>
</svg>
Pen style
que nenhuma pena :)