Creating 3D line from points with python

12601
10
Jump to solution
09-16-2014 09:29 AM
MartinSirkovsky
Occasional Contributor

Hi.

I have a series of points with X,Y,Z coordinates. I am trying to create a polylines from the points. Points should be vertexes of the polyline and Z-Coordinate should be used to define the elevation of vertexes.

I have created a script which works, but the Z-Coordinate is lost on vertexes and is recorded as ZERO. I am sure that my script is correct because if I pass the Z-Coordinate into the M value, it is recorded correctly. The part of the script which creates the line can be seen below:

vertexArray = arcpy.Array()

     for points in pointArray:

     xCoord = valueX

     yCoord = valueY

     zCoord = valueZ

         

     # valueZ is also passed to M dimension to test if there are some problems with values

     currentPoint = arcpy.Point(valueX, valueY, valueZ, valueZ)

     vertexArray.add(currentPoint)

newLineCursor = arcpy.da.InsertCursor(outputFc, ["SHAPE@"])

  polyline = arcpy.Polyline(vertexArray)

  newLineCursor.insertRow([polyline])

The script runs wihtout problems, and the polylines are created. But when I check in ArcMAP the polyline under sketch properties all the vertexes on line have null as Z-Coordinate (see image bellow).

edit sketch properties.jpg

I have just tested to convert points with arcpy.PointsToLine_management, and it works correctly. I could implement this in my script, but I am still curious as to why is Z-Coordinate not recorded properly with my script.

Thanks,

Martin

0 Kudos
1 Solution

Accepted Solutions
MartinSirkovsky
Occasional Contributor

I have tried a different approach and got it to work. Actually what I am trying to accomplish is to convert line file to 3D based on points. As it is not possible to snap 3D in ArcMap the lines constructed from surveying points in ArcMap are placed on zero elevation. After the lines are constructed, I am using the point file to change the elevation on the vertexes to the original one. The working script can be seen here:

import arcpy

shapeFileFolder = "folder where the files are located"

fileToProcess = "line or polygon file"

fileWith3DPoints = "file with 3D points which were used to construct the lines"

arcpy.env.workspace = shapeFileFolder

arcpy.env.overwriteOutput = True

def convertTo3D(fc, zPoints):

  # Dictionary to hold the point coordinates (key: x,y coord, value: z coord)

  zCoordDict = {}

  # Create an array which will hold geometries of point feature class

  fields = ["SHAPE@X","SHAPE@Y","SHAPE@Z"]

  with arcpy.da.SearchCursor(zPoints, fields) as cursor:

  

    for row in cursor:

     # round the coordinates to 3 decimal places

      xCoord = round(row[0], 3)

      yCoord = round(row[1], 3)

      zCoord = round(row[2], 3)

      # add key:value for current point to the dictionary

      zCoordDict[str(xCoord) + "," + str(yCoord)] = zCoord


  # Update Z coord in input file

  fields = ["SHAPE@X","SHAPE@Y","SHAPE@Z"]

  cursor = arcpy.da.UpdateCursor(fc, fields, None, None, True)

  for row in cursor:

       # Get x,y coordinates of current point

       xCoord = str(round(row[0],3))

       yCoord = str(round(row[1],3))

       newZCoord = zCoordDict[xCoord +"," + yCoord]

       print "New Z coordinate for current point is %s" % (newZCoord)

            row[2] = newZCoord

       cursor.updateRow(row)

# Run the function

convertTo3D(fileToProcess, fileWith3DPoints)

View solution in original post

10 Replies
IanMurray
Frequent Contributor

Just a thought, since ArcMap is for viewing and editting 2-D features, perhaps you can only edit the x and y in an edit session in ArcMap, and Z values are not given.  Try editting your 3-D line in ArcScene and see if it has a Z value.

0 Kudos
MartinSirkovsky
Occasional Contributor

I have tried "PointsToLine_management" which almost does what I need it to do. And that tool works in ArcMap. So I guess the script should work. Is it a bug?

0 Kudos
NeilAyres
MVP Alum

I am using v10.2 and regularly create polylineZM's from coordinates in python. So no bugs.

Be aware that when you create the geometry you should specify the SR of that geometry.

But that is unlikely to be the issue here.

0 Kudos
TimothyHales
Esri Notable Contributor

Is the feature class z enabled?

Create Feature Class (Data Management)

has_z parameter

MartinSirkovsky
Occasional Contributor

Yes it is Z enabled. You can see it at the image I have attached, that there is a z-coordinate.

You can edit Z values in ArcMap by typing z values in sketch properties.

MartinSirkovsky
Occasional Contributor

I have tried a different approach and got it to work. Actually what I am trying to accomplish is to convert line file to 3D based on points. As it is not possible to snap 3D in ArcMap the lines constructed from surveying points in ArcMap are placed on zero elevation. After the lines are constructed, I am using the point file to change the elevation on the vertexes to the original one. The working script can be seen here:

import arcpy

shapeFileFolder = "folder where the files are located"

fileToProcess = "line or polygon file"

fileWith3DPoints = "file with 3D points which were used to construct the lines"

arcpy.env.workspace = shapeFileFolder

arcpy.env.overwriteOutput = True

def convertTo3D(fc, zPoints):

  # Dictionary to hold the point coordinates (key: x,y coord, value: z coord)

  zCoordDict = {}

  # Create an array which will hold geometries of point feature class

  fields = ["SHAPE@X","SHAPE@Y","SHAPE@Z"]

  with arcpy.da.SearchCursor(zPoints, fields) as cursor:

  

    for row in cursor:

     # round the coordinates to 3 decimal places

      xCoord = round(row[0], 3)

      yCoord = round(row[1], 3)

      zCoord = round(row[2], 3)

      # add key:value for current point to the dictionary

      zCoordDict[str(xCoord) + "," + str(yCoord)] = zCoord


  # Update Z coord in input file

  fields = ["SHAPE@X","SHAPE@Y","SHAPE@Z"]

  cursor = arcpy.da.UpdateCursor(fc, fields, None, None, True)

  for row in cursor:

       # Get x,y coordinates of current point

       xCoord = str(round(row[0],3))

       yCoord = str(round(row[1],3))

       newZCoord = zCoordDict[xCoord +"," + yCoord]

       print "New Z coordinate for current point is %s" % (newZCoord)

            row[2] = newZCoord

       cursor.updateRow(row)

# Run the function

convertTo3D(fileToProcess, fileWith3DPoints)

MichaelFell
New Contributor

When you create a 3D polyline object, you have to set the 'has_Z' property to True --

arcpy.Polyline (inputs, {spatial_reference}, {has_z}, {has_m})

When you do this the polyline will retain the Z coordinates in your points.

XanderBakker
Esri Esteemed Contributor

Very true what Michael Fell mentions. You can see how to convert 3D point to 3D lines with python code in the thread below:

Convert 3D points to 3D lines (underground well data)

0 Kudos
TanyaKnowles2
New Contributor

Just a point of information here - I was writing a script to write some 3D polylines to an empty feature class. I was having trouble adding the Z value, pretty much the same as Martin Sirkovsky's initial post. I tried setting the 'has_z' to true when I created a polyline, but I was getting an error saying that attribute was read only. The solution: despite both being optional parameters you need to have a spatial reference value set before you can set has_z to true. 

0 Kudos