From e4aef2faaa661097939b181f9ac734c8acfca779 Mon Sep 17 00:00:00 2001 From: Harley Date: Tue, 7 Jul 2026 03:40:58 -0400 Subject: [PATCH] =?UTF-8?q?Remove=20bounding-box=20normalization=20?= =?UTF-8?q?=E2=80=94=20compare=20paths=20in=20original=20dp=20space?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- swipetype-core/src/IdealPathGenerator.cpp | 27 +++---------------- swipetype-core/src/PathProcessor.cpp | 32 +++++------------------ 2 files changed, 9 insertions(+), 50 deletions(-) diff --git a/swipetype-core/src/IdealPathGenerator.cpp b/swipetype-core/src/IdealPathGenerator.cpp index 1f6fdd5..ec7c0fa 100644 --- a/swipetype-core/src/IdealPathGenerator.cpp +++ b/swipetype-core/src/IdealPathGenerator.cpp @@ -69,31 +69,12 @@ struct IdealPathGenerator::Impl { return result; } - // Normalize to [0,1] bounding box + // Keep coordinates in original dp space static GesturePath normalizeBB(const std::vector& points, float arcLen) { GesturePath result; if (points.empty()) return result; - float minX = points[0].x, maxX = points[0].x; - float minY = points[0].y, maxY = points[0].y; - for (const auto& p : points) { - minX = std::min(minX, p.x); - maxX = std::max(maxX, p.x); - minY = std::min(minY, p.y); - maxY = std::max(maxY, p.y); - } - float width = maxX - minX; - float height = maxY - minY; - - if (width < 0.001f && height < 0.001f) { - result.points.assign(points.size(), NormalizedPoint(0.5f, 0.5f, 0.5f)); - result.aspectRatio = 1.0f; - result.totalArcLength = arcLen; - return result; - } - - float scale = std::max(width, height); - result.aspectRatio = (height > 0.001f) ? (width / height) : 1.0f; + result.aspectRatio = 1.0f; result.totalArcLength = arcLen; int64_t firstTs = points.front().timestamp; @@ -102,12 +83,10 @@ struct IdealPathGenerator::Impl { result.points.reserve(points.size()); for (const auto& p : points) { - float nx = (p.x - minX) / scale; - float ny = (p.y - minY) / scale; float nt = (tsRange > 0.0f) ? static_cast(p.timestamp - firstTs) / tsRange : 0.5f; - result.points.emplace_back(nx, ny, nt); + result.points.emplace_back(p.x, p.y, nt); } return result; } diff --git a/swipetype-core/src/PathProcessor.cpp b/swipetype-core/src/PathProcessor.cpp index bfa5acb..8435817 100644 --- a/swipetype-core/src/PathProcessor.cpp +++ b/swipetype-core/src/PathProcessor.cpp @@ -114,7 +114,10 @@ struct PathProcessor::Impl { } /** - * Normalize coordinates to [0,1] bounding box preserving aspect ratio. + * Keep coordinates in original dp space — no bounding-box normalization. + * The gesture and ideal paths naturally share the same coordinate space + * (both derived from the same KeyboardLayout), so DTW on absolute + * positions correctly measures spatial distance on the keyboard. */ GesturePath normalizeBoundingBox(const std::vector& points, float totalArcLength) const { @@ -122,28 +125,7 @@ struct PathProcessor::Impl { if (points.empty()) return result; - float minX = points[0].x, maxX = points[0].x; - float minY = points[0].y, maxY = points[0].y; - for (const auto& p : points) { - minX = std::min(minX, p.x); - maxX = std::max(maxX, p.x); - minY = std::min(minY, p.y); - maxY = std::max(maxY, p.y); - } - - float width = maxX - minX; - float height = maxY - minY; - - // Degenerate: near-point path - if (width < 0.001f && height < 0.001f) { - result.points.resize(points.size(), NormalizedPoint(0.5f, 0.5f, 0.5f)); - result.aspectRatio = 1.0f; - result.totalArcLength = totalArcLength; - return result; - } - - float scale = std::max(width, height); - result.aspectRatio = (height > 0.001f) ? (width / height) : 1.0f; + result.aspectRatio = 1.0f; result.totalArcLength = totalArcLength; int64_t firstTs = points.front().timestamp; @@ -152,12 +134,10 @@ struct PathProcessor::Impl { result.points.reserve(points.size()); for (const auto& p : points) { - float nx = (p.x - minX) / scale; - float ny = (p.y - minY) / scale; float nt = (tsRange > 0.0f) ? static_cast(p.timestamp - firstTs) / tsRange : 0.5f; - result.points.emplace_back(nx, ny, nt); + result.points.emplace_back(p.x, p.y, nt); } return result;