From 65cb3dfde90bb8ae1c5751b86f006ecf67c1af22 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Sat, 30 Nov 2019 11:58:51 +0100 Subject: [PATCH] Keyframe::GetClosestPoint(): Use binary search --- src/KeyFrame.cpp | 53 +++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 686626b0..6b186d37 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -121,39 +121,32 @@ bool Keyframe::Contains(Point p) const { // Get current point (or closest point) from the X coordinate (i.e. the frame number) Point Keyframe::GetClosestPoint(Point p, bool useLeft) const { - Point closest(-1, -1); - - // loop through points, and find a matching coordinate - for (int64_t x = 0; x < Points.size(); x++) { - // Get each point - Point existing_point = Points[x]; - - // find a match - if (existing_point.co.X >= p.co.X && !useLeft) { - // New closest point found (to the Right) - closest = existing_point; - break; - } else if (existing_point.co.X < p.co.X && useLeft) { - // New closest point found (to the Left) - closest = existing_point; - } else if (existing_point.co.X >= p.co.X && useLeft) { - // We've gone past the left point... so break - break; - } + if (Points.size() == 0) { + return Point(-1, -1); } - // Handle edge cases (if no point was found) - if (closest.co.X == -1) { - if (p.co.X <= 1 && Points.size() > 0) - // Assign 1st point - closest = Points[0]; - else if (Points.size() > 0) - // Assign last point - closest = Points[Points.size() - 1]; - } + // Finds a point with an X coordinate which is "not less" (greater + // or equal) than the queried X coordinate. + std::vector::const_iterator candidate = + std::lower_bound(begin(Points), end(Points), p.co.X, IsPointBeforeX); - // no matching point found - return closest; + if (candidate == end(Points)) { + // All points are before the queried point. + // + // Note: Behavior the same regardless of useLeft! + return Points.back(); + } + if (candidate == begin(Points)) { + // First point is greater or equal to the queried point. + // + // Note: Behavior the same regardless of useLeft! + return Points.front(); + } + if (useLeft) { + return *(candidate - 1); + } else { + return *candidate; + } } // Get current point (or closest point to the right) from the X coordinate (i.e. the frame number)