本帖最后由 sfzyr 于 2012-5-23 11:53 编辑
1.引子:
AutoCAD中,有很多这样的变量,一个变量其不同的变量值,代表着不同的意思,且多数是按位编码的,以"osmode"为例子,系统帮助文件解释如下:
OSMODE 系统变量
类型:整数
保存位置:注册表
初始值: 4133 使用下列位码设置“对象捕捉”的运行模式:
0 NON(无) 1 END(端点) 2 MID(中点) 4 CEN(圆心) 8 NOD(节点) 16 QUA(象限点) 32 INT(交点) 64 INS(插入点) 128 PER(垂足) 256 TAN(切点) 512 NEA(最近点) 1024 QUI(快速) 2048 APP(外观交点) 4096 EXT(尺寸线) 8192 PAR(平行)
要指定多个对象捕捉方式,请输入各个位码值之和。例如,输入 3 指定“端点”(位码 1) 和“中点”(位码 2) 对象捕捉。输入 16383 指定全部对象捕捉方式。
使用状态行的“对象捕捉”按钮关闭对象捕捉模式,除了返回 OSMODE 的普通值,还将返回位码 16384 (0x4000)。这个附加值有助于开发人员编写 AutoCAD 应用程序并将此模式与“绘图设置”对话框关闭的对象捕捉模式区别开来。设置此位码值将关闭对象捕捉。在该位码值关闭时将 OSMODE 设置为其他值可以打开对象捕捉。
如只打开“端点,中点” ,则osmode = 1 + 2 =3
(setq osm(getvar "osmode")) 得到"osmode"值,就知道了那几个捕捉开了,其实这种编码就好先开关,解释如下:
第n位 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| 二进制
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 对应的十进制
| 32768 | 16384此位码值将关闭对象捕捉 | 8192 PAR(平行) | 4096 EXT(尺寸线) | 2048 APP(外观交点) | 1024 QUI(快速) | 512 NEA(最近点) | 256 TAN(切点) | 128 PER(垂足) | 64 INS(插入点) | 32 INT(交点) | 16 QUA(象限点) | 8 NOD(节点) | 4 CEN(圆心) | 2 MID(中点) | 1 END(端点) | 0 NON(无) |
故:14位全开,十进制= (1+ 2 + 4 + …… + 4096 + 8192 )= 16383:输入 16383 指定全部对象捕捉方式
16384:关闭对象捕捉(绘图区按钮)
所以:(setq osm(getvar "osmode")) 得到"osmode"值,osmode = 16385,虽然端点打开,但是(16385 = 16384 + 1 ),而16384 绘图区 “ 对象捕捉按钮” 为关闭状态。
所以:判断某捕捉是否打开,并有效 ,判断某位置的“位码”是否为1 即可,用logand 函数
如 logand 2 (getvar "osmode") )=2 则中点开,且判断(logand 16384 (getvar “osmode”))是否= 16384即可
;;;;;=================================================================
2解码:
有人问:
通过(getvar "osmode")返回值确认某种捕捉方式已打开,
如返回值为11,如何通过程序知道这11由1+2+8组成
caoyin 版在http://bbs.mjtd.com/forum.php?mod=viewthread&tid=93694已经给了一种算法,我在给出另外几种算法,抛砖引玉。
 - ;; [功能] 按位编码分解
- ;; [参数] maxi----整型数。因子的最大范围
- ;; cost----整型数。要分解的值
- ;; [返回] 包含按位编码的整型数列表
- ;; [测试] (lt:factor 171)->(1 2 8 32 128)
- ;;;sfzyr,logand分解
- (defun sf:factor (cost / fact lst maxi)
- (setq maxi 1)
- (while (< maxi cost)
- (if (/= (setq fact (logand maxi cost)) 0)
- (setq lst (cons fact lst))
- )
- (setq maxi (* maxi 2))
- )
- (reverse lst)
- )
- ;;;sfzyr,rem分解:计算机基础中的十进制二进制转换算法,“除 2 取 余”
- (defun sf:factor2 (cost / fact lst maxi)
- (setq maxi 1)
- (while (> cost 0)
- (setq fact (* maxi (rem cost 2))
- cost (/ cost 2)
- maxi (* maxi 2)
- lst (vl-remove 0 (cons fact lst))
- )
- )
- (reverse lst)
- )
3:其实位码拆分,就是“十进制”转“二进制” 的过程,有下面的计算机基础,你就可以编写出很多这个问题的解法了
二进制的1101转化成十进制
1101(2)=1*2^0+0*2^1+1*2^2+1*2^3=1+0+4+8=13
转化成十进制要从右到左用二进制的每个数去乘以2的相应次方
不过次方要从0开始
相反 用十进制的数除以2 每除一下将余数就记在旁边
最后按余数从下向上排列就可得到1101
十进制转二进制:
用2辗转相除至结果为1
将余数和最后的1从下向上倒序写 就是结果
例如302
302/2 = 151 余0
151/2 = 75 余1
75/2 = 37 余1
37/2 = 18 余1
18/2 = 9 余0
9/2 = 4 余1
4/2 = 2 余0
2/2 = 1 余0
1/2 = 0 余1
故二进制为100101110
以上,希望对logand 函数的用法更加清楚,对 一个系统变量,对应多个值 ,表示不同状态有所理解。
同时,自己也可以创建这样的变量,编码实现不同值对应不同状态。
抛砖引玉,高手不要拍砖。 
|