I have a dataset of lines with a start and end elevation value in the attribute table. I want to apply this value to the Z coordinate of the start/end vertex respectively to create a 3D line. The lines themselves do not represent a single Z value like a contour; each line represents a sloped downward and thus has a different elevation at its start vertex than at its end vertex. I did this once in Arc Desktop using 3D Analyst tools by exporting all the start and end nodes to point shapefiles, converted the 2D points to 3D point using the start/end elevation for each shapefile, assigning all start points with a sequence of "0" and all end points with sequence "1", then merged the 2 shapefiles into one to get a "from to" array of points, finally ran points to lines to get 3D lines. I need to do this in QGIS because I do not have access to 3D analyst anymore. Anyone out there done this and willing to share the procedure?
1 Answer
if you are familar with scripting, you can use a python script to create 3D features. Inside the following example i assume to have a layer loaded inside qgis containing line string features and two fields named "from" and "to" which store the elevetion values for the first and the last vertice.
layer = iface.activeLayer()
iter = layer.getFeatures()
for feature in iter:
# retrieve every feature with its geometry and attributes
# fetch geometry
geom = feature.geometry()
# assume z values are stored in fields "from" and "to"
p0z = feature["from"]
p1z = feature["to"]
# access Points, assuming each line has to vertices
oldp0, oldp1 = geom.asPolyline()[0], geom.asPolyline()[1]
# creating a new LineString with PointZ-vertices
newp0 = QgsPointV2( QgsWKBTypes.PointZ, oldp0[0], oldp0[1], p0z )
newp1 = QgsPointV2( QgsWKBTypes.PointZ, oldp1[0], oldp1[1], p1z )
linez = QgsLineStringV2()
linez.setPoints([newp0, newp1])
# output
print linez.asWkt()
this is just quick and dirty and you'll want to add code to store the new geometry into a new layer, but i left that out. The pyqgis developer cookbook describes, how to do that (http://docs.qgis.org/2.14/en/docs/pyqgis_developer_cookbook/vector.html).
As discussed in the comments, the data is stored inside a postgis database, so i can give a solution using SQL. I assume to have a table called linxyz with a geometry column "geom" along with "from" and "to" as z-values for the first/last point of a linestring geometry.
First add a second geometry column, it should have the same SRS as the original one (for me its SRID 4326 aka WGS84):
SELECT AddGeometryColumn ('linxyz','geomz', 4326, 'LINESTRING', 3);
Then use update to fill this new geometry column with a 3D linestring:
update linxyz set geomz =
ST_GeomFromText('LINESTRING(' ||
ST_X(ST_StartPoint(geom)) || ' ' ||
ST_Y(ST_StartPoint(geom)) || ' ' || "from" || ',' ||
St_X(St_EndPoint(geom)) || ' ' ||
St_Y(St_EndPoint(geom)) || ' ' || "to" ||
')' , 4326)
I used sql's string contatening operator || here to "build" the geometry from a WKT-String. Checking the result with select, shows the z-Dimension is present in the new column "geomz"
select ST_AsText(geomz) from linxyz
I'm not sure if this is the simplest way to accomplish this task, but it works in my little example :-)
-
Unfortunately not the best at scripting, in fact I failed it and had to pick another minor. I had a look at the link you posted but didn't really understand it. Commented Aug 24, 2017 at 15:58
-
My data is stored in a postgreSQL database, anyway I can update the geometries from within the database? Commented Aug 25, 2017 at 13:44
-
Generally yes, a postgis layer can be edited in QGis or you use SQL's update command from pgadmin or even QGis DB Manager. Commented Aug 25, 2017 at 17:41
-
I tried ALTER TABLE sa_net.arc ALTER COLUMN the_geom type geometry (POINTZM,2954); but it wouldn't let me because "the_geom" is used in a trigger definition. I will have to export it to a new postgre layer and then try to force the Z value. From there I should be able to use other postgis functions to recalculate the Z coordinate at each vertex. Unless there is a way to get around that error? Using pgAdmin 4 but have the db manager as well. Commented Aug 28, 2017 at 14:02
-
1This worked very well; I managed to produce a 3D model of a small area using this to get the elevations. Thank you for the help; Cheers Commented Aug 28, 2017 at 17:46