Python - Polyline Getpart method

4074
1
04-02-2012 10:59 AM
Pierre-LucBoivin
Occasional Contributor
Hi,

I'm trying to convert and optimize the Ianko PolylineGetAzimut function to meet our requirements and i'm having problem to extract the line with the getpart method. I'm got this error message when I run the function :
AttributeError: 'function' object has no attribute 'shape'.

Thanks you


import arcpy
import math

def polyline_Get_Azimuth(azimut):
    #try:
        
        #pGeometry = params.Geometry
    fc = "C:\Temp\Generation_Direction\Montreal_Ouest_Test2.shp"
    #fc = arcpy.GetParameterAsText(0)
    dDistance = 0.5
    desc = arcpy.Describe(fc)
        ### V?rifier si les champs Azimut et Orientation sont pr?sent
    shapefieldname = desc.ShapeFieldName 
    fieldnames =  []
    fields = arcpy.ListFields(fc)
    for field in fields :
        print("Field:       {0}".format(field.name))
            #fieldnames.format(field.name)
            #print fieldnames   
            #field = fields.next()
    if "Azimut" not in fieldnames:
        arcpy.AddField_management(fc,"Azimut","DOUBLE")
    if "Orientatio" not in fieldnames :
        arcpy.AddField_management(fc,"Orientatio","TEXT","","","1")
     
        
        ### V?rification du type de format du shapefile       
    type = desc.shapetype
    #if fc.IsEmpty:
        #return -1
        #arcpy.AddMessage("Le fichier est vide")
    #else:
            #if pGeometry.GeometryType != ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
    if type != "Polyline":
        arcpy.AddMessage("Le fichier n'est pas du type polygone")
            #return -1
            
         
            
     
    rows = arcpy.SearchCursor(fc)       
    pPolyline = fc
    Pi = 4 * math.tan(1)
            #pLine = ESRI.ArcGIS.Geometry.Line()
    pLine = fc.getPart(0)
    dLength = pPolyline.Length
    pPolyline.QueryTangent(0, dDistance, True, dLength, pLine)
    dAngle = pLine.Angle * 360 / (2 * Pi)
    if (dAngle < 90):
        dAngle = 90 - dAngle
    else:
        dAngle = 450 - dAngle
    return dAngle
        
      #Process the lines
    row = rows.next()

    for row in rows:
        outshape = row.shape
        row.Azimut = dAngle
        #while row:
                #if geodesic:
                    #utshape = row.shape
                    #[Orientatio,Azimut] = azimut(outshape)
                #arcpy.AddMessage('!: %s,%s'%(sdmbearing,sdmazimuth))
                #row.Orientatio = Orientatio
                #row.Azimut = Azimut
                #else:
                    #pass #map_azimuth(inrow.shape)
                #rows.updaterow(row)
                #row = rows.next()
        rows.updaterow(row)
        row = rows.next()
Tags (2)
0 Kudos
1 Reply
KimOllivier
Occasional Contributor III
When you use a cursor to extract the shape outShape = row.shape it is not a geometry object unfortunately.
You have to unpack the parts and then unpack the points inside the parts.
Then you can rebuild a geometry object.

Here is my FillDonut script as an example. (I have since found that it does not handle all cases of donuts, but I have not fixed it yet.)
# fillDonut10.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
# 7 Nov 2011
# handle double donut parts, if a second+ parts is enclosed
# then have to drop them as well.

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
    m = 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
        id = row.objectid
        msg1 = "%d has %d parts" % (row.objectid,feat.partCount)
        arcpy.AddMessage(msg1)
        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
            g = arcpy.Polygon(polyOuter)
            if partNum == 0:
                polyGeo.append(polyOuter) # reassemble first part
                gOuter = arcpy.Polygon(polyGeo) # make a geometry object
            else :
                if g.disjoint(gOuter) :
                    polyGeo.append(polyOuter) # reassemble separate part
                else :
                    m+=1
                    msg2 = "%d has island at part%d" % (row.objectid,partNum)
                    arcpy.AddMessage(msg2)
            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 %d and %d with island donuts" % (n,m)
    arcpy.AddMessage(msg)
    

#----------------------------------------------------
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.RefreshActiveView()
0 Kudos