Hi - the title says most of it. This may be more intermediate than beginner? Kind of a general C++ question more than just oF.
I have a pre-defined vector of > 5000 random ofVec2f 2d points in screen space.
Out of that vector I want to find the element closest to mouse x,y (or any given screen coords) at every frame.
I’m trying to find the most elegant/accurate/quickest solution - that could work with say, a vector of 300,000 elements as well as with 5000.
I can pre-sort the vector during setup() since it won’t really change (or I can insert new elements in the correct order if it does) - so I can use binary search for speed…
What I have now:
So far I have code that pre-sorts the vector by distance from (0,0) during setup().
-
During update() it uses a binary search to find the upper_bound element with distance to (0,0) closest to the mouse’s distance to 0,0.
-
Then it finds 50 elements on either side of that element, and copies the resulting 101 elements to a new temporary vector.
-
Then it sorts that small vector by distance to mouse x,y - and index [0] of that vector is the result.
It’s quite fast and works fairly well but since it’s sorting by radial distance to 0,0 it doesn’t always get the actual closest point - it prefers points along the radius of mouse’s distance to 0,0.
Anyone have a better way to get faster/more accurate results?
Thanks!
Here’s my search function:
ofVec2f mouse(ofGetMouseX(),ofGetMouseY());
vector<ofVec2f>::iterator it =
upper_bound(posVector.begin(), posVector.end(), mouse, DistComp(ofVec2f(0,0)));
// DistComp is custom binary operator that sorts vector by distance to a given ofVec2f
// grab 101 items for new vector
int index = it - posVector.begin(); // index of search result
int dFirst = 50; // distance to first index
int dLast = 50; // distance to last index
// fix if index is too close to beginning or end of vector
if (index < 50){
dFirst = index;
dLast = 100 - dFirst;
}
else if (index + 50 >= eyePositionsOrdered.size()){
dLast = (int)eyePositionsOrdered.size()-1 - index;
dFirst = 100 - dLast;
}
vector<ofVec2f>::iterator fIt = it-dFirst; // first iterator
vector<ofVec2f>::iterator lIt = it+dLast; // last iterator
vector<ofVec2f> tmpVec(101); // temporary vector
vector<ofVec2f>::iterator tmpIt = tmpVec.begin(); // iterator for copy position
copy(fIt,lIt, tmpIt); // copy into temp vector
sort(tmpVec.begin(),tmpVec.end(),DistComp(mouse)); // sort by distance to mouse
return tmpVec[0]; // closest ofVec2f to mouse (sort of...)`