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).
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
Solved! Go to Solution.
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)
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.
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?
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.
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.
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)
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.
Very true what Michael Fell mentions. You can see how to convert 3D point to 3D lines with python code in the thread below:
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.