计时器是个很常见的功能。比如,生成1幅图用了多少时间,和手动相比为用户节约了多少时间,提高了多少效率。 又如,两种不同的程序实现方式,用时有多少差异。

不过,autocad并没有直接给出计时器接口,需要我们自己动手写。作为一门函数式编程的编程语言,无法写出计时器对象, 只能通过若干个函数,组合使用来实现计时的功能。

计时器功能分析

这里,咱们只考虑最基础的功能,也就是从某一时刻到另一时刻,用了多少时间。 那么,就需要2个代表时间点的值,有了这2个值,求二者的差值,就实现了预定功能。

获取代表某一时间点的值

从我之前写的《3个和时间有关的autocad系统变量》,可以看出来, 获取时间点的值用millisecs值是最合适的。

所以,咱们就用millisecs值,使用(getvar "millisecs")就获得了当前的时间值。一段时间之间,再次(getvar "millisecs"), 就获得了第2个时间值。

计时器函数代码

根据前文分析可知,计时器函数(主函数)通过计算2个时间值的差值来返回时长,后一个时间值可以在函数内部 通过(getvar "millisecs")获得,所以,有了前一个时间值这个输入参数,就能实现预定功能了。

这个函数可以写成下面这样:

1
2
(defun xg/timer (start-time) 
  (* 0.001 (- (getvar "millisecs") start-time)))

只要输入参数start-timemillisecs的返回值,调用这个函数,它就能给出准确的时长。 万一输入参数弄错了,不是millisecs的返回值,而是其他值,比如cdate的返回值,它给出的结果就有问题了。

针对这种情况,我们有必要改进一下现有的函数及其使用方式,杜绝上述的问题。我们将获取时间值的方式改进一下, 封装为一个函数,再通过调用这个函数来获取时间值,不再直接使用(getvar "millisecs")语句获取时间值。

为了符合大多数人的习惯,把这个函数命名为timer-start,写出来就是下面这样:

1
2
(defun xg/timer-start () 
  (getvar "millisecs"))

然后,把xg/timer改写成下面这样:

1
2
(defun xg/timer (start-time) 
  (* 0.001 (- (xg/timer-start) start-time)))

不过,现在的xg/timer代码依然存在问题,就是在函数内部调用了xg/timer-start, timer-start这个函数名会给以后的代码维护人员带来困扰。另外,原本求差值的简单运算, 引入了乘以0.001的特殊逻辑,以后换用其他的获取时间值的方式时,还要重构这一部分代码, 所以,有必要剔除掉乘以0.001的特殊逻辑,回归其本原。

故此,再写一个新函数,专门用来获取时间值,可以写成下面这样:

1
2
(defun xg/timer-record () 
  (* 0.001 (getvar "millisecs")))

然后,把xg/timer-start改写成下面这样:

1
2
(defun xg/timer-start () 
  (xg/timer-record))

最后,把xg/timer改写成下面这样:

1
2
(defun xg/timer (start-time) 
  (- (xg/timer-record) start-time))

至此,就使用autolisp完整实现了最基础的计时器了,并且,咱们的代码还实现了模块化, 假如未来某一天,autodesk修改了millisecs的返回值,我们需要修改计时器代码时, 就只需要修改xg/timer-record的代码即可。

最终版autolisp计时器完整源代码

本文的计时器实现的完整源代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
(defun xg/timer-record () 
  ;; autolisp计时器辅助函数1
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  ;; 返回时间值,供其计时器他函数调用。
  (* 0.001 (getvar "millisecs")))

(defun xg/timer-start () 
  ;; autolisp计时器辅助函数2
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  ;; 启动计时器,返回时间值。
  (xg/timer-record))

(defun xg/timer (start-time) 
  ;; autolisp计时器主函数
  ;; 作者:徐工, 微博:@徐工徐工2020,头条:@徐工徐工
  ;; 返回自start-time到当前时刻的时长。
  (- (xg/timer-record) start-time))