Problems constructing geometry using da.InsertCursor

1342
8
Jump to solution
01-30-2013 01:42 AM
NeilAyres
MVP Alum
I have sucessfully used the old style InsertCursor to build lots of different geometries.
But today, I decided to have a look at the new da.InsertCursor and all those "SHAPE@" tokens.

Firstly, the geometry points are coming from a table in access.
Generally each polygon has 4 records. I read these into a python dictionary of the form -
[Key] : [(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x1, y1)] ie my key is the polygon name and this points to a list of tuple pairs.
Note that I have repeated the first coord at the end so that the polygon closes.

So each of these code blocks is reading exactly the same data dictionary (PolyData).

Firstly, the old style way of doing it :

OutCur = arcpy.InsertCursor(os.path.join(OutPath, OutPoly))  for k in PolyData:     v = PolyData     array = arcpy.Array()     # print k, len(v)     for xy in v:         point = arcpy.Point()         point.X = xy[0]         point.Y = xy[1]         array.add(point)      FcPoly = OutCur.newRow()      FcPoly.setValue("PMLNo", k)     FcPoly.shape = array      OutCur.insertRow(FcPoly)          del OutCur


Then the new da way:

OutCur = arcpy.da.InsertCursor(os.path.join(OutPath, OutPoly + "2"), ["PMLNo", "SHAPE@"])  for k in PolyData:     v = PolyData     array = arcpy.Array()     # print k, len(v)     for xy in v:         point = arcpy.Point()         point.X = xy[0]         point.Y = xy[1]         array.add(point)      polygon = arcpy.Polygon(array)     data = [k, polygon]     OutCur.insertRow(data)  del OutCur


Sadly the da way gives me some decidely odd looking (and non-existant) geometries.
Have a look at the screen grab.
The red outlines are the output of the old way. The label in the middle is the polygon name.
The green outlines are the da way output. Not only has the geometry gone from a rhomboid to a triangle, but even the corners are in a different place(?).
A bigger worry is that most of this second polygon layer has null geometry. Note the lack of other green polygons, where the red ones are.

Can someone please advise me on what I am doing wrong with the da InsertCursor way of doing things.

Thanks in advance,
Neil
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
ChrisFox3
Occasional Contributor III
This might be an spatial resolution/XY tolerance issue where vertices are being snapped together because the are closer than the default XY tolerance of a geometry with an unknown spatial reference. Try passing in an appropriate spatial reference for the geometry when you create the Polygon:

OutCur = arcpy.da.InsertCursor(os.path.join(OutPath, OutPoly + "2"), ["PMLNo", "SHAPE@"]) desc = arcpy.Describe(os.path.join(OutPath, OutPoly + "2")) sr = desc.spatialReference   for k in PolyData:     v = PolyData     array = arcpy.Array()     # print k, len(v)     for xy in v:         point = arcpy.Point()         point.X = xy[0]         point.Y = xy[1]         array.add(point)      polygon = arcpy.Polygon(array, sr)     data = [k, polygon]     OutCur.insertRow(data)  del OutCur

View solution in original post

0 Kudos
8 Replies
ChrisFox3
Occasional Contributor III
This might be an spatial resolution/XY tolerance issue where vertices are being snapped together because the are closer than the default XY tolerance of a geometry with an unknown spatial reference. Try passing in an appropriate spatial reference for the geometry when you create the Polygon:

OutCur = arcpy.da.InsertCursor(os.path.join(OutPath, OutPoly + "2"), ["PMLNo", "SHAPE@"]) desc = arcpy.Describe(os.path.join(OutPath, OutPoly + "2")) sr = desc.spatialReference   for k in PolyData:     v = PolyData     array = arcpy.Array()     # print k, len(v)     for xy in v:         point = arcpy.Point()         point.X = xy[0]         point.Y = xy[1]         array.add(point)      polygon = arcpy.Polygon(array, sr)     data = [k, polygon]     OutCur.insertRow(data)  del OutCur
0 Kudos
NeilAyres
MVP Alum
Chris,
thanks. That did it. Now the output from both code blocks is exactly the same.
Does seem odd though that the "old" way doesn't require the sr to be specifically referenced. The output, btw, is a fc inside an fd in a geodb.
Perhaps one could update the help stuff to make this more explicit.

Cheers and have a nice day and all that.
Neil
0 Kudos
ChrisFox3
Occasional Contributor III
Hi Neil,

I don't know if it is a difference in the cursors, there is a slight difference in your code other than the cursor. What if in your old code you first constructed the Polygon object and then passed that into the row? I think the issue is occuring at the time you polygon object is created.

    FcPoly.setValue("PMLNo", k)
    polygon = arcpy.Polygon(array)
    FcPoly.shape = polygon
0 Kudos
jp
by
New Contributor II
Hi Chris,

I am creating geometries using the data access module similarly but I see strange performance.

The first time I created the tool from the script that reads xy from one shapefile and inserts to another. When tested with 2000 points it was completed a second. Then I started testing with other shapefiles and changed the geometry source from shapefile to Access database table. Now the tool takes 13 seconds with even lesser number of points. I retested with the original shapefile, still slow performance.

I am deleting the cursors at the end of the Execution. Is there anything else I need to clear ?

Appreciate your help!
0 Kudos
ChrisFox3
Occasional Contributor III
Hi Chris,

I am creating geometries using the data access module similarly but I see strange performance.

The first time I created the tool from the script that reads xy from one shapefile and inserts to another. When tested with 2000 points it was completed a second. Then I started testing with other shapefiles and changed the geometry source from shapefile to Access database table. Now the tool takes 13 seconds with even lesser number of points. I retested with the original shapefile, still slow performance.

I am deleting the cursors at the end of the Execution. Is there anything else I need to clear ?

Appreciate your help!


I am not sure why you are seeing a difference in performance. You might want to contact support to try to troubleshoot this issue further.
0 Kudos
NeilAyres
MVP Alum
Chris,
regardless of the slight difference in code, the "old" way has worked for ages.
The InsertCursor is pointing at a newly created Fc inside a Fd, so seems carry with it all those good things defined by the Fd.

These polygons are being created in a GCS and are quite small. About 800m by 300m in UTM projected space. Approx 0.007 of a degree and less. So, you were correct that some rounding / resolution issue was the problem with the da.InsertCursor way.

Its just that the da.InsertCursor isn't "aware" of the spatial resolution / crs of the feature it is inserting into. The old InsertCursor plainly was!

Cheers,
N
0 Kudos
ChrisFox3
Occasional Contributor III
Chris,
regardless of the slight difference in code, the "old" way has worked for ages.
The InsertCursor is pointing at a newly created Fc inside a Fd, so seems carry with it all those good things defined by the Fd.

These polygons are being created in a GCS and are quite small. About 800m by 300m in UTM projected space. Approx 0.007 of a degree and less. So, you were correct that some rounding / resolution issue was the problem with the da.InsertCursor way.

Its just that the da.InsertCursor isn't "aware" of the spatial resolution / crs of the feature it is inserting into. The old InsertCursor plainly was!

Cheers,
N


Neil, I guess what I am trying to say is the rounding occurs at this line in the code:

polygon = arcpy.Polygon(array)


If you were to inspect the geometry of the polygon object you would find this to be the case. It is not the cursor that is rounding the geometry. When you use the insert cursor you are just adding the already rounded geometry.

In your old code you never create a polygon object:

    FcPoly = OutCur.newRow()

    FcPoly.setValue("PMLNo", k)
    FcPoly.shape = array


You just pass in the array of point objects into the Shape field of the row, at this point the polygon is constructed and it takes on the spatial reference defined by the feature class. If you were to construct the polygon object from the array before passing it into the Shape field you would see the same problem.
0 Kudos
NeilAyres
MVP Alum
Chris,
Okay, I think I get it. I now understand what you were pointing out. Obvious really.
So the "Polygon" build has no prior knowledge of what these coordinates represent, and uses some default resolutions.

Thanks again for all your hard work.

Cheers,
N
0 Kudos