Tuesday, 22 May 2018

postgis - rotate point along line layer



I have two layers: point and line (postgis or shp) The line layer represent a hiking trail. The point layer the mountain passes. The points are exactly on the same position like the node of the line. Now I would like to rotate the points in orientation of the line. Is there a way to do that automatically?


enter image description here



Answer



You need to determine the azimuth of the polyline segment next to the point. It is possible to calculate this value and save it to an attribute, or calculate it as an expression which give the azimuth as result.



How to use the following Python script:



  1. Point layer and line layer are added to the legend (in the script named bridges and trails) and change the names in the code

  2. Add an attribut of type REAL to the point layer (in the script named angle), when using a different name, change the code in line 8

  3. Open Python Console -> Editor and copy & paste the code

  4. Run the script


from math import atan2

# get layers

bridges = QgsMapLayerRegistry.instance().mapLayersByName('bridges')[0]
trails = QgsMapLayerRegistry.instance().mapLayersByName('trails')[0]

# get fieldindex
fni = bridges.fieldNameIndex('angle')

# initializations
tolerance = 0.01 # search tolerance
bridges.startEditing()


# loop over all bridges
for bridge in bridges.getFeatures():
x = bridge.geometry().asPoint().x()
y = bridge.geometry().asPoint().y()

# get the rectangular search area
searchRect = QgsRectangle(x - tolerance, y - tolerance, x + tolerance, y + tolerance)

# find trails
for trail in trails.getFeatures(QgsFeatureRequest().setFilterRect(searchRect)):

# get the nearest vertex on trail and the one before and after
pnt, v, b, a, d = trail.geometry().closestVertex(bridge.geometry().asPoint())
p1 = trail.geometry().vertexAt(v)
# when vertex before exists look back, otherwise look forward
if v>-1 and b>-1:
p2 = trail.geometry().vertexAt(b)
elif v>-1 and a>-1:
p2 = trail.geometry().vertexAt(a)

# calculate azimuth

angle = atan2(p2.x() - p1.x(), p2.y() - p1.y()) / 0.017453
bridge[fni] = angle
bridges.updateFeature(bridge)

# save changes and stop editing
bridges.commitChanges()

The value for variable tolerance depends on the units of length measurements. Tt may be necessary to choose the appropriate value to really pick the nearest vertex.


Use this attribut angle as variable for data defined rotation of the symbols:


rotated symbols



You may wish to complicate things a little bit and calculate azimuths to the vertex before AND after and take the average.


The dynamic expression version:


from qgis.core import *
from qgis.gui import *
from math import atan2

@qgsfunction(args='auto', group='Custom')
def get_azimuth(layername, tolerance, feature, parent):
# initializations
trails = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0]

x = feature.geometry().asPoint().x()
y = feature.geometry().asPoint().y()

# get the rectangular search area
searchRect = QgsRectangle(x - tolerance, y - tolerance, x + tolerance, y + tolerance)

# find trails
for trail in trails.getFeatures(QgsFeatureRequest().setFilterRect(searchRect)):
# get the nearest vertex on trail and the one before and after
pnt, v, b, a, d = trail.geometry().closestVertex(feature.geometry().asPoint())

if v == -1:
continue
p1 = trail.geometry().vertexAt(v)
# when vertex before exists look back, otherwise look forward
if v>-1 and b>-1:
p2 = trail.geometry().vertexAt(b)
elif v>-1 and a>-1:
p2 = trail.geometry().vertexAt(a)
# calculate azimuth
angle = atan2(p2.x() - p1.x(), p2.y() - p1.y()) / 0.017453

return angle

expression


field calculator


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...