As an alternative I generated a script that will calculate the 3D distance between two sets of 3D point featureclasses.
The result is a table that contains the OID of the buildings, the OID of the tunnel points and the 3D distance:
By defining two relates in ArcMap you will be able to do what you are looking for.
Relate 1: based on the tunnel points, relating to the new table.
Relate 2: based on the table relating to the building points:
Make sure to define some attribute indexes in the table to increase the performance:
How does it work. In ArcMap you select a tunnel point and open the attribute table of the tunnel point featureclass:
Click on the relate button and select the relate:
This will open the table with the related combinations selected:
Then select the relate to propagate the selection to the building points:
... which will open the selected building points:
The map will show the selection:
The script I used for this is listed below. In my case I only had 6.5M combinations and it took 2 minutes to process the combinations on an average computer. This will probably take all night processing the 264M combinations.
Script:
import math
import arcpy
from time import localtime, strftime
def main():
import os
ShowProgress("Start process...")
fc_buildings = r'D:\Xander\GeoNet\Generate3DNearTable\gdb\data.gdb\building_points_3D'
fc_tunnel_points = r'D:\Xander\GeoNet\Generate3DNearTable\gdb\data.gdb\tunnel_points_3D'
tbl_out = r'D:\Xander\GeoNet\Generate3DNearTable\gdb\data.gdb\Near3D_table_v01'
fld_building_id = 'OID_Building'
fld_tunnel_point_id = 'OID_TunnelPoint'
fld_dist3D = 'Distance3D'
max_dist = 250
ShowProgress("Create lists of buildings and tunnel points...")
flds = ('OID@', 'SHAPE@')
lst_building = [[r[0], r[1]] for r in arcpy.da.SearchCursor(fc_buildings, flds)]
lst_tunnelpoints = [[r[0], r[1]] for r in arcpy.da.SearchCursor(fc_tunnel_points, flds)]
ShowProgress("Create output table...")
tbl_ws, tbl_name = os.path.split(tbl_out)
arcpy.CreateTable_management(tbl_ws, tbl_name)
ShowProgress("Add fields to output table...")
AddField(tbl_out, fld_building_id, "LONG", 8)
AddField(tbl_out, fld_tunnel_point_id, "LONG", 8)
AddField(tbl_out, fld_dist3D, "DOUBLE", 8)
cnt_total = len(lst_building) * len(lst_tunnelpoints)
flds = (fld_building_id, fld_tunnel_point_id, fld_dist3D)
ShowProgress("Start creating combinations...")
with arcpy.da.InsertCursor(tbl_out, flds) as curs:
cnt = 0
cnt_found = 0
for building_data in lst_building:
oid_building = building_data[0]
pntg_building = building_data[1]
for tunnel_data in lst_tunnelpoints:
oid_tunnel_point = tunnel_data[0]
pntg_tunnel_point = tunnel_data[1]
cnt += 1
if cnt % 10000 == 0:
ShowProgressPercentage("Processing combination: {0}, found: {1}".format(cnt, cnt_found), cnt, cnt_total)
dist3D = get3Ddistance(pntg_building, pntg_tunnel_point)
if dist3D <= max_dist:
cnt_found += 1
row = (oid_building, oid_tunnel_point, dist3D, )
curs.insertRow(row)
ShowProgressPercentage("Ready processing {0} combinations, found: {1}".format(cnt, cnt_found), cnt, cnt_total)
def AddField(fc, fld_name, fld_type, fld_length):
if len(arcpy.ListFields(fc, fld_name)) == 0:
arcpy.AddField_management(fc, fld_name, fld_type, None, None, fld_length)
def get3Ddistance(pntg1, pntg2):
pnt1 = pntg1.firstPoint
pnt2 = pntg2.firstPoint
distance = math.sqrt((pnt1.X-pnt2.X)**2 + (pnt1.Y-pnt2.Y)**2 + (pnt1.Z-pnt2.Z)**2)
return distance
def ShowProgressPercentage(txt, cnt, cnt_tot):
current_time = strftime("%H:%M:%S", time.localtime())
if cnt_tot is None:
print "{0} - {1}".format(current_time, txt)
else:
percentage = float(cnt) * 100.0 / float(cnt_tot)
print "{0} - {1} ({2}%)".format(current_time, txt, round(percentage, 2))
def ShowProgress(txt):
current_time = strftime("%H:%M:%S", time.localtime())
print "{0} - {1}".format(current_time, txt)
if __name__ == '__main__':
main()