Release v0.6.25: recognize pencil strokes as straight lines

This commit is contained in:
2026-11-01 23:00:59 +02:00
parent 20f3b72287
commit 908985d775
11 changed files with 80 additions and 21 deletions
+3 -1
View File
@@ -1537,12 +1537,14 @@ LRESULT CALLBACK captureProc(HWND w, UINT msg, WPARAM wp, LPARAM lp)
!c->marks.back().fromNumber && !c->marks.back().toNumber &&
!c->marks.back().fromLink.target && !c->marks.back().toLink.target) {
ScreenshotShape recognized{};
auto improved=improveScreenshotStroke(c->marks.back().points,&recognized);
bool straightLine=false;
auto improved=improveScreenshotStroke(c->marks.back().points,&recognized,&straightLine);
if(!improved.empty()) {
c->remember(c->marks);
auto &mark=c->marks.back();
mark.points=std::move(improved);
mark.from=mark.points.front(); mark.to=mark.points.back();
if(straightLine) { mark.points.clear(); mark.freehand=false; }
if(recognized!=ScreenshotShape::None) {
mark.shape=recognized; mark.freehand=false; mark.ends=LineEnds::None;
auto bounds=markBounds(mark);
+24 -2
View File
@@ -40,14 +40,36 @@ inline double cross(Point a, Point b, Point c) { return (b.x-a.x)*(c.y-a.y)-(b.y
namespace ks {
// Returns a replacement path; an empty result means no visible improvement.
// Report recognized geometry separately from a smoothed freehand path.
inline std::vector<POINT> improveScreenshotStroke(const std::vector<POINT> &input, ScreenshotShape *shape=nullptr) {
inline std::vector<POINT> improveScreenshotStroke(const std::vector<POINT> &input, ScreenshotShape *shape=nullptr,
bool *straightLine=nullptr) {
if(shape) *shape=ScreenshotShape::None;
if(straightLine) *straightLine=false;
using namespace stroke_detail;
if(input.size()<5) return {};
if(input.size()<3) return {};
std::vector<Point> raw;
for(auto p:input) if(raw.empty() || distance(raw.back(),{double(p.x),double(p.y)})>0)
raw.push_back({double(p.x),double(p.y)});
double total=length(raw);
if(raw.size()>=3) {
double span=distance(raw.front(),raw.back());
if(span>=24 && total<=span*1.35) {
double tolerance=std::clamp(span*.03,2.0,6.0),maximum=0,backtracking=0,previous=0;
Point a=raw.front(),b=raw.back();
// Check every original point so a short excursion cannot disappear in resampling.
for(auto p:raw) {
maximum=std::max(maximum,segmentDistance(p,a,b));
double along=((p.x-a.x)*(b.x-a.x)+(p.y-a.y)*(b.y-a.y))/span;
backtracking+=std::max(0.0,previous-along); previous=along;
}
double squared=0;
for(auto p:sample(raw,64)) { double d=segmentDistance(p,a,b); squared+=d*d; }
if(maximum<=tolerance && std::sqrt(squared/64)<=tolerance*.7 &&
backtracking<=std::max(2.0,span*.02)) {
if(straightLine) *straightLine=true;
return {input.front(),input.back()};
}
}
}
if(raw.size()<5 || total<16) return {};
auto points=sample(raw,128);
double left=points[0].x,right=left,top=points[0].y,bottom=top;
+1 -1
View File
@@ -2,7 +2,7 @@
#include "platform.h"
namespace ks
{
inline constexpr wchar_t AppVersion[] = L"0.6.24";
inline constexpr wchar_t AppVersion[] = L"0.6.25";
inline constexpr UINT UpdateMessage = WM_APP + 7;
inline constexpr UINT UpdateCheckIntervalMs = 6 * 60 * 60 * 1000;
inline constexpr UINT UpdateNotificationRetryMs = 5 * 60 * 1000;