¿Cómo agregar Dirección y Distancia a la tabla de atributos?

18

Cualquiera que pueda ayudar. Solo quiero agregar dirección (Rumbo: es decir, N 25 35 E) y Distancia (Longitud: 125 metros) como mi nuevo campo en datos de línea / polilínea. ¿Hay un complemento para generar estos campos? Traté de usar "exportar / agregar columnas de geometría" en los datos de mi línea, pero solo se agregó el valor "Longitud".

arzandia
fuente
Hasta ahora puedo usar el complemento mmqgis para darme distancia. Estoy explorando el problema de la dirección.
Willy
1
¿Cómo son sus datos de polilínea? La distancia es relativamente fácil de calcular; sin embargo, el 'rumbo' puede cambiar a lo largo de una polilínea. ¿Está buscando demora desde el punto de inicio hasta el punto final ?
Simbamangu
Sí, estoy buscando rumbo desde el punto de inicio hasta el punto final ... gracias
arzandia
1
¿Desea una distancia en línea recta desde el punto inicial al punto final, o la longitud de la línea que sigue la ruta de la línea? Estos podrían variar ampliamente si el segmento de línea tiene curvas intermedias u otros cambios de dirección.
RyanKDalton-OffTheGridMaps

Respuestas:

42

Puede calcular la demora en la Calculadora de campo en QGIS. Esto funciona en coordenadas UTM (métricas) a distancias pequeñas (cientos de km), pero se necesitaría algo más sofisticado para grandes distancias o para grados decimales.

Abra la tabla de atributos para su capa de línea, cambie la edición y haga clic en el botón Calculadora de campo para abrir el cuadro de diálogo:

ingrese la descripción de la imagen aquí

Cree un nuevo campo como decimal con 1 o 2 de precisión.

Pegue este código en el cuadro "Expresión" y haga clic en "Aceptar": (atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + (180 *(((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)))

La primera parte calcula la tangente inversa de las diferencias x e y y la convierte a grados (180 / pi). La segunda parte agrega 180 o 360 a la figura resultante para dar un rumbo de 0-360 °.

Simbamangu
fuente
2
La solución más elegante, gracias. Mencionaría que si necesita determinar el rumbo para cada segmento de una polilínea, puede hacerlo dividiendo el archivo de forma de línea con el complemento 'División de características'. Luego cargue el nuevo shapefile (dividido) y siga el procedimiento anterior.
nhopton
1
@arzandia: tenga en cuenta que DEBE utilizar QGIS 1.9 (consulte la página de inicio para descargas beta) ya que las funciones xat () y yat () no funcionan en 1.7, que está utilizando.
Simbamangu
Ya usé el enchufe que has mencionado. como puede ver la imagen, el nombre de la capa está "dividido" ...
arzandia
1
Para responder a mi propia pregunta, "Sí, puede insertar valores de campo para yat (0) / yat (-1) y xat (0) / xat (-1)".
cbunn
1
Para mí, tuve que hacer algunos cambios en el script para que funcione: (atan ((xat (0) -xat (1)) / (yat (0) -yat (1)))) * 180 / 3.14159 + (180 * (((yat (0) -yat (1)) <0) + (((xat (0) -xat (1)) <0 AND (yat (0) - yat (1))> 0) * 2)))
oskarlin
21

No necesitas un complemento. Todo está en la clase QgsPoint de PyQGIS

Si examina el contenido de una clase de punto QGIS con la función incorporada de Python dir () en la consola de Python.

dir(point])
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__'
, '__getitem__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'azimuth', 
'multiply', 'set', 'setX', 'setY', 'sqrDist', 'sqrDistToSegment', 'toDegreesMinutesSeconds', 'toString', 'wellKnownText', 'x', 'y']

Puede ver que hay funciones de acimut y sqrDist y después de algunos intentos:

- xy[0].azimuth(xy[1]) or xy[1].azimuth(xy[0]) gives the azimuth direction between two points(in degrees, +/- 180°)
- xy[0].sqrDist(xy[1]) give the square distance between two points (in the unit of the project)

El problema ingrese la descripción de la imagen aquí

Entonces en la consola de Python

def select_all(layer):
     layer.select([])
     layer.setSelectedFeatures([obj.id() for obj in layer])

myline = qgis.utils.iface.activeLayer()
select_all(myline)
for elem in myline.selectedFeatures():
      xy = elem.geometry().asPolyline()

ahora xy contiene todos los nodos (puntos) de la línea

# first point
print "x=%2d y=%2d" % (xy[0].x(),xy[0].y())
x=112935 y=117784
# and others...

Usando todos los puntos de nodo de la línea:

1) punto acimutal i al punto i + 1 (+/- 180 °) (nodos de una línea)

for i in range(len(xy)-1):
     print "x=%2d y=%2d azim=%6.1f azim2=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].azimuth(xy[i+1]), xy[i+1].azimuth(xy[i]))

x=112935 y=117784 azim= 168.4 azim2= -11.6
x=113032 y=117312 azim=-167.5 azim2=  12.5
x=112926 y=116835 azim= 177.3 azim2=  -2.7
x=112943 y=116472 azim= 145.1 azim2= -34.9
[...]

2) distancia euclidiana entre el punto i y el punto i + 1

for i in range(len(xy)-1):
     print "x=%2d y=%2d dist=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].sqrDist(xy[i+1]))

x=112935 y=117784 dist=232533.9
x=113032 y=117311 dist=238243.6
x=112926 y=116835 dist=131839.8
x=112943 y=116472 dist=209268.1
[...]

Después, no es muy difícil agregar estos valores a la tabla de atributos.

Utilizo esta técnica para analizar los lineamientos (geología) con matplotlib y el complemento Script Runner

ingrese la descripción de la imagen aquí

gene
fuente
55
+1 - ¡Buena solución! Debe ... aprender ... Python ...
Simbamangu
Esta es una gran solución y muy valiosa para los geólogos ... pero también muy complicada
Shawn
10

La solución proporcionada por @Simbamangu es bastante efectiva pero no cubre todos los casos. Por ejemplo, la aplicación de la fórmula con un desplazamiento horizontal NULARÁ el resultado, por lo que debe usar esta fórmula en la Calculadora de campo de QGIS

case
when yat(-1)-yat(0) < 0 or yat(-1)-yat(0) > 0 then 
(atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + 
(180 *
(((yat(-1)-yat(0)) < 0) + 
(((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)
))
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) >0) then 90
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) <0) then 270
end
Sergio
fuente