Quote:Original post by iMalc
Next, reduce the work done each time we find a point closer than the last one. Instead of dereferencing a pointer twice over two lines of code, I just remember the pointer.
That's a little awkward. But we can make it make sense interface-wise by returning the actual point instead of a copy of its value. Or, more generally, a handle for it.
Quote:Note that I'm expecting the compiler to perform comon sub-expression elimination for the xSqr and ySqr calculations to avoid the double-dereferences. If not, that can be taken care of manually.
Then you might as well write a function for the ugly part and expect it to be inlined. :) I'm doubtful that complicating the logic in order to test one dimension separately is a net win, for that matter. After all, there's an extra branch that way and I can't imagine it being terribly well-predicted. (Of course, the existing branch isn't terribly well-predicted either :) So maybe it wouldn't matter. I don't know.)
Quote:I hope POINT has an appropriate default constructor because otherwise this function (your version or mine) returns garbage when the vector is empty.
The version I propose below returns something unusable that has to be checked for. That's better IMO than replacing garbage with a "valid" but wrong value (i.e. a point at the origin). Of course, the calling code should check for this anyway.
Quote:I do have to question why you store pointers to points in the vector instead of just the points themselves though.
I expect this to make a bigger difference than many of the other changes. It costs memory, too, to store the actual pointers in addition to the POINTs.
The only reason you'd want to set up a vector of pointers like this, to something as simple as a POINT structure, would be for some kind of "index buffer" technique, where the points are potentially shared or repeated. But in that case, the points still have to be stored somewhere, and you should be searching
that storage (since it doesn't have the duplicates).
Accordingly, I wrote the example assuming that this is fixed. ;)
typedef vector<POINT> points_t;int squaredDistanceBetween(const Point& a, const Point& b) { int dx = a.x - b.x; int dy = a.y - b.y; return dx*dx + dy*dy;}// "mouse_" doesn't belong in parameter names here, because the function// doesn't care that the point in question came from a mouse.points_t::iterator nearestPointTo(const points_t& v, int x, int y) { return nearestPointTo(v, POINT(x, y));}points_t::iterator nearestPointTo(const points_t& v, const Point& p) { points_t::iterator result = v.begin(), end = v.end(); if (result == end) { return result; } int bestSquaredDistance = squaredDistanceBetween(*result, p); for (points_t::iterator it = ++result, end = v.end(); it != end; ++it) { int squaredDistance = squaredDistanceBetween(*it, p); if (squaredDistance < bestSquaredDistance) { bestSquaredDistance = squaredDistance; result = it; } } return result;}
(And before you ask why I don't get really fancy and use std::min_element: the custom comparator supplied for that would end up evaluating the squared-distance twice for (almost) each Point.)