Select to view content in your preferred language

Polygon Centroid

1634
14
Jump to solution
08-09-2013 05:03 AM
JamesSmith7
New Contributor
I am attempting to create a script that zooms to a polygon centroid.  I want the polygon centroid to be based on a Subd attribute field.  Location is a feature class and I intend to use the SHAPE@XY to zoom to the polygon centroid.  I am receiving an RuntimeError: Invalid SQL statement.

centroid = "SHAPE@XY" spatialref = arcpy.Describe("Location").spatialReference cursor = arcpy.da.SearchCursor("Location", "Subd", centroid, spatialref)  row[0] = Subd del row del cursor
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JamesCrandall
MVP Frequent Contributor
To follow up with Waynes contribution, if all you want to do is zoom to a selected feature -- you could just do that too and not even worry about centroids or extents of anything.

 for lyr in arcpy.mapping.ListLayers(mxd):          tlyr = lyr            dsc = arcpy.Describe(tlyr)         sel_set = dsc.FIDSet         if dsc.shapeType == "Polygon":           if len(sel_set) > 0:                df.zoomToSelectedFeatures()                     arcpy.RefreshActiveView()         


Or, if you are still wanting to use the individual rows of the cursor for some reason, you could get the extent of each SHAPE@ value of the row object (this does exactly what the above code does, so I am not sure if it will benefit you. I just thought it is more inline with your OP code):

  for lyr in arcpy.mapping.ListLayers(mxd):          tlyr = lyr            dsc = arcpy.Describe(tlyr)         sel_set = dsc.FIDSet         if dsc.shapeType == "Polygon":           if len(sel_set) > 0:                with arcpy.da.SearchCursor(tlyr, ("SHAPE@")) as cursor:                  for row in cursor:                      shape = row[0]                      zoomextent = shape.extent               df.extent = zoomextent              arcpy.RefreshActiveView()                  

View solution in original post

0 Kudos
14 Replies
JamesCrandall
MVP Frequent Contributor
This seems to give me the SHAPE@XY value of a selected polygon feature in a FGDB FeatureClass I have loaded into ArcMap 10.1 -- ignore the first "if" statement if you are not concerned about checking for GroupLayer data.


mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd)[0]

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.isGroupLayer:
       for sublyr in lyr:
          if dsc.shapeType == "Polygon":
            with arcpy.da.SearchCursor(sublyr, "SHAPE@XY")) as cursor:
                   for row in cursor:
                       arcpy.AddMessage(str(row))
    else:
        tlyr = lyr   
        if dsc.shapeType == "Polygon":
          with arcpy.da.SearchCursor(tlyr, ("SHAPE@XY")) as cursor:
                 for row in cursor:
                     arcpy.AddMessage(str(row))
                      

0 Kudos
T__WayneWhitley
Frequent Contributor
Just to extend what James already said, to zoom to the centroid of a feature, you'd likely feed in an Extent based on the centroid xy return you're interested in to the df obj he already established (see his code), then if I'm not mistaken you have to refreshActiveView.

I think your trick will be to establish the extent from your point coords...not a big deal, but you need to establish xy min and max, not just a single point coord.  Otherwise, there is a zoomToSelectedFeatures, but that'll very likely yield different results for you.

...even if your extent obj established doesn't quite provide the zoom level you want, you may 'readjust' the scale property, as in DataFrame example 2 on this page:


DataFrame (arcpy.mapping)
Desktop » Geoprocessing » ArcPy » Mapping module
http://resources.arcgis.com/en/help/main/10.1/index.html#//00s300000003000000


Enjoy,
Wayne
0 Kudos
JamesCrandall
MVP Frequent Contributor
To follow up with Waynes contribution, if all you want to do is zoom to a selected feature -- you could just do that too and not even worry about centroids or extents of anything.

 for lyr in arcpy.mapping.ListLayers(mxd):          tlyr = lyr            dsc = arcpy.Describe(tlyr)         sel_set = dsc.FIDSet         if dsc.shapeType == "Polygon":           if len(sel_set) > 0:                df.zoomToSelectedFeatures()                     arcpy.RefreshActiveView()         


Or, if you are still wanting to use the individual rows of the cursor for some reason, you could get the extent of each SHAPE@ value of the row object (this does exactly what the above code does, so I am not sure if it will benefit you. I just thought it is more inline with your OP code):

  for lyr in arcpy.mapping.ListLayers(mxd):          tlyr = lyr            dsc = arcpy.Describe(tlyr)         sel_set = dsc.FIDSet         if dsc.shapeType == "Polygon":           if len(sel_set) > 0:                with arcpy.da.SearchCursor(tlyr, ("SHAPE@")) as cursor:                  for row in cursor:                      shape = row[0]                      zoomextent = shape.extent               df.extent = zoomextent              arcpy.RefreshActiveView()                  
0 Kudos
JacobDrvar
New Contributor II
I was thinking of using a zoom to centroid approach, since my field has multiple attributes with the same name.  Also, if I am in zoomed in working on a feature class, I would use the zoom to centroid of my Subd field, and see the feature class at another scale.
0 Kudos
JamesSmith7
New Contributor
I was thinking of using a zoom to centroid approach, since my field has multiple attributes with the same name.  Also, if I am in zoomed in working on a feature class, I would use the zoom to centroid of my Subd field, and see the what is left to modify within that Subd area.
0 Kudos
T__WayneWhitley
Frequent Contributor
...like that a lot, what you did with Describe,
arcpy.Describe(tlyr).FIDSet

One of the things I haven't been too fond of is RefreshActiveView -- I don't like 'flashing' the screen unnecessarily, so essentially if there's no selection there's no need to change or refresh the view.

Thanks James, I have to remember that one.


EDIT:
Oops I tried to delete that duplicate post and both were deleted, sorry.  So, relevant info is here in the web help in case you need it:

DataFrame (arcpy.mapping)
Desktop » Geoprocessing » ArcPy » Mapping module
http://resources.arcgis.com/en/help/main/10.1/index.html#//00s300000003000000
0 Kudos
JamesSmith7
New Contributor
Is it possible to select the polygon, hit a python addin button and zoom to centroid?  Or am I required to run the tool by selecting the polygon, entering input parameters, and then zoom to the centroid?  I would like to perform the operation without having to enter input parameters.  But, I am unsure if Python has this capability.
0 Kudos
JamesCrandall
MVP Frequent Contributor
Is it possible to select the polygon, hit a python addin button and zoom to centroid?  Or am I required to run the tool by selecting the polygon, entering input parameters, and then zoom to the centroid?  I would like to perform the operation without having to enter input parameters.  But, I am unsure if Python has this capability.


Yes, and if that is the workflow you decide on then the df.zoomToSelectedFeatures() will work out just fine.  It will zoom to the extent of the selected  feature though, not the cetnroid so not sure if that affects your requirement.

Just code the onClick event of your Python Add-In button:


class ButtonClass_WorkSelection(object):
    """Implementation for MyTools_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        
        mxd = arcpy.mapping.MapDocument("CURRENT")
        df = arcpy.mapping.ListDataFrames(mxd)[0]
        for lyr in arcpy.mapping.ListLayers(mxd):

           tlyr = lyr   
           dsc = arcpy.Describe(tlyr)
           sel_set = dsc.FIDSet
           if len(sel_set) > 0:  
              df.zoomToSelectedFeatures()       
              arcpy.RefreshActiveView()

0 Kudos
JamesSmith7
New Contributor
Yes, I am going with the centroid approach.  I took your advice on adding the above script into the add in.  But, when clicking on the button, I get the message stating the tool has no parameters.  I have been unable to get buttons to work without input parameters.
0 Kudos