Calculate Field..X to M, Y to Z

3018
6
04-16-2012 11:47 AM
PacoVanSistine
New Contributor
Is there a way to calculate my populated X,Y,Z,M vertice values to one another using a Calculate Field python code block? 
basically Calc field X to field M and Calc field Y to field Z.  im buidling a simple model in Model Builder and would like to switch those vertex values.
thanks!
0 Kudos
6 Replies
KimOllivier
Occasional Contributor III
Instead of using a codeblock in CalculateField, open an updateCursor in a Python script and put the code in there.
You have to extract out the shape as an object, rebuild a new object and update the shape field.
A script can be much easier to write, with exception traps.

        # POS transect with measures
        
        posArray = arcpy.Array()
        for transit in dPOS.keys():
            for mrk in dPOS[transit]:
                ta,tb = trans(mrk[0],mrk[1])
                posArray.add(arcpy.Point(ta,tb,mrk[2],mrk[3]))
            rowPOS = curPOS.newRow()
            rowPOS.mark = transit.upper()
            rowPOS.plotid = plotid
            rowPOS.plotmark = plotid + transit.upper()
            rowPOS.shape = posArray
            curPOS.insertRow(rowPOS)
            posArray.removeAll()

In this snippet I am looping around a dictionary of coordinates (dPOS), transforming them and building an array of points in posArray for the polyline feature. I am creating the lines, not updating.
Note the four values ta,tb,mrk[2],mrk[3] which are x,y,z,m values.
In your case you would be extracting the current values from the shape using an update cursor with something like

Here is a more complex example showing how you have to iterate over the parts in a polyline to get to the vertices.

# fillDonut.py
# frequent forum request to fill holes
# use an Update Cursor to edit polys with donuts
# 22 May 2010
# Kim Ollivier kimo@ollivier.co.nz
# (c) Creative Commons 3.0 (Attribution)
# Method
# ------
# Polygon features are stored as:
# [[pnt,pnt,pnt,pnt,,pnt,pnt,pnt,pnt][pnt,pnt,pnt,pnt]]
# Parts are separate lists inside the feature object array
# null point in a part indicates donut ring(s) follow
# So just step through and truncate at first null pnt per part,
#   re-assemble parts into a polygon
# Update feature if a donut found, otherwise continue
# Input is a layer so can use selection in Arcmap
# could also put on menu at ArcMap 10
# can be back-ported to 9.3
# 4 June 2010
# added iter lambda function for part array because isn't interable
# cleared polyOuter buffer earlier to fix logic for multiple parts

import arcpy,sys

def filldonut(inlay) :
    '''Edits a layer in-place
    fills all features with donuts
    requires a layer to honour 
    selected features
    '''
    desc = arcpy.Describe(inlay)
    shapefield = desc.ShapeFieldName
    rows = arcpy.UpdateCursor(inlay)
    n = 0
    polyGeo = arcpy.Array() # to hold edited shape
    polyOuter = arcpy.Array() # to hold outer ring
    for row in rows:
        feat = row.getValue(shapefield)
        qInterior = False
        for partNum in range(feat.partCount) :
            part = feat.getPart(partNum)
            for pt in iter(lambda:part.next(),None) : # iter stops on null pt
                polyOuter.append(pt)
            if part.count > len(polyOuter) :
                qInterior = True
            polyGeo.append(polyOuter) # reassemble each part
            polyOuter.removeAll() # ready for next part
        if qInterior : # in any part of this feature, otherwise skip update
            n+=1
            row.setValue(shapefield,polyGeo)
            rows.updateRow(row)
        polyGeo.removeAll()
    del rows,row
    msg = "Features with interior ring filled "+str(n)
    arcpy.AddMessage(msg)
    arcpy.AddMessage("Refresh view to see donuts disappear!")

#----------------------------------------------------
if __name__ == '__main__' :
    inlay = sys.argv[1] # arcpy.GetParameterAsText(0)
    desc = arcpy.Describe(inlay)
    if desc.shapetype != 'Polygon' :
        arcpy.AddError(inlay + " Not a polygon class")
    else :
        filldonut(inlay)
        arcpy.RefreshGraphics()

(Unfortunately it is possible to fool this code with complex nested imbedded holes in multipart polygons. but it works for simple cases.)
0 Kudos
NobbirAhmed
Esri Regular Contributor
... basically Calc field X to field M and Calc field Y to field Z.


Do you already have X, Y, M and Z fields in your table? If so then create a model like this graphic:

[ATTACH=CONFIG]13642[/ATTACH]

And then, use parameter values as follows for one of the Calculate Field tool:

Field Name: X
Expression: !M!
Express Type: PYTHON_9.3

And for the other Calc Field tool as:

Field Name: Z
Expression: !Y!
Express Type: PYTHON_9.3
0 Kudos
PacoVanSistine
New Contributor
Well,  i do have a populated Shape/Geometry Polyline ZM field of vertices.  opening the sketch properties definitely shows X, Y and Z and M values for each vertice.
but not individual fields in the attribute table.  Ive extracted elevation values from my surface to the line, and created a route/distances for the line as well.
i was hoping there was something as 'simple' as calculating one field = to another field, as you can easily do with the Field Calculator within a typical attribute table.
however calculating these vertex geometries seems to be a task.

thanks!
0 Kudos
NobbirAhmed
Esri Regular Contributor
If your input is a polyline then you'll have one record per polyline. If you have four vertices per polyline then you want four times the number polylines records in your output?

Here is a little snippet of code that loads the geometry into a Geometry object (available in 10.0 only) and then reads X, Y, M, Z for each cenroid of the lines:

import arcpy

input_fc = r"C:\points_to_XYMZ\f.gdb\poly_fc_zm"

g = arcpy.Geometry()
geometry_list = arcpy.CopyFeatures_management(input_fc, g)

for geom in geometry_list:
    c = geom.centroid
    print c.X, c.Y, c.Z, c.M



If you want one output record for each vertex then you have to write a python script.
0 Kudos
DanLee
by Esri Regular Contributor
Esri Regular Contributor
The xyzm values for each vertex reflect the location of the vertex, the elevation you obtained, and the route/distance measurements you created. Why do you want to "mess up" these values and put the xy coordinates into the zm values? Depending on what you need to analyze, there may be a different way to support your analysis. Could you describe the goal of your process?
0 Kudos
AliciaBurney
New Contributor
Do you already have X, Y,
0 Kudos