網頁版幾何畫板開發筆記(十七) 加強版本的做圖檢測

過去實現的做圖檢測有了新的發展的需求, 所以須要對此功能進行加強/升級. 主要的加強是提供了
簡單表達式計算(含簡單對象字段獲取,變量), 擴展/增長了判斷函數, 自定義判斷提示信息幾個方面. javascript

變量和表達式 java

須要進行一些簡單計算的場合, 所以判斷腳本須要支持變量和簡單表達式. 瀏覽器

變量一般是以$開頭的標識符, 標識符中可以使用 字母,數字和下劃線. 例如 $a, $x, $1, $long_name 等.
使用 $ 開頭是爲了不和幾何對象的標記相混淆和衝突, 如幾何中點一般標記爲大寫字母, 線,圓
標記爲小寫字母, 角有時候標記爲數字. dom

簡單表達式計算中支持 +, -, *, / (加減乘除), 比較. 下面簡單列出, 設 $a, $b 是兩個量:
   $a + $b : 求兩個量的和, 數字能夠相加, 兩個字符串也能夠加.
   $a - $b: 減.
   $a * $b: 乘.
   $a / $b: 除.
   $a % $b: 求模, 通常此計算對整數纔有意義.
   $a == $b:  相等比較. 因爲 js 中使用浮點數, 浮點數計算後一般不能保證必定精確相等.
   $a ~= $b:  近似相等, 二者的差的絕對值小於 0.000001 (EPSILON) 就認爲是近似相等.
   $a != $b:  不相等.
   $a < $b:  比較 a 小於 b.
   $a > $b:  比較 a 大於 b.
   $a <= $b: 小於等於.
   $a >= $b: 大於等於.
   $a & $b:  邏輯與(and), 兩值都爲真才爲真.
   $a | $b: 邏輯或(or), a,b有任何一值爲真結果即爲真. ide

還支持用 . (句點) 訪問對象的簡單屬性, 例如設 $a 得到一個點對象時:
   $a = point(A);
   $a.x, $a.y 獲得該點的 x,y 座標. 它們可用於計算中, 如:
   $r = sqrt($a.x * $a.x + $a.y * $a.y);
不一樣的對象有不一樣的屬性. 在下面得到對象的地方有簡單說明. 函數

 

函數調用 工具

在新的檢測腳本中提供了不少檢測,獲取值,計算的函數, 調用方式是:
   funame(arg1, arg2, ...); oop

有些(大部分)函數有返回值, 如:
   $p = point(P);  --- 獲得點 P 的對象. spa

函數也能被嵌套調用:
   $val = px2cm(dist(A,B)) + sin(log(x)); 設計

在每一個表達式後面, 分號的前面, 可使用錯誤信息子句, 最經常使用的地方是函數調用以後:
   $m = line(m) error '獲取線 m 時發生某種錯誤';
錯誤信息子句被設計用來提供自定義的錯誤信息, 根據題意, 教師選擇合適的錯誤信息, 可以給學生
更恰當的指導.

錯誤信息子句可以使用多種錯誤類型, 如:
   $x = point(X)  unlabel '沒有找到標記爲 X 的點'
                         unexist '點 X 不存在'
                         invisible '點 X 不可見'
                         errtype '有標記爲 X 的對象, 但不是點'
                         multi  '有多個點被標記爲 X, 因此指代不明確.'
                         error '錯誤總類' ;

注意表達式最後必定要有 ';' 分號結束. 如今程序須要有這個分號作爲表達式結束標誌.

錯誤子句其實是加在表達式最後的, 因此下面寫也是能夠的:
   $not_care = line(m) & point(B) & point(C) & line(n) error '錯誤子句' ;
這個表達式一次檢測了線 m, 點 B,C, 線 n, 並使用最後的錯誤子句報告錯誤信息.

抑制錯誤報告: 有時候調用某個函數只爲判斷點,線,圓等對象是否存在, 而不是報告錯誤(而後終止了),
   此時可使用 @func(...) 形式來調用函數, 即在函數調用前面加上 @ 符號, 該符號的做用是
   抑制錯誤報告和終止, 若是有錯誤仍然返回, 但返回的對象爲 null 或 斷定返回 false(假).

例子: $x = @point(X);  --- 假設沒有點 X (或別的錯誤狀況), 則該調用返回 $x 爲 null.
   實際錯誤信息保存在變量 $check_result 中, 錯誤數量保存在變量 $error_count 中.
例如: print($x) 打印爲 null, print($check_result) 打印爲 '請標記出點 X.'
   若是自定義了 error/false 子句, 則該錯誤信息是自定義的子句值.

 

輔助函數

print (a, b, ...);   --- 在瀏覽器 console (調試控制檯)打印出參數, 參數數量不限制. 一般用於調試.
judge(cond) false '錯誤信息';  ---  給出一個條件值 cond, 若是爲假則輸出後面的錯誤信息, 並終止程序.

判斷函數

保留了一些和前一版本兼容(有少許改動會標記出來)的判斷函數, 並增長了一些新的判斷函數. 判斷函數比較容易增長.
有的函數有兩種(或更多)形式, 程序是根據參數數量判斷的, 所以請確保參數數量是對的.

下面的斷定函數, 參數爲大寫字母的大多表示一個點, 小寫字母通常表示是數字或對象, $開頭的通常表示變量.

print(arg1, arg2, ...) 在瀏覽器 console 上輸出 arg1, arg2,... 的信息, 這裏參數數量不限.
這個函數通常用於調試輸出一些信息, 幫助查看相應信息. 下面的示例中就經常使用到.
 point(A)
point(A,B,C, ...)

斷定和獲得點 A 對象. 形式2 point(A,B,C ...) 可一次判斷多個點, 但只返回最後一個點對象.
例子:
   $a = point(A);    --- 獲得點 A.
   print ($a.x, $a.y);  ---  輸出點 A 的座標 (x,y) 於瀏覽器 console.
   $a.name --- 此點的名字, 這個例子中爲 'A'. 注意: 有些點可能(學生)沒有標記名字.
   $a.type --- 對象類型, 對於點老是 'point'
   $a.sub_type --- 點的子類型, 當前主要有 'freept' (自由點), 'midpt' (中點), 'oopt' (線或圓上的點), ...
   $a.exist --- 點是否存在, 在數學意義上. 如兩線段交點, 線段不交的時候, 則原來構造的交點對象有, 但其
        exist 爲 false.
   $a = point(A) unlabel '沒有標記爲 A 的點.'      --- 畫板中沒有找到標記爲 A 的點.
                       errtype '有標記爲 A 的別的對象, 但不是點.'
                       multi    '有多個點被標記爲 A, 指代不明確.'
                       invisible '點 A 被隱藏, 而不可見.'
                       unexist  '點 A 不存在.'
                       error   '發生上述某種錯誤.' ;

在對象斷定和獲取函數的後面可使用 unlabel, errtype, multi, invisible, unexist 等錯誤信息自定義子句, 給出學生更準確的錯誤信息.

vpoint(x, y, name) 建立一個虛的點, 其座標爲 (x,y), 這個點可參與各類斷定函數的計算, 但不對應到畫板中的點 (也許畫板中該位置的確有一個點, 但不和這個對象關聯).
可選給出一個名字 name. 可幫助輸出信息的時候使用. 例子:
   --- 假設 $a 是另外一個點.
   $x = vpoint($a.y, $b.x);   ---- 點 $x 位置等因而 $a 點的 y=x 線的對稱點.
   dist($a, $x);  --- 計算兩個點的距離.
   $y = vpoint(100, 40, 'Y');  --- 虛擬點 Y, 位置在 (100,40)
line(A, B)
line(m)
any_line(A,B)

形式1 判斷並獲得過點 A,B 的線對象(含各類線, 如 seg線段, ray射線, sline直線, paral 平行線, perpl 垂線, bisl 角平分線)
形式2 判斷並獲得標記爲 m 的線.  any_line() 是 line() 的過去的名字, 爲兼容過去的腳本而保留.
  $m = line(m)  unlabel '未標記' 
              errtype '類型不對' 
              multi '多線同名' 
              invisible '不可見

              unexist '不存在'
              error '上述各類錯誤總類';

  可用的錯誤子句同 point() 函數.

線對象保證能夠得到構成此線的兩個點 p1 ,p2, 如:
   print ($m.p1, $m.p2);
要注意的是 部分線類型構成該線的點 p1 或和 p2 只有 (x,y) 座標位置(如構造的平行線), p1,p2不是真正的點對象.

seg(A,B)
seg(m)
相似於 line() 函數, 限定線的類型是 'seg', 即線段. 
ray(A, B)
ray(m)
相似於 line() 函數, 限定線的類型是 'ray','bisl', 即射線. 這裏構造的角平分線(bisl)也被認爲是一種射線.
sline(A, B)
sline(m)
相似於 line() 函數, 限定線的類型是 'sline','paral','perpl' 即直線. 這裏構造的平行線(paral)和垂線(perpl) 也被認爲是一種直線.
paral(A, B)
paral(m)
相似於 line() 函數, 限定線的類型是 'paral', 即構造時爲平行線.
perpl(A, B)
perpl(m)
相似於 line() 函數, 限定線的類型是 'perpl', 即構造時爲垂線.
bisl(A,B)
bisl(m)
相似於 line() 函數, 限定線的類型是 'bisl', 即在構造時爲角平分線.
circ(c)
circ(O, A)
circ(A,B,C)

形式1 判斷並獲得標記爲 c 的圓對象. 若是標記爲 c 的圓沒有, 則嘗試將 c 當作是一個點, 並判斷是否有以該點爲圓心的圓.
形式2 判斷並獲得圓心爲 O, 圓上有一點 A 的圓對象.
形式3 判斷並獲得一個圓對象, 此圓過三點 A,B,C.
例子:
   $c = circ(c);   --- 找標記爲 c 的圓, 或圓心爲 c 的圓.
   $c = circ(O);   --- 設O 爲點, 則找圓心爲 O 的圓.
   $c = circ(O, A);   --- 找圓心爲 O, 圓上一點爲 A 的圓.

在 circ(c) 後面可以使用 unlabel, unexist, invisible, multi 等子句自定義錯誤提示信息.
每一個圓對象必定有圓心點, 爲 $c.op, 其中過三點圓可能圓心是一個只有 (x,y) 座標的假點.
每一個圓對象必定有半徑屬性, 如 print ($c.r), 單位是像素.

 

判斷 △ABC≌△PQR. 三角形全等.
 coll(A,B,C)  判斷點A,B,C 是否共線.
 not_coll(A,B,C)  判斷點A,B,C 不共線, 也即這三個點可構成三角形.

para(A,B,C,D)
para(m, n)

形式1判斷AB 是否平行(∥)於CD, 其中A,B,C,D 都是點, 不要求有任何線.
形式2判斷線 m,n 是否平行.  
例子:
   $m = line(A, B);   --- 獲得過點 A,B 的線, 注意也含斷定.
   $n = line(n
);    --- 獲得標記爲 n 的線. 
   para($m, $n) false 'AB 不平行線 n';   --- 進行斷定.

perp(A,B,C,D)
perp(m, n)
形式1 判斷 AB 是否垂直(⊥)於CD.
形式2判斷線 m,n 是否垂直.
intpt_ll(X,A,B,C,D)
intpt_ll(X, m, n)
形式1 判斷點 X 是否在 AB, CD 兩線的交點位置.
形式2 判斷點 X 是否在 m, n 兩線的交點位置.
實際實現上來講, 若是 X,A,B 共線, 且X,C,D 共線, 則X 是 AB,CD 的交點.
cycl(A,B,C,D) 判斷 A,B,C,D 四點共圓.
eqdist(A,B,C,D) 判斷距離 AB=CD.
如今還能夠寫爲:
  $ab = dist(A,B);       --- 求 A,B 間距離.
  $cd = dist(C,D);       --- 求 C,D 間距離.
  judge ($ab == $cd);   --- 判斷兩值相等, 因爲浮點計算有自然的細小的偏差, 這個斷定幾乎不會成立.
  judge ($ab ~= $cd);   --- 兩個值近似相等, 程序中近似指兩值差絕對值小於 0.000001
  judge (abs($ab - $cd) < 0.001);   --- 判斷近似相等, 差小於 0.001, 比上面的比較寬鬆一些.
eqang(A,B,C, P,Q,R) 判斷∠ABC=∠PQR. 角相等.
如今也能夠寫做:
  $b = angle(A,B,C);   --- 獲得∠ABC 的值, 單位是弧度.
  $q = angle(P,Q,R);   --- 獲得∠PQR 的值, 單位是弧度.
  judge ($b ~= $q);    --- 判斷兩值近似相等.
con_tri(A,B,C, P,Q,R)
sim_tri(A,B,C, P,Q,R) 判斷 △ABC∽△PQR. 三角形類似.
equ_tri(A,B,C) 判斷 △ABC 是等邊三角形.
ang_is(A,B,C, degree) 判斷 ∠ABC=指定度數 degree. (如 90°, 注意這裏單位不是弧度)
可使用rad2d(x) 函數轉換弧度爲角度.
angle_v(A,B,C) 獲得∠ABC 的值, 該值爲弧度.
可使用 rad2d(x) 函數轉換弧度爲角度.
angle(A,B,C) 判斷存在角 ∠ABC, 其中 B 是頂點, BA,BC 是兩條邊(即存在任意的線在 BA,BC)
tri(A,B,C, opt) 判斷 A,B,C 是一個三角形. 若是 opt 給出爲字符串 'seg', 則要求 AB,BC,CA 之間有線段.
若是 opt 爲字符串 'line', 則AB,BC,CA 之間只要有任何種類的線便可. opt 不給出則不限制是否有線段.
也即此判斷函數可調用爲 tri(A,B,C) --- 不用給出 opt 參數. 
acute_tri(A,B,C, opt) 判斷 A,B,C 是一個銳角三角形. 選項參數 opt 含義同 tri() 斷定函數.
right_tri(A,B,C, opt) 判斷 A,B,C 是一個直角三角形, 其中角 A 是直角. 選項參數 opt 含義同 tri() 斷定函數.
obtuse_tri(A,B,C,opt) 判斷 A,B,C 是一個鈍角三角形. 選項參數 opt 含義同 tri() 斷定函數.
amark(A,O,B)
amark(n)
形式1 判斷∠AOB 有一個標記, 並返回該角標記對象.
形式2 判斷有一個標記爲 n 的角標記, 並返回該角標記對象.
調用示例(假設已經畫了一個角ABC, 並標記爲 1):
$1 = amark('1');  --- 獲得該角標記, 此對象在畫板中是一個 AngleMark 類的實例.
print ($1);   --- 在瀏覽器的 console 中打印出這個角標記對象.
print ($1.value, $1.value_d);   --- 輸出這個角的弧度值, 度數(°)值.
print ($1.style);  --- 這個標記樣式, 值爲1,2,3,4, 分別表示標記是1-4個弧線.
lmark(A,B) 判斷線段A,B 之間有線標記, 並返回線標記對象, 在畫板中是一個 LineMark 類的實例.
todo: 實現形式2: lmark(name), 根據名字獲得線標記.
$1 = lmark(A,B);
print($1.style);  --- 標記樣式, 取值1-4 表示由幾個小線段構成.
mk_ss(m1, m2) 判斷標記對象 $m1, $m2 有相同的樣式, 也即 $m1.style == $m2.style.
ratio(A,B,C,D, E,F,G,H) 判斷 AB:CD = EF:GH, 即線段構成比例.
如今也能夠用 dist(A,B)/dist(CD) 和 dist(E,F)/dist(G,H) 計算出其比例, 而後用 judge(b) 進行判斷.
ratio_2(A,B,C,D,n1,n2) 判斷 AB:CD=n1:n2 線段構成比例, 其中 n1,n2 是數字.
如今能夠本身計算長度和比例, 如 dist(A,B)/dist(C,D).
intpt(X)

斷定點 X 是被構造爲交點的類型(點對象的 sub_type == 'intpt'), 並返回該點.
如今能夠寫爲:
  $x = point(X);
  judge($x.sub_type == 'intpt') false '請構造兩線的交點X.';

 

 is_square(A,B,C,D,opt) 判斷A,B,C,D 構成正方形. 選項 opt 取值可爲 'seg', 'line', 含義同 tri() 函數中的 opt 參數.
 is_rect(A,B,C,D,opt) 判斷A,B,C,D 構成矩形(長方形). opt 參數同上. 正方形也是矩形. 
 is_diam(A,B,C,D,opt) 判斷A,B,C,D 構成菱形. opt 參數同上. 正方形也是菱形. 
is_paralg(A,B,C,D,opt) 判斷A,B,C,D 構成平行四邊形. 正方形, 長方形, 菱形也是(特殊)平行四邊形.
is_trapz(A,B,C,D,opt) 判斷 A,B,C,D 構成梯形, 其中 AB//CD, 梯形兩腰不平行.
quad(A,B,C,D,opt) 判斷存在任意 A,B,C,D 構成的四邊形. opt 參數同上.
at_ray(A, B, C) 判斷點 A 在射線 B->C 上.
at_seg(A, B, C) 判斷點 A 在線段 B, C 上(在線段以內).
pt_at(x, y) 已知座標 x,y, 找到差別在 EPSILON 以內的點對象, 若是沒有找到則返回 null.
is_refl(A, B, m) 判斷點 A,B 是否關於直線 m 對稱.
ln_intp(m, n) 計算兩線 m, n 的交點位置. 若是線是線段或射線, 則交點在線段內或射線上纔算交點.
返回爲一個 vpoint.
cc_intp(c1, c2, which) 計算兩個圓的交點. which 若是爲 1 則返回第一個交點, 爲 2 則返回第二個交點; 不然同時返回兩個交點.
lc_intp(ln, cr, which) 計算線 ln 和圓 cr 的交點. which 含義同上.
cr_rel(cr1, cr2) 計算兩個圓 cr1, cr2 的關係.
返回 0:圓不存在; 1:兩圓相外離; 2:外切; 3:相交; 4:內切; 5:cr1含cr2; 6:cr2含cr1.
cr_devi(cr1, cr2) 判斷圓 cr1, cr2 外離. 即 cr_rel(cr1, cr2) == 1
cr_xtang(cr1, cr2) 是否兩圓外切.
cr_itang(cr1, cr2) 是否兩圓內切.
cr_intp(cr1, cr2) 判斷圓 cr1,cr2 相交.
cr_inc(cr1, cr2) 判斷圓 cr1 內含於 cr2.
xpoly(opt, A, B, C, ...) 判斷 A,B,C,D ... 多個點(數量可任意指定) 可構成多邊形, 注意:至少要給出四個點.
opt 是 'seg', 'line', 'convex' 的任意組合, 或沒有.
選項 'seg' 表示要求判斷多邊形各邊必須有線段鏈接, 如 AB, BC, CD, DA 線段.
   'line' 表示要求判斷各邊必須有線(任意線)鏈接.
   'convex' 表示判斷是不是 凸多邊形.
例子: xpoly('seg,convex', A,B,C,D,E);  --- 判斷存在凸五邊形ABCDE, 且各邊有線段.

 

數學函數

abs,acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random, round, sin, sqrt, tan.

這些數學函數是直接引用 javascript Math 對象中的相應數學函數.
另在程序中可以使用 _PI, _E 兩個常量, 爲避免和幾何圖中 PI,E 名字衝突, 前面加了 _ 下劃線符號.

 

單位轉換

px2cm(x) --- 像素轉爲釐米.
cm2px(x) --- 釐米轉爲像素.
rad2d(x)  --- 弧度轉爲度數, 弧度值 π 對應 180°.
d2rad(x)  --- 度數轉爲弧度.

判斷點線的顏色等:

對於點, 如 $a =point(A); print($a); --- 獲得一個點, 打印該點對象. 咱們能夠訪問點對象的信息有:

1. 點的座標: $a.x, $a.y  --- 點的像素座標, 像素座標系以畫板的左上角爲 (0,0), X軸向右, Y軸向下.
   (注意Y軸向下是與通常座標系的區別)

2. 點的顏色: $a.color --- 例如紅色的值爲 'red' 或 '#ff0000'.
   judge($a.color == 'red' | $a.color == '#ff0000') false '請將點 A 設置爲紅色';

3. 點的大小: $a.point_size  --- 標準點大小該值爲 3.5, 小的點該值爲 2.5, 最小的點爲 1.2, 大點爲 5.

對於線, 如 $m = line(A,B); print($m);  --- 獲得一條線, 打印該線對象. 則有:

1. 肯定該線的兩個點: $m.p1, $m.p2, 這種點有時候只有 x,y 的值, 不保證必定是用戶畫出的點, 多是程序
   計算出的繪製該線的兩個點.

2. 線型: $m.line_style , 取值 0 爲實線, 1 爲點劃線, 2 爲點線.

3. 線寬: $m.line_width, 取值 2 爲標準線寬(中細), 取值 0.3 爲極細, 0.8 爲細線, 4 爲粗線.

4. 線顏色: $m.color , 含義同點的顏色.

對於圓, 如 $c = circ(O, A); print($c); 

1. $c.op 爲圓心點, $c.r 爲圓的半徑.   $c.rp 爲圓上一點(不保證必定有)

2. $c.line_width 線寬, 含義同線的說明. $c.line_style 線型, 對圓不支持.

3. $c.color 圓的顏色, 含義同點的顏色.

 =========================================================

新的斷定函數 (2015-05-15)

 vpoly(A,B,C ...) 根據所給的任意點數量建立一個虛擬的多邊形, 此多邊形可用於各類計算. 至少要給出三個點.
 in_poly(A, $poly)

斷定點 A 是否在多邊形 $poly 內部, 返回 true 在內部, 返回 false 在外部.

 ln_xk(l)  用於獲得(任意)線ln 與 x 軸之間的夾角 a, 並規範到銳角範圍內, 取值爲度數, 即值爲 [0, 90] 之間. 若是是 0°表示與 x 軸平行, 90°表示與 x 軸垂直.
tri_centroid(A,B,C), 給出三角形的三個點 A,B,C, 返回一個虛擬的點, 其座標爲 A,B,C 的重心.
tri_orthocentre(A, B, C) 求三角形垂心.
tri_circumcentre(A, B, C) 求三角形外心.
tri_incentre(A, B, C) 求三角形心裏.
foot(x, y, ln) 求取點 A(x,y) 到任意的線 ln 的垂足, 返回爲一個虛擬點.
ang_r2(a1, a2) 函數 ang_r2(a1, a2) 用於斷定兩個角 ∠a1, ∠a2 的位置關係.
返回 1,  表示等角關係(角相等, 邊所在射線相同)
返回 2,  表示互補角關係. 一樣對 (1,4) (2,3) (3,4) 也是互補關係.
返回 3,  表示對頂角關係. 一樣對 (2,4) 也是對頂角關係.
返回 -1 表示所給對象不正確, 其它負值表示其它錯誤.
ang_rel(l1, l2, l3, a1, a2)

斷定由線 l3 截l1,l2 構成的兩個角a1,a2 的位置關係.
返回 1, 表示是同旁內角.
返回 2, 表示是內錯角.
返回 3 表示是同位角.
返回 4 表示是 (沒名字), 一個在內,一個在外,且異側.
返回 5 是同旁外角.
返回 6 是異旁外角.
返回負值表示沒法斷定, 通常是所給對象不對.

sm_side(A, B, l)  斷定點 A,B 是否在直線 l 的同側或異側.
返回: 1 表示在同側, -1 表示在異側; 返回 0 表示沒法斷定(點不存在, 或在線 l 上)
refl_pt(A, l) 計算點 A 以直線 l 爲鏡面的反射點(對稱點)
返回爲一個虛擬點. 若是參數有錯, 則返回 null (空).
is_sel(A, B, C ...) 判斷幾何對象 A,B,C ... 等是否被選中了. 參數數量任意.
sel_tool(tool_name)

斷定當前選擇的工具是 tool_name.
其中工具名字分別爲 'select' (選擇工具,箭頭), 'point'(點工具), 'circle'(圓工具), 'segment'(線段工具),
   'ray'(射線工具), 'line'(直線工具), 'any_line'(前三種線工具統稱), 'mark'(標記工具), 'text'(文本工具).
可能之後還會添加別的工具, 如 polygon,macro 等.

obj_num(obj_type) 獲得指定對象類型爲 obj_type 的對象數量. 如 obj_num('point') 獲得點的數量. obj_num('segment') 獲得線段數量. obj_num('line') 獲得任意線的數量. obj_num() 獲得全部對象數量.
相關文章
相關標籤/搜索