Select to view content in your preferred language

How to test using ArcPy for an existing Point feature at a given location

994
15
Jump to solution
01-28-2026 11:54 AM
PeterAnderton
Emerging Contributor

I have an process that will calculate (x, y) coordinate pairs from other data, and I also have an existing feature class of Points. How can I test using ArcPy whether there is already an existing Point feature at my calculated (x, y) position? The idea is that if there IS an existing Point at that position, then I will note a particular field value of that Point and use it elsewhere in the wider process; if there ISN'T an existing Point then I will generate a new one at that position.

The rationale behind this is that I am trying to recreate using Python within ArcGIS Pro a process that I actually first wrote over two decades ago (!) using MapBasic within the MapInfo GIS. MapBasic had a very handy function called SearchPoint(), which simply took a Point feature class name plus the (x, y) coordinates of interest as parameters, and returned how many points there were at that location (although all I needed to know was whether the answer was zero or non-zero). After extensive online searching I cannot find anything directly equivalent within ArcGIS Python. Functions such as Count Overlapping, Near Table, Buffer, etc. all seem to work with all features within a feature class, or compare all features in one class against all features in another, etc., which isn't what I'm looking for.

Some might suggest calculating all my required (x, y) locations first, removing any duplicates, then generating all my Points in one go, but the process doesn't work like that; coordinates will change over time, new Points may or may not be needed on an ad hoc basis. I just want a simple test of a single given location against a dataset of existing Points that I can use within a wider Python script.  

Obviously I could just iterate over all existing Points, testing each one in turn against my calculated coordinates, but I wanted to know whether there was some existing ArcPy function optimised for my intended use case, as thus far I have not been able to find anything remotely similar.

I should perhaps stress that, although in a previous life many years ago I wrote thousands of lines of MapBasic, I am new to Python programming in ArcGIS Pro, so I may well be missing something blindingly obvious!

0 Kudos
1 Solution

Accepted Solutions
DanPatterson
MVP Esteemed Contributor

You can read from the featureclass (fc) what you want

array = arcpy.da.FeatureClassToNumPyArray(fc, ["OID@", "SHAPE@XY"])  # oid and paired coordinates
array = arcpy.da.FeatureClassToNumPyArray(fc, ["SHAPE@X","SHAPE@Y"]) # just the x, y as separate fields
# "some!!!" of the possibilities are in the code samples

... sort of retired...

View solution in original post

0 Kudos
15 Replies
AlfredBaldenweck
MVP Frequent Contributor

something like this (untested) should probably work

tbl = r"...\points" # Existing points
pairs = [(X1, Y1), (X2, Y2)] # Points to test

#Get list of all current coordinate points
pointList = []
with arcpy.da.SearchCursor(tbl, ["SHAPE@"]) as cursor:
    for row in cursor:
        pointList.append(row[0].centroid)

# Check each new point to see if it's already there
for pair in pairs:
    if pair in pointList:
        continue
    else:
        #do something

 

I'd check to make sure that the given coordinates are in the same format, as well as like, making sure that if one of them has  a Z or an M, both of them do.

0 Kudos
DanPatterson
MVP Esteemed Contributor

a bit issue in any solution would be how you address floating point issues. 

Are you limiting the decimal precision of the inputs?  (ie 3 decimals for data in a projected coordinate system)

How close is close? or is 'exact' the only case you are interested in?  (eg [400,000.01, 5,000,000.01] versus [400,000.00, 5,000,000.00]

The could be a cases  made to use NumPy to facilitate comparisons since it has options to simplify inclusion, closesness or equality tests with or without tolerances.  Arcpy has FeatureClassToNumPy array that facilitates getting point coordinates into an appropriate array format.  The next stage would be whether your points that you want to test are entered manually, read from a text file or something else. 

 


... sort of retired...
AlfredBaldenweck
MVP Frequent Contributor

Fair point!

0 Kudos
PeterAnderton
Emerging Contributor

Clearly that's a valid question, all though in the original use case I am trying to replicate it would have been an exact match; moreover, although the original SearchPoint() function returned a count of Points at that location, the result would only ever have been either zero or 1. I won't bore you with the full details of the original process, partly because it doesn't affect my original question and partly because I was just looking for an ArcPy equivalent function that could also be used elsewhere, not solely in what I am trying to replicate.

0 Kudos
PeterAnderton
Emerging Contributor

That's an interesting approach. For a single test location (x, y), you're suggesting generating a list of coordinate pairs from all existing Point geometries first, then using the IN function to see whether my (x, y) pair appears within that list in a single comparison step.

That's certainly a helpful idea, although given that I would still need to iterate over all Points to list their respective coordinates first in order to do the comparison step, that rather confirms my suspicion that there isn't an existing ArcPy function equivalent to MapBasic's SearchPoint().

Many thanks for the suggestion.

0 Kudos
DanPatterson
MVP Esteemed Contributor
import numpy as np
pnts = np.random.rand(10,2) * 100
pnts = np.round(pnts, 2)  # 2 decimal precision
p = pnts[2]  # -- take a sample point (2nd position)for testing inclusion/equality

np.isin(p, pnts).all(-1)  # are both x and y coordinates the same 
True

# now where is it
np.nonzero((p == pnts).all(-1))[0]  # we took the 2nd point remember
array([2])

# inputs for sample points and a single point
pnts
 
array([[38.79, 17.36],
       [54.56, 80.24],
       [83.56, 54.81],
       [98.59, 48.87],
       [98.64, 98.10],
       [26.62,  1.80],
       [85.05, 15.94],
       [53.33, 85.95],
       [ 8.25,  3.17],
       [94.05, 77.85]])

p
array([83.56, 54.81])

Read once, test as appropriate or test many

ps = pnts[[0, 2, 4, 6]]  # take the various points

np.nonzero((ps == pnts[:, None]).all(-1))[0]  # where are they, broadcasting necessary
array([0, 2, 4, 6])

ps
array([[38.79, 17.36],
       [83.56, 54.81],
       [98.64, 98.10],
       [85.05, 15.94]])

... sort of retired...
0 Kudos
PeterAnderton
Emerging Contributor

Thank you for that. I haven't used numpy (other than on a training course!), but I can see this is a similar approach to that from AlfredBaldenweck. Basically I generate a list / array / dataframe / whatever of coordinate pairs from all the existing Points, then use a single direct comparison function to see if my coordinate pair of interest appears therein. In this example, the np.nonzero() function also returns the index of each match, which could be useful for extracting other field data from any such match. Very interesting!

0 Kudos
DanPatterson
MVP Esteemed Contributor

FeatureClassToNumPyArray

FeatureClassToNumPyArray—ArcGIS Pro | Documentation

can replace the searchcursor and the resultant array can be queried should you need to check other attributes.  There has been some generalities here since your original question was solely about coordinates


... sort of retired...
0 Kudos
PeterAnderton
Emerging Contributor

A quick look at that documentation suggests that the entire feature class gets converted in one go, and optionally with only the fields of interest (in addition to the (x, y) coordinates). That's definitely better than having to iterate over all Points, and would give me all that I need.

The short answer to my original question appears to be that there isn't a dedicated ArcPy function that does what I want, but the information I have received since posing that question certainly points to a solution I would never have thought of! 

0 Kudos