這個CGAL python binding example非常適合展示如何使用AABB樹來獲得三角湯上最近的點。不幸的是,它只返回最近三角形上的單個最近點。使用CGAL python綁定查詢三角形上的最近點
我正在尋找一個函數,我可以提供一個查詢點(s),一個三角形數組,然後得到每個三角形的最近點作爲返回。
我發現做到這一點的唯一方法是通過遍歷一次三角形之一,做出AABB_tree_Triangle_3_soup每個和查詢......這感覺非常低效的,特別是因爲example顯然可以處理的數組三角形一次。
爲了說明這一點,這裏有一個像我正在尋找:
紅點查詢點,每個藍點是三角形的頂點,綠點是最接近因爲它是投影,因此每條線都有點。
這是我想出的代碼。代碼有效,但不是很漂亮。
# Imports
import time
import numpy as np
from scipy.spatial import cKDTree
from CGAL.CGAL_Kernel import Point_3
from CGAL.CGAL_Kernel import Triangle_3
from CGAL.CGAL_AABB_tree import AABB_tree_Triangle_3_soup
# Setup the source data
# ---------------------
# Create large numpy array of triangles
N_TRIANGLES = 100000 #100K triangles
np_triangles = np.random.random_sample((N_TRIANGLES,3,3,)) # lets make a random array for this example
# Create a random query point
np_query = np.random.random_sample((3,)) * 100 # lets use a random point for this example
# Convert the data so we can use CGAL
cgal_triangles = []
for p in np_triangles:
a = Point_3(p[0][0],p[0][1],p[0][2])
b = Point_3(p[1][0],p[1][1],p[1][2])
c = Point_3(p[2][0],p[2][1],p[2][2])
cgal_triangles.append(Triangle_3(a,b,c))
cgal_query = Point_3(np_query[0],np_query[1],np_query[2])
# Test begins!
# ------------
# If all i care for is to find THE closest point on all the given triangles to the query point, it's easy:
def simple_closest():
tree = AABB_tree_Triangle_3_soup(cgal_triangles)
cp = tree.closest_point(cgal_query)
return np.array([cp.x(),cp.y(),cp.z()])
simple_closest_result = simple_closest()
# Unfortunately, what i want is a return value for all given triangles, which i could sort in the future for N closest if need be
# The only way i found to do this is to make an AABB tree per triangle, which sounds silly, and is the focus of my question
def all_closest():
cp = []
for t in cgal_triangles:
tree = AABB_tree_Triangle_3_soup([t])
p = tree.closest_point(cgal_query)
cp.append([p.x(),p.y(),p.z()])
return np.array(cp)
all_closest_result = all_closest()
# From here, if i wish to sort the results to get all the points from closest to furthest, i can do that
N = 8 # Lets say i want the 8 closest triangles to the query point
n = max(min(N, N_TRIANGLES), 1) # clamp n <= tri count
def n_closest():
kdTree = cKDTree(all_closest_result)
q = kdTree.query(np_query,k=n)
return all_closest_result[q[1]], q[0], q[1]
n_closest_result = n_closest()
print ''
print 'Does the closest item match: %s'%np.allclose(n_closest_result[0][0],simple_closest_result)
print 'Closest Simple:\n%s'%simple_closest_result
print '%s closest'%n
print n_closest_result[0]
這個例子顯示了我必須一次遍歷三角形。爲每個三角形創建一個AABB_tree_Triangle_3_soup,然後查詢。這聽起來非常低效。特別是在處理許多許多查詢時,例如100萬個三角形列表的100k查詢。
所以,我正在尋找的是比我的迭代方法更好的方法。希望一個命令,如:
樹= AABB_tree_Triangle_3_soup(三角形) tree.all_points(查詢)#返回未排序的最接近點 tree.all_closest(查詢,N = 56)#返回56個最近點
我很抱歉誤導你與我如何制定我的問題。我之前提出我的問題的方式聽起來像我試圖在CGAL中找到N個最近點。我正在尋找三角形上N個最近的點。我提到的例子給了我最近的點,這很有用,但如果CGAL可以給我N個三角形上的最近點到查詢點,那麼最好,然後我可以使用你的Spacial搜索示例(或scipy's cKDTree)來爲最近的一個排序。 – Fnord
我編輯了問題的清晰度 – Fnord
我不確定它是否合理。三角形中最近點的整個鄰域將包含所有最接近的點。 – sloriot