-
-
Notifications
You must be signed in to change notification settings - Fork 270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve ClosestPointToPoint
#699
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice work! Looking at the PQP_Distance function it looks like they use a similar approach to the hybrid method in that it starts a new sorted queue once the last one becomes full. I assume this has the benefit of limiting memory usage and preventing insertion time from becoming too long. I wonder if we'd see benefits from that solution here?
See the DistanceQueueRecurse function and this condition where it recurses and creates a new queue to traverse. Here is documentation from header file describing "qsize" use. Granted the function is a bit different because it's performing geometry-to-geometry so the queue is storing two nodes and a distance but fundamentally it's very similar.
if ( leftDistance < closestDistanceSq && leftDistance < maxThresholdSq ) { | ||
|
||
if ( _closestPointToPoint( leftIndex ) ) return true; | ||
if ( rightDistance < closestDistanceSq ) return _closestPointToPoint( rightIndex ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we want to check distance to maxThresholdSq
here, as well?
@@ -0,0 +1,20 @@ | |||
export function closestDistanceSquaredPointToBox( nodeIndex32, array, point ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering how much of the 25% improvement we would see if we used this function instead of three.js' built in version in the original "shapecast" function (see #656) - similar to the box / ray test where avoiding reading the bounds to a Box3 object gave a significant speed improvement.
if ( count >= sortedListMaxCount ) { | ||
|
||
if ( _closestPointToPoint( nodeIndex32 ) ) return; | ||
|
||
continue; | ||
|
||
} | ||
|
||
count ++; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the logic and rationale of the hybrid function a bit? It looks like it will choose the "best" node from the first 16 nodes (by default) and then fall back to the basic approach of traversing to the leaves for each of those nodes in order. The count never goes down, right?
Regarding the use of sorted queue, I would like to do more tests to understand when it is necessary. I would also like to modify the current Edit: sorry I read later that you also recommended doing to this. I'll try these days :) |
Unfortunately, modifying the I believe it is correct to expose a Could we make an alternative method for internal use, which instead of passing the Or could we stop using shapecast for internal methods (as I am doing in this PR)? Or leave it as is. The overhead of shapecast is mainly callbacks and superfluous data that is passed as a parameter but not used by the caller (like |
Thanks for checking!
I was mostly curious as to how much of the improvement was coming from this conversion to a Box3. It's worth documenting in #656, I think, but given that it's a breaking change lets not make it for now. If we have a method that would be frequently used and benefit from the performance boost (like we're doing here) then I think it makes sense. Shapecast is just easier to implement initially. I'm curious about #699 (comment) as well as how the PQP_Distance approach compares to this hybrid approach:
|
@gkjohnson Sorry for the delay... Brief recap: The current algorithm recursively checks the child node with a shorter distance first and then the second. What can be improved? Solution: Using a sortedList, I noticed that on average 30% fewer nodes are checked (using the PR geometry), but the algorithm is slower. What can be improved? Solution 1 (Hybrid Approach): Solution 2 (Hybrid Approach 2): This approach might be better than the previous one, because all nodes in the list would have precisely the same depth in the tree. Solution 3 (Two separated lists): This logic could also be applied for other algorithms that traverse via score What do you think? :) |
Thanks for the summary! Generally this seems like a good improvement. Have you tried "solution 3", as well? Was Solution 2 still best? 3 sounds closest to what the
I know it will still add some overhead but I'm wondering if this would be best added for the shapecast function so the faster algorithm is used for other queries, as well. This should just sort based on the What do you think? |
Actually I only tried the first method. I just committed the second one.
Sure, as you wish 😄 But I will finish trying the third method first. |
By not using the
shapecast
function, there is a slight improvement of about 25%.I have added a page for benchmarks to be removed later called 'testToRemove.html' (I know, I have a big imagination).
I will also add the function using the sorted list shortly (#695).
Edit: I finished 3 first versions of closestPointToPoint.