Skip to content

Commit

Permalink
Reduce the likelihood of drawing very small arrows
Browse files Browse the repository at this point in the history
  • Loading branch information
MuTsunTsai committed May 21, 2024
1 parent ac480eb commit f378a7d
Show file tree
Hide file tree
Showing 20 changed files with 67 additions and 162 deletions.
10 changes: 5 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

# Change log

## v4.1.1

Fix bug in label rendering.

## v4.1.0
## v4.1

If a line is later only used to make one intersection, we render it as a pinch instead of a whole line.

Patches:
- v4.1.1: Fix bug in label rendering.
- v4.1.2: Reduce the likelihood of drawing very small arrows.

## v4.0.3

Version 4.0.3 made some significant initialization performance improvements (about 40% faster) by means of the following:
Expand Down
2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><title>ReferenceFinder</title><meta charset="UTF-8"><meta name="viewport" content="initial-scale=1,maximum-scale=5,width=device-width"><meta name="description" content="Find reference points and lines in crease patterns."><link rel="icon" href="/reference-finder/favicon.ico"/><script async src="https://www.googletagmanager.com/gtag/js?id=G-GG1TEZGBCQ"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),"localhost"!=location.hostname&&gtag("config","G-GG1TEZGBCQ",{page_title:document.title,page_path:"/reference-finder/"});const settings=localStorage.getItem("settings");settings&&0!=JSON.parse(settings).state.theme||!matchMedia("(prefers-color-scheme: dark)").matches||(document.documentElement.dataset.bsTheme="dark"),"serviceWorker"in navigator&&"31213"!=location.port&&navigator.serviceWorker.register("/reference-finder/service-worker.js",{scope:"/reference-finder/"})</script><script defer="defer" src="/reference-finder/static/js/react.10390aae.js"></script><script defer="defer" src="/reference-finder/static/js/rabbit-ear.cee198ed.js"></script><script defer="defer" src="/reference-finder/static/js/vendor.3d1c998f.js"></script><script defer="defer" src="/reference-finder/static/js/index.79a53f1e.js"></script><link href="/reference-finder/static/font/fa-solid-900.6691c62b.woff2" rel="preload" as="font" crossorigin=""><link href="/reference-finder/static/css/index.ce02ef66.css" rel="stylesheet"></head><body><noscript class="p-3">You need to enable JavaScript to run this app.</noscript><div id="root" class="d-flex flex-column h-100"></div></body></html>
<!doctype html><html lang="en"><head><title>ReferenceFinder</title><meta charset="UTF-8"><meta name="viewport" content="initial-scale=1,maximum-scale=5,width=device-width"><meta name="description" content="Find reference points and lines in crease patterns."><link rel="icon" href="/reference-finder/favicon.ico"/><script async src="https://www.googletagmanager.com/gtag/js?id=G-GG1TEZGBCQ"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),"localhost"!=location.hostname&&gtag("config","G-GG1TEZGBCQ",{page_title:document.title,page_path:"/reference-finder/"});const settings=localStorage.getItem("settings");settings&&0!=JSON.parse(settings).state.theme||!matchMedia("(prefers-color-scheme: dark)").matches||(document.documentElement.dataset.bsTheme="dark"),"serviceWorker"in navigator&&"31213"!=location.port&&navigator.serviceWorker.register("/reference-finder/service-worker.js",{scope:"/reference-finder/"})</script><script defer="defer" src="/reference-finder/static/js/react.10390aae.js"></script><script defer="defer" src="/reference-finder/static/js/rabbit-ear.cee198ed.js"></script><script defer="defer" src="/reference-finder/static/js/vendor.3d1c998f.js"></script><script defer="defer" src="/reference-finder/static/js/index.029599d5.js"></script><link href="/reference-finder/static/font/fa-solid-900.6691c62b.woff2" rel="preload" as="font" crossorigin=""><link href="/reference-finder/static/css/index.ce02ef66.css" rel="stylesheet"></head><body><noscript class="p-3">You need to enable JavaScript to run this app.</noscript><div id="root" class="d-flex flex-column h-100"></div></body></html>
2 changes: 1 addition & 1 deletion docs/service-worker.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "reference-finder",
"version": "4.1.1",
"version": "4.1.2",
"description": "Find reference points and lines in crease patterns.",
"scripts": {
"start": "make && rsbuild dev -o",
Expand Down
2 changes: 1 addition & 1 deletion src/core/RFVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ NOTE: Do not edit these directly, as these values now sync with package.json aut
#define APP_FAMILY ReferenceFinder
#define VERSION_MAJOR 4
#define VERSION_MINOR 1
#define VERSION_BUGFIX 1
#define VERSION_BUGFIX 2
#define VERSION_BUILD 20240521

/******************************************************************************/
Expand Down
119 changes: 11 additions & 108 deletions src/core/class/refDgmr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,51 +57,10 @@ void RefDgmr::DrawLabel(const XYPt & /* aPt */, const string & /* aString */,
LabelStyle /* lstyle */) {
}

/*
Class RefDgmr provides a set of routines for drawing arrows that are built on
top of the primitive routines above. These can be overridden if you want to
implement a different style of arrow.
*/

/*****
Draw a valley-fold arrowhead with tip at location loc, direction dir, and size
len.
*****/
void RefDgmr::DrawValleyArrowhead(const XYPt &loc, const XYPt &dir, double len) {
DrawLine(loc, loc - len * dir.RotateCCW(.523), LINESTYLE_ARROW);
DrawLine(loc, loc - len * dir.RotateCCW(-.523), LINESTYLE_ARROW);
}

/*****
Draw a mountain arrowhead with tip at location loc, direction dir, and size len.
*****/
void RefDgmr::DrawMountainArrowhead(const XYPt &loc, const XYPt &dir, double len) {
XYPt ldir = len * dir;
vector<XYPt> poly;
poly.push_back(loc);
poly.push_back(loc - ldir.RotateCCW(.523));
poly.push_back(loc - .8 * ldir);
DrawPoly(poly, POLYSTYLE_ARROW);
}

/*****
Draw an unfold arrowhead with tip at location loc, direction dir, and size len.
*****/
void RefDgmr::DrawUnfoldArrowhead(const XYPt &loc, const XYPt &dir, double len) {
XYPt ldir = len * dir;
vector<XYPt> poly;
poly.push_back(loc);
poly.push_back(loc - ldir.RotateCCW(.523));
poly.push_back(loc - .8 * ldir);
poly.push_back(loc - ldir.RotateCCW(-.523));
DrawPoly(poly, POLYSTYLE_ARROW);
}

/*****
Calculate all the parameters necessary to draw any type of arrow (valley,
mountain, unfold, fold-and-unfold).
Calculate all the parameters necessary to draw arrow.
*****/
void RefDgmr::CalcArrow(const XYPt &fromPt, const XYPt &toPt,
void RefDgmr::CalcArrow(const XYPt &fromPt, const XYPt &toPt, const XYPt *around,
XYPt &ctr, double &rad, double &fromAngle, double &toAngle, bool &ccw,
double &ahSize, XYPt &fromDir, XYPt &toDir) {
const double RADIANS = 57.29577951;
Expand All @@ -117,13 +76,12 @@ void RefDgmr::CalcArrow(const XYPt &fromPt, const XYPt &toPt,

// Compute the center of rotation. There are two possible choices.
// We'll want the bulge of the arc to always be toward the inside of the square,
// i.e., closer to the middle of the square, so we pick the value of the center
// that's farther away.
XYPt sqmp = MidPoint(ReferenceFinder::sPaper.mBotLeft,
ReferenceFinder::sPaper.mTopRight);
// i.e., closer to the middle of the square (or away from the point around, if specified),
// so we pick the value of the center that's farther away.
XYPt target = around == NULL ? MidPoint(ReferenceFinder::sPaper.mBotLeft, ReferenceFinder::sPaper.mTopRight) : mp * 2 - *around;
XYPt ctr1 = mp + mup;
XYPt ctr2 = mp - mup;
ctr = (ctr1 - sqmp).Mag() > (ctr2 - sqmp).Mag() ? ctr1 : ctr2;
ctr = (ctr1 - target).Mag() > (ctr2 - target).Mag() ? ctr1 : ctr2;

// radius of the arc.
rad = (toPt - ctr).Mag();
Expand Down Expand Up @@ -157,9 +115,9 @@ void RefDgmr::CalcArrow(const XYPt &fromPt, const XYPt &toPt,
}

/*****
Draw a valley-fold arrow. fromPt is the moving point, toPt is the destination.
Draw a arrow. fromPt is the moving point, toPt is the destination.
*****/
void RefDgmr::DrawValleyArrow(const XYPt &fromPt, const XYPt &toPt) {
void RefDgmr::DrawArrow(const XYPt &fromPt, const XYPt &toPt, const XYPt *around) {
XYPt ctr;
double rad;
double fromAngle;
Expand All @@ -168,65 +126,10 @@ void RefDgmr::DrawValleyArrow(const XYPt &fromPt, const XYPt &toPt) {
double ahSize;
XYPt fromDir;
XYPt toDir;
CalcArrow(fromPt, toPt, ctr, rad, fromAngle, toAngle, ccw, ahSize, fromDir,
toDir);
CalcArrow(fromPt, toPt, around, ctr, rad, fromAngle, toAngle, ccw, ahSize, fromDir, toDir);
DrawArc(ctr, rad, fromAngle, toAngle, ccw, LINESTYLE_ARROW);
DrawValleyArrowhead(toPt, toDir, ahSize);
}

/*****
Draw a mountain-fold arrow. fromPt is the moving point, toPt is the
destination.
*****/
void RefDgmr::DrawMountainArrow(const XYPt &fromPt, const XYPt &toPt) {
XYPt ctr;
double rad;
double fromAngle;
double toAngle;
bool ccw;
double ahSize;
XYPt fromDir;
XYPt toDir;
CalcArrow(fromPt, toPt, ctr, rad, fromAngle, toAngle, ccw, ahSize, fromDir,
toDir);
DrawArc(ctr, rad, fromAngle, toAngle, ccw, LINESTYLE_ARROW);
DrawMountainArrowhead(toPt, toDir, ahSize);
}

/*****
Draw an unfold arrow. fromPt is the moving point, toPt is the destination.
*****/
void RefDgmr::DrawUnfoldArrow(const XYPt &fromPt, const XYPt &toPt) {
XYPt ctr;
double rad;
double fromAngle;
double toAngle;
bool ccw;
double ahSize;
XYPt fromDir;
XYPt toDir;
CalcArrow(fromPt, toPt, ctr, rad, fromAngle, toAngle, ccw, ahSize, fromDir,
toDir);
DrawArc(ctr, rad, fromAngle, toAngle, ccw, LINESTYLE_ARROW);
DrawUnfoldArrowhead(toPt, toDir, ahSize);
}

/*****
Draw a fold-and-unfold arrow. fromPt is the moving point, toPt is the
destination.
*****/
void RefDgmr::DrawFoldAndUnfoldArrow(const XYPt &fromPt, const XYPt &toPt) {
XYPt ctr;
double rad;
double fromAngle;
double toAngle;
bool ccw;
double ahSize;
XYPt fromDir;
XYPt toDir;
CalcArrow(fromPt, toPt, ctr, rad, fromAngle, toAngle, ccw, ahSize, fromDir,
toDir);
DrawArc(ctr, rad, fromAngle, toAngle, ccw, LINESTYLE_ARROW);
DrawValleyArrowhead(toPt, toDir, ahSize);
DrawUnfoldArrowhead(fromPt, fromDir, ahSize);
void RefDgmr::DrawArrow(const XYPt &fromPt, const XYPt &toPt) {
DrawArrow(fromPt, toPt, NULL);
}
23 changes: 8 additions & 15 deletions src/core/class/refDgmr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class RefDgmr {
LINESTYLE_EDGE,
LINESTYLE_HILITE,
LINESTYLE_VALLEY,
LINESTYLE_MOUNTAIN,
LINESTYLE_MOUNTAIN, // not in use
LINESTYLE_ARROW,
LINESTYLE_DOTTED,
LINESTYLE_PINCH,
Expand All @@ -53,20 +53,13 @@ class RefDgmr {
virtual void DrawLabel(const XYPt &aPt, const std::string &aString,
LabelStyle lstyle);

// Subclasses may use or override these methods
virtual void CalcArrow(const XYPt &fromPt, const XYPt &toPt,
XYPt &ctr, double &rad, double &fromAngle, double &toAngle, bool &ccw,
double &ahSize, XYPt &fromDir, XYPt &toDir);
virtual void DrawValleyArrowhead(const XYPt &loc, const XYPt &dir,
double len);
virtual void DrawMountainArrowhead(const XYPt &loc, const XYPt &dir,
double len);
virtual void DrawUnfoldArrowhead(const XYPt &loc, const XYPt &dir,
double len);
virtual void DrawValleyArrow(const XYPt &fromPt, const XYPt &toPt);
virtual void DrawMountainArrow(const XYPt &fromPt, const XYPt &toPt);
virtual void DrawUnfoldArrow(const XYPt &fromPt, const XYPt &toPt);
virtual void DrawFoldAndUnfoldArrow(const XYPt &fromPt, const XYPt &toPt);
void DrawArrow(const XYPt &fromPt, const XYPt &toPt, const XYPt *around);
void DrawArrow(const XYPt &fromPt, const XYPt &toPt);

private:
void CalcArrow(const XYPt &fromPt, const XYPt &toPt, const XYPt *around,
XYPt &ctr, double &rad, double &fromAngle, double &toAngle, bool &ccw,
double &ahSize, XYPt &fromDir, XYPt &toDir);
};

#endif
8 changes: 3 additions & 5 deletions src/core/class/refLine/refLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,7 @@ void RefLine::DrawSelf(RefStyle rstyle, short ipass) const {
// We add a tiny offset along the direction of the line,
// to prevent the label from coinciding with other labels,
// causing rendering error.
mp.x += (op1.x - op2.x) * 1e-10;
mp.y += (op1.y - op2.y) * 1e-10;
mp += (op1 - op2) * 1e-10;

string sl(1, GetLabel());
switch (rstyle) {
Expand All @@ -191,11 +190,10 @@ void RefLine::DrawSelf(RefStyle rstyle, short ipass) const {
}

void RefLine::moveCloser(XYPt &from, const XYPt &to, double dist) {
XYPt diff(from.x - to.x, from.y - to.y);
XYPt diff(from - to);
if (diff.Mag() < dist) return;
diff.NormalizeSelf();
from.x = to.x + diff.x * dist;
from.y = to.y + diff.y * dist;
from = to + diff * dist;
}

/*****
Expand Down
2 changes: 1 addition & 1 deletion src/core/class/refLine/refLineC2PC2P.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void RefLine_C2P_C2P::DrawSelf(RefStyle rstyle, short ipass) const {
p4 = mp - dp;

// Draw an arrow that connects these two points.
sDgmr->DrawFoldAndUnfoldArrow(p3, p4);
sDgmr->DrawArrow(p3, p4);
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/core/class/refLine/refLineL2L.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ void RefLine_L2L::DrawSelf(RefStyle rstyle, short ipass) const {

XYLine &l1 = rl1->l;
XYLine &l2 = rl2->l;
XYPt p;
l1.Intersects(l2, p); // intersection
XYPt p1a, p1b;
ReferenceFinder::sPaper.ClipLine(l1, p1a, p1b); // endpoints of l1
XYPt p2a, p2b;
Expand All @@ -176,14 +178,23 @@ void RefLine_L2L::DrawSelf(RefStyle rstyle, short ipass) const {
tvals.push_back((p2a - du1).Dot(up1)); // parameterize p2a along l1
tvals.push_back((p2b - du1).Dot(up1)); // parameterize p2b along l1
sort(tvals.begin(), tvals.end()); // sort them in order; we want the middle 2
XYPt p1c = du1 + 0.5 * (tvals[1] + tvals[2]) * up1;
XYPt p2c = l.Fold(p1c);

// Place the arrow closer to tvals[2] if the resulting arrow is too small
XYPt p1c, p2c;
int weight = 1;
do {
double offset = (tvals[1] + weight * tvals[2]) / (1 + weight);
p1c = du1 + offset * up1;
p2c = l.Fold(p1c);
weight++;
} while ((p1c - p2c).Mag() < 0.3 && weight < 5);

switch (mWhoMoves) {
case WHOMOVES_L1:
sDgmr->DrawFoldAndUnfoldArrow(p1c, p2c);
sDgmr->DrawArrow(p1c, p2c, &p); // Specify arrow orientation for L2L
break;
case WHOMOVES_L2:
sDgmr->DrawFoldAndUnfoldArrow(p1c, p2c);
sDgmr->DrawArrow(p1c, p2c, &p); // Specify arrow orientation for L2L
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/class/refLine/refLineL2LC2P.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void RefLine_L2L_C2P::DrawSelf(RefStyle rstyle, short ipass) const {
double t1 = abs((p1 - pi).Dot(u1p));
double t2 = abs((p2 - pi).Dot(u1p));
double tmin = t1 < t2 ? t1 : t2;
sDgmr->DrawFoldAndUnfoldArrow(pi + tmin * u1p, pi - tmin * u1p);
sDgmr->DrawArrow(pi + tmin * u1p, pi - tmin * u1p);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/core/class/refLine/refLineL2LP2L.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,17 @@ void RefLine_L2L_P2L::DrawSelf(RefStyle rstyle, short ipass) const {
double t1 = abs((p1 - pi).Dot(u1p));
double t2 = abs((p2 - pi).Dot(u1p));
double tmin = t1 < t2 ? t1 : t2;
sDgmr->DrawFoldAndUnfoldArrow(pi + tmin * u1p, pi - tmin * u1p);
sDgmr->DrawArrow(pi + tmin * u1p, pi - tmin * u1p);

// Draw point-to-line arrow
XYPt &p3 = rm1->p;
XYPt p3p = l.Fold(p3);
switch (mWhoMoves) {
case WHOMOVES_P1:
sDgmr->DrawFoldAndUnfoldArrow(p3, p3p);
sDgmr->DrawArrow(p3, p3p);
break;
case WHOMOVES_L1:
sDgmr->DrawFoldAndUnfoldArrow(p3p, p3);
sDgmr->DrawArrow(p3p, p3);
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/class/refLine/refLineP2LC2P.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ void RefLine_P2L_C2P::DrawSelf(RefStyle rstyle, short ipass) const {
XYPt p1f = l.Fold(p1);
switch (mWhoMoves) {
case WHOMOVES_P1:
sDgmr->DrawFoldAndUnfoldArrow(p1, p1f);
sDgmr->DrawArrow(p1, p1f);
break;
case WHOMOVES_L1:
sDgmr->DrawFoldAndUnfoldArrow(p1f, p1);
sDgmr->DrawArrow(p1f, p1);
break;
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/core/class/refLine/refLineP2LP2L.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,23 +355,23 @@ void RefLine_P2L_P2L::DrawSelf(RefStyle rstyle, short ipass) const {
XYPt p2b = l.Fold(p2a);
switch (mWhoMoves) {
case WHOMOVES_P1P2:
sDgmr->DrawFoldAndUnfoldArrow(p1a, p1b);
sDgmr->DrawFoldAndUnfoldArrow(p2a, p2b);
sDgmr->DrawArrow(p1a, p1b);
sDgmr->DrawArrow(p2a, p2b);
break;

case WHOMOVES_L1L2:
sDgmr->DrawFoldAndUnfoldArrow(p1b, p1a);
sDgmr->DrawFoldAndUnfoldArrow(p2b, p2a);
sDgmr->DrawArrow(p1b, p1a);
sDgmr->DrawArrow(p2b, p2a);
break;

case WHOMOVES_P1L2:
sDgmr->DrawFoldAndUnfoldArrow(p1a, p1b);
sDgmr->DrawFoldAndUnfoldArrow(p2b, p2a);
sDgmr->DrawArrow(p1a, p1b);
sDgmr->DrawArrow(p2b, p2a);
break;

case WHOMOVES_P2L1:
sDgmr->DrawFoldAndUnfoldArrow(p1b, p1a);
sDgmr->DrawFoldAndUnfoldArrow(p2a, p2b);
sDgmr->DrawArrow(p1b, p1a);
sDgmr->DrawArrow(p2a, p2b);
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/class/refLine/refLineP2P.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ void RefLine_P2P::DrawSelf(RefStyle rstyle, short ipass) const {
XYPt &p2 = rm2->p;
switch (mWhoMoves) {
case WHOMOVES_P1:
sDgmr->DrawFoldAndUnfoldArrow(p1, p2);
sDgmr->DrawArrow(p1, p2);
break;
case WHOMOVES_P2:
sDgmr->DrawFoldAndUnfoldArrow(p2, p1);
sDgmr->DrawArrow(p2, p1);
break;
}
}
Expand Down
Loading

0 comments on commit f378a7d

Please sign in to comment.