Create four points with slightly different properties to test other properties.
>>> pnt0 = arcpy.Point(X=1,Y=2,Z=3,M=4,ID=0) # a point
>>> pnt1 = arcpy.Point(X=1,Y=2,Z=1,M=0,ID=1) # different Z,M and ID
>>> pnt2 = arcpy.Point(X=3,Y=4,Z=2,M=2,ID=2) # different X,Y,Z,M and ID
>>> pnt3 = arcpy.Point(X=1,Y=2,Z=3,M=4,ID=3) # clone pnt0, changing ID only
Perform some equality checks to test what is comparable to pnt0. There is some fancy attribute collection and print formatting.
>>> all_pnts = [pnt0,pnt1,pnt2,pnt3]
>>> equality = [[getattr(pnt0,i) == getattr(p,i) for i in props] for p in all_pnts]
>>> for i in range(len(equality)):
... print('pnt0 vs pnt{}: {}'.format(i, equality[i]))
...
pnt0 vs pnt0: [True, True, True, True, True]
pnt0 vs pnt1: [True, True, False, False, False]
pnt0 vs pnt2: [False, False, False, False, False]
pnt0 vs pnt3: [True, True, True, True, False]
>>>
It is good, that pnt0 is identical to itself, and pnt3 only differs by the ID number. All the other comparisons identify what attributes in the properties list (prop) differ. Why not simplify things then and use the built-in methods? Well...because...
>>> pnt0 == pnt3
False
>>> pnt0.equals(pnt3)
True
>>>
The first equality check ( == ) is comparing objects and all its properties, whilst the second
check doesn’t consider the ID value. To confirm this consider the following tests.
I would expect this behaviour
real_pnt = arcpy.Point(0,0,1,1,0)
>>> real_pnt2 = arcpy.Point(0,0,1,1,0)
>>> real_pnt == real_pnt
True
>>> real_pnt == real_pnt2
False
not this
>>> real_pnt.equals(real_pnt2)
True
>>> a = arcpy.Point(X=1,Y=2,Z=3,M=4)
>>> b = arcpy.Point(X=1,Y=2,Z=3,M=0)
>>> c = arcpy.Point(X=1,Y=2,Z=0,M=0)
>>> a == b, a == c, b == c
(False, False, False)
>>> a.equals(b), a.equals(c), b.equals(c)
(True, True, True)
>>>
Shades of George Orwell...
"...all Points are equal but some Points are more equal than others..."
Disappointing if you require comparisons on all point properties.
Well PointGeometry is no better, since it depends upon the points that are used to construct it. Consider the equality check again, using PointGeometry objects instead of Point objects.
>>> pg_a = arcpy.PointGeometry(a)
>>> pg_b = arcpy.PointGeometry(b)
>>> pg_c = arcpy.PointGeometry(c)
>>>
>>> pg_a == pg_b, pg_a == pg_c, pg_b == pg_c
(False, False, False)
>>> pg_a.equals(pg_b), pg_a.equals(pg_c), pg_b.equals(pg_c)
(True, True, True)
>>>
Any comments as to why the Arcpy Point and PointGeometry class are so feable? Is the implementation in ArcObjects better? Or should I go back to using my own geometry classes.
I will be producing a summary on my blog after my musings about the various geometry classes is complete but my impressions are somewhat muted by the seemingly poor implementation or exposure to useful properties and methods.
It seems important to keep in mind that unless arcpy.Point defines a custom __eq__ or __cmp__ operator, then comparisons like pointA == pointB will only return True if pointA and pointB are references to the same object. Apparently the arcpy developers decided to stick with that behavior and define their own equals() method for geospatial comparisons.
However, IMHO your questioning of the whether the semantics of Point.equals() are adequate is a valid question.
from Joshua's post....
Since ArcGIS Pro is an Since ArcGIS Pro is an integrated 2D/3D application, it will be interesting to see if Esri extends the existing ArcPy Geometry classes or introduces new ones that support 3D differently.
any news from the ArcGIS Pro users? or is its incarnation not added to the geometry capabilities much?
> any news from the ArcGIS Pro users? or is its incarnation not added to the geometry capabilities much?
The help for pro looks awfully similar.
Beyond the ArcPy Mapping module (arcpy.mp), which had to get updated quite a bit because of how different the ArcGIS Pro UI is compared to ArcGIS Desktop, it is disappointing all of the other modules and base classes have been updated and cleaned up so little.
Esri took the release of ArcGIS Pro, a brand new application, to migrate ArcPy to Python 3.x, but I would have liked to see the migration to Python 3.x include cleaning up some of the detritus. For example, why keep the iterator.next() methods around with the cursors in ArcGIS Pro, especially the arcpy.da cursors? PEP 3114 was accepted back in 2007 as an acknowledgement that calling for the next item of an iterator in Python 2.x was/is not consistent with how other magic/dunder methods are handled in the language.
Esri did add dunder next methods in ArcGIS Pro because they had to or none of the cursors would work, but they didn't drop the explicit next method. Some might say including the explicit next method allows for a smoother transition from ArcGIS Desktop and Python 2.x to ArcGIS Pro and Python 3.x, but that argument is rather facile. The major overhaul to ArcPy Mapping already broke the smooth transition argument, and keeping an explicit next method with the cursors just promotes poor Python programming, especially for those unfortunate souls who decide to learn Python through ArcPy.
I thank all for the comments. I have 'Helpful' -ed those that provided some context to the questions. In my estimation here are some conclusions:
I applaud efforts being made and that the organization is being drawn in different directions and that the biggest return on investment will dictate what 'barking dog' gets fed first .... but come on ... what is wrong with marketing Arc* for its geometric capabilities and quality. What is also wrong with making it a showcase feature.
Some things on my wish list and for my sabbatical:
Couldn't agree more. A robust geometry library and implementation should be seen as the foundation of a Geographic Information System, not as some bin item or nice-to-have.
Esri's lack of and inconsistency with supporting empty geometries is another case in point. I opened five or more bugs in the past two weeks on this topic, and I am not battling Esri to justify cleaning up the inconsistencies and adding better support. The Romans did just fine without a zero, right? Now where is my abacus.
Update... as of this date, the geometry class remains the same in ArcMap 10.4.1 and ArcGIS Pro 1.3.1
Maybe some time in the future....
I hear you, frustrating but not surprising. I think the only big improvement/update to the ArcPy Geometry classes that users can expect in the next release is indexing and slicing of geometries.
From conversations I have had, I get the impression there is too much history behind ArcPy Geometry classes to see any major "fixes." Since the Geometry classes have worked a certain way for years (even if that way is less than ideal), and Esri doesn't know all of what their customers do with the classes as is, there is a reluctance to change existing behavior. I can't say I agree completely with the logic when it comes to some of the "fixes," but I have resigned myself, sadly.
I have been told to focus my efforts on the new ArcGIS Python API. Since the API is being written mostly from the ground up, they can (whether they will or not is a different matter) design different behavior than the ArcPy Geometry classes. I can't say I have had much luck, or feel much confidence yet, but I am focusing on trying to convince Esri to aim high with the geometry model in the new API.
THe python api unfortunately doesn't address geometry unless the underlying 'classes' have been written. It appears the focus is now on mapping and collecting and not on analysis. I had hopes that when the 3D offerings were enhanced, that would have included the pillars from which they were built
I agree with you on how the API looks now, but I have heard from various folks that analysis (including geometry) will be a future development. I wish I had more or something concrete to offer, but this is one of those times with Esri where I choose to believe because accepting the opposite will be too defeating.