From 21da23ffe6cd066640fa04513bc41f45c8e2b577 Mon Sep 17 00:00:00 2001 From: wind1900 Date: Sun, 12 Jan 2025 21:37:16 +0800 Subject: [PATCH] [23_27] Fix bugs when drawing semicircle ## What Fix 2 little bugs. 1. Can not draw the correct semicircle in current environment. 2. There will be "division by zero" exception in console when you're choosing the third point and move mouse to center point (the first point). ## Why When drawing an arc, we first select the circle center `c`, then the start point `p` and end point `x` on the arc. It will use these points to calculate a third point `m` on arc, and use `p`, `m`, `x` to draw the arc. By default it's counterclockwise though it's called "Std-arc". When we want to draw a semicircle, the angle between `vec-c-p` and `vec-c-q` is 180. In the previous code, it uses `vec-c-p` as the third point `m` incorrectly. We should still consider it's clockwise or counterclockwise here and then add the correct vector to the center point as the third point. Before: image Fixed: image The distance of `c` and `q` as `r1` is used to avoid the exception message in console, like ``` ;/: division by zero, (/ 0.0 0.0) ; (let ((n (length opts))) (cond ((= n... ; D:\mogan\build\packages\app.mogan\data\progs\kernel\library\base.scm, line 270, position: 0 ; (let ((n (length opts))) (cond ((= n 0) (... ; f: 0.0 ; (f2s (/ (point-get-x pt) f)) ; pt: (point "0.0" "0.0") ; (list-values 'point (f2s (/ (point-get-x ... ; std-arc-helper: (equal? (point-get-unit v... ; vec-c-p: (point "2.0" "0.0") ; vec-c-q: (point "0.0" "0.0") ``` ## How to test your changes? Add a unit test so I can test it by `xmake run 23_27` --- TeXmacs/progs/graphics/graphics-markup.scm | 18 +++-- TeXmacs/tests/23_27.scm | 78 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 TeXmacs/tests/23_27.scm diff --git a/TeXmacs/progs/graphics/graphics-markup.scm b/TeXmacs/progs/graphics/graphics-markup.scm index e8f2645d9b..b004b16877 100644 --- a/TeXmacs/progs/graphics/graphics-markup.scm +++ b/TeXmacs/progs/graphics/graphics-markup.scm @@ -87,28 +87,32 @@ (p (if (tm-point? P) (tree->stree P) c)) (q (if (tm-point? Q) (tree->stree Q) p)) (r (points-distance c p)) - (x (if (equal? r 0.0) + (r1 (points-distance c q)) + (x (if (zero? r) c - (points-add (point-times (point-get-unit (points-sub q c)) r) c))) + (if (zero? r1) + p + (points-add (point-times (point-get-unit (points-sub q c)) r) c)))) (mid-p-x (points-mid p x)) (vec-c-p (points-sub p c)) (vec-c-q (points-sub q c)) - (m (if (equal? r 0.0) - c + (m (if (or (zero? r) (zero? r1)) + x (if (clockwise (points-cross-product-k vec-c-p vec-c-q) 0) (points-add (point-times (point-get-unit (points-sub mid-p-x c)) (- r)) c) (if (= (points-cross-product-k vec-c-p vec-c-q) 0) ;; If cross product == 0, then the angle between vec-c-p and vec-c-q is 0 or 180. ;; We should find out whether it's 0 or 180. + ;; And we should determine whether it's clockwise or counterclockwise. (if (equal? (point-get-unit vec-c-p) (point-get-unit vec-c-q)) x - (point-rotate-90 (point-rotate-90 (point-rotate-90 vec-c-p)))) + (if (eq? clockwise >) + (points-add (point-rotate-90 (point-rotate-90 (point-rotate-90 vec-c-p))) c) + (points-add (point-rotate-90 vec-c-p) c))) (points-add (point-times (point-get-unit (points-sub mid-p-x c)) r) c)))))) `(arc ,p ,m ,x))) - - (define-graphics (std-arc C P Q) (std-arc-helper C P Q >)) diff --git a/TeXmacs/tests/23_27.scm b/TeXmacs/tests/23_27.scm new file mode 100644 index 0000000000..4a22da8a87 --- /dev/null +++ b/TeXmacs/tests/23_27.scm @@ -0,0 +1,78 @@ +(import (liii check) + (liii os)) + +; Because std-arc-helper is using define, it is not using tm-define +; We have to load the module directly +; +; (texmacs-module (tests 23_27) +; (:use (graphics graphics-markup))) +(load (string-append (getenv "TEXMACS_PATH") "/progs/graphics/graphics-markup.scm")) + +(define (point x y) + (stree->tree `(point ,x ,y))) + +(define (test-std-arc-helper) + ;c==p==q + (check (std-arc-helper (point "0" "0") (point "0" "0") (point "0" "0") #f) + => `(arc (point "0" "0") + (point "0" "0") + (point "0" "0"))) + ;c==p + (check (std-arc-helper (point "0" "0") (point "0" "0") (point "1" "1") #f) + => `(arc (point "0" "0") + (point "0" "0") + (point "0" "0"))) + ;c==q + (check (std-arc-helper (point "0" "0") (point "1" "1") (point "0" "0") #f) + => `(arc (point "1" "1") + (point "1" "1") + (point "1" "1"))) + ;p==q + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "1" "0") >) + => `(arc (point "1" "0") + (point "1.0" "0.0") + (point "1.0" "0.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "1" "0") <) + => `(arc (point "1" "0") + (point "1.0" "0.0") + (point "1.0" "0.0"))) + ;cross-product==0, angle is 0 degree + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "2" "0") >) + => `(arc (point "1" "0") + (point "1.0" "0.0") + (point "1.0" "0.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "2" "0") <) + => `(arc (point "1" "0") + (point "1.0" "0.0") + (point "1.0" "0.0"))) + ;cross-product==0, angle is 180 degree + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "-2" "0") >) + => `(arc (point "1" "0") + (point "0.0" "-1.0") + (point "-1.0" "0.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "-2" "0") <) + => `(arc (point "1" "0") + (point "0.0" "1.0") + (point "-1.0" "0.0"))) + ;cross-product!=0 + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "0" "1") >) + => `(arc (point "1" "0") + (point "-0.7071067811865475" "-0.7071067811865475") + (point "0.0" "1.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "0" "-1") >) + => `(arc (point "1" "0") + (point "0.7071067811865475" "-0.7071067811865475") + (point "0.0" "-1.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "0" "1") <) + => `(arc (point "1" "0") + (point "0.7071067811865475" "0.7071067811865475") + (point "0.0" "1.0"))) + (check (std-arc-helper (point "0" "0") (point "1" "0") (point "0" "-1") <) + => `(arc (point "1" "0") + (point "-0.7071067811865475" "0.7071067811865475") + (point "0.0" "-1.0")))) + +(define (test_23_27) + (test-std-arc-helper) + (check-report) + (if (check-failed?) (exit -1))) \ No newline at end of file