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?


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 :-)

| improve this answer | |
  • 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. – Tyler Veinot Aug 24 '17 at 15:58
  • My data is stored in a postgreSQL database, anyway I can update the geometries from within the database? – Tyler Veinot Aug 25 '17 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. – Andreas Müller Aug 25 '17 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. – Tyler Veinot Aug 28 '17 at 14:02
  • 1
    This 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 – Tyler Veinot Aug 28 '17 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.