# Linking points within a specified tolerance

I have a set of points, and I want to build lines between pairs of points whenever their separating distance is within a specified tolerance. For example, 3 or 4 meters. Is there a way to do it in FME?

• I suggest you specify a software you're working with.
– Erik
Commented Mar 25, 2021 at 9:49
• A short answer: yes it is possible, but to answer how we need more details and more focus from you. For instance, the decision about a software/tool, what have you tried etc. Commented Mar 25, 2021 at 9:49
• Do they share some attribute? Or is it obvious which two pair of points should be connected?
– Bera
Commented Mar 25, 2021 at 10:05
• I am working with ArcGIS, but I can manage to use Qgis or FME Unfortunatly the points have no common attributes, just their X and Y coordinates Commented Mar 25, 2021 at 10:08
• "I can manage to use three different softwares" is no specification.
– Erik
Commented Mar 25, 2021 at 11:00

The NeighborFinder transformer is the tool for this.

Finds the nearest Candidate feature(s) to each Base feature and merges their attributes onto the Base feature. May also be used in Candidates Only mode, where each feature is considered the Base in turn and compared to all other features, but not itself.

You can set the maximum distance to your tolerance of 3 or 4 metres.

Here is a script in arcpy:

1 - Create a empty geodatabase

2 - copy your points inside it

Points - should be in projected coordinates system (the length need to be calculated).

3 - Create an empty line feature inside this .gdb (in the same coordinate system with points)

4 - change the parameters, depending in your paths and change the tolerance

5 - run the script

6 - the result will be extended in the line feature class, and some useful information will be added (linked points id,coordinates).

https://github.com/florjanv/Points-2-lines

``````import arcpy
import math

#parameters
f = r"C:\Users\user\Desktop\test\points\temp.gdb\Points" #input points feature class
lines_f = r"C:\Users\user\Desktop\test\points\temp.gdb\Lines" #empty line feature class
tolerance = 4 #the tolerance in meters

#variables
feature_id = []
total_x = []
total_y=[]
lines = []

def main():
desc = arcpy.Describe(f)
noZvalue()
try:
except:
print("fields exists")

with arcpy.da.InsertCursor(lines_f,["SHAPE@","from_id","from_xy","to_id","to_xy"]) as cursor:
for i in feature_id:
if lines[i]:
for j in lines[i]:
array = arcpy.Array([arcpy.Point(total_x[i], total_y[i]), arcpy.Point(total_x[j], total_y[j])])
cursor.insertRow([arcpy.Polyline(array),i+1,str(total_x[i])+", "+str(total_y[i]),j+1,str(total_x[j])+", "+str(total_y[j])])

#remove dublicated lines
arcpy.CalculateField_management(lines_f,"length","!SHAPE_Length!","PYTHON_9.3")
arcpy.CalculateField_management(lines_f,"dub",'str(!length!) +", " +str(abs( !from_id! - !to_id! ))',"PYTHON_9.3")
arcpy.DeleteIdentical_management(lines_f, "dub")

def noZvalue(): #function for calculating the distances without Z coordinate
oid = 0
for a in arcpy.da.SearchCursor(f,["SHAPE@X","SHAPE@Y"]):
total_x.append(round(a[0],4))
total_y.append(round(a[1],4))
feature_id.append(oid)
oid+=1
#fill the variable with id's that are nearer than 4m
for i in feature_id:
v1=[]
for j in feature_id:
dist=0
dist = math.sqrt(math.pow(total_x[j]-total_x[i],2)+math.pow(total_y[j]-total_y[i],2))
if dist<=tolerance:
if dist ==0: continue
v1.append(feature_id[j])
lines.append(v1)

if __name__ == "__main__":
main()
``````

Result, calculated for 1000 points: