过去实现的作图检测有了新的发展的需求, 因此需要对此功能进行增强/升级. 主要的增强是提供了
简单表达式计算(含简单对象字段获取,变量), 扩展/增加了判断函数, 自定义判断提示信息几个方面.变量和表达式
需要进行一些简单计算的场合, 因此判断脚本需要支持变量和简单表达式.
变量通常是以$开头的标识符, 标识符中可使用 字母,数字和下划线. 例如 $a, $x, $1, $long_name 等.
使用 $ 开头是为了避免和几何对象的标记相混淆和冲突, 如几何中点通常标记为大写字母, 线,圆 标记为小写字母, 角有时候标记为数字.简单表达式计算中支持 +, -, *, / (加减乘除), 比较. 下面简单列出, 设 $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有任何一值为真结果即为真.还支持用 . (句点) 访问对象的简单属性, 例如设 $a 获得一个点对象时:
$a = point(A); $a.x, $a.y 得到该点的 x,y 坐标. 它们可用于计算中, 如: $r = sqrt($a.x * $a.x + $a.y * $a.y); 不同的对象有不同的属性. 在下面获得对象的地方有简单说明.
函数调用
在新的检测脚本中提供了很多检测,获取值,计算的函数, 调用方式是:
funame(arg1, arg2, ...);有些(大部分)函数有返回值, 如:
$p = point(P); --- 得到点 P 的对象.函数也能被嵌套调用:
$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() 得到所有对象数量. |