4

I'm trying to figure out lengths of polyline features in a feature class with a WGS 1984 coordinate system.

Here's code to list lengths:

>>> import arcpy
>>> inFc = r"C:\Users\e1b8\Desktop\E1B8\GIS_Stackexchange\data.gdb\test"
>>> sr = arcpy.Describe (inFc).spatialReference
>>> sr.name
u'GCS_WGS_1984'
>>> with arcpy.da.SearchCursor (inFc, "SHAPE@") as cursor:
    for geom, in cursor:
        print geom.length

0.000785568606752
0.000784558202405
0.00117166138222
0.000816779544786

I'm not sure what units these lengths are in. I know it's generally in the coordinate system's linear units, but WGS 1984 has no linear units.

>>> sr.linearUnitName
u''

Ultimately I'd like to be able to write code that works with distances and is compatible with both projected and geographic coordinate systems. Usually I use the spatial reference's metersPerUnit property to get to a common unit regardless of the coordinate system's unit, but this throws an error for WGS 1984:

>>> sr.metersPerUnit

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    sr.metersPerUnit
AttributeError: SpatialReference: Get attribute metersPerUnit does not exist

So again, how can I get the length of features? And preferably, how do I figure out their lengths in meters?

6

I thought at first the arcpy.Polyline.getLength() method would work, as you can specify a measurement type and units but it did not because it is GCS. As you can see here, we are still in Decimal Degrees:

>>> with arcpy.da.SearchCursor("line_wgs", 'SHAPE@') as rows:
...     for row in rows:
...         print row[0].getLength('PLANAR', 'METERS')
...         
0.00193201661559
>>> desc = arcpy.Describe("line_wgs")
>>> desc.spatialReference.factoryCode
4326

What you can do is add a spatial reference to your search cursor (such as the Web Mercator):

>>> with arcpy.da.SearchCursor("line_wgs", 'SHAPE@', spatial_reference=arcpy.SpatialReference(102100)) as rows:
...     for row in rows:
...         print row[0].getLength('PLANAR', 'METERS')
...         
215.071313581
>>> 

Note, since WGS Web Mercator is in meters you can just use the length property as you did in your first one:

>>> with arcpy.da.SearchCursor("line_wgs", 'SHAPE@', spatial_reference=arcpy.SpatialReference(102100)) as rows:
...     for row in rows:
...         print row[0].length
...         
215.071313581
>>> 
  • 1
    Careful! Web Mercator is not actually in meters and should not be used to calculate length/distance/etc. I would suggest using a UTM Zone projection that intersects your data. – Mintx Aug 26 '15 at 17:43
  • 1
    I can't access Arc right now to verify, but think arcpy.Polyline.getLength() will still work if you specify the measurement_type as "GEODESIC" rather than "PLANAR" for a GCS. But passing the spatialref as an argument in the cursor to quickly re-project on-the-fly is great too! – John Aug 26 '15 at 17:48
  • @ John you're right about getLength() working when measurement_type is set as "GEODESIC". In my case, it returns the value in meters. Do you happen to know if this is always the case for geographic coordinate systems? – Emil Brundage Aug 26 '15 at 18:00
  • @Mintx that is a good point. You could use any projection in there, I just used web Mercator as an example I thought everyone would be familiar with. – crmackey Aug 26 '15 at 18:13
  • 1
    Again, those conditions can't be met. The data frame CS would supersede the data CS, or the cursor CS would,.. You can have an error state with an invalid coordsys, but not a valid coordsys with an invalid GCS -- the projection engine just won't bend that way. There are plenty of ways to foul up coordinate data so that innocent coordrefs get blamed when distance is unreliable, but that's a different story. – Vince Aug 27 '15 at 2:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.