理解按位编码的好处,及编码后如何拆分因子,理解系统变量决定的状态(源码)
本帖最后由 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位16151413121110987654321
二进制
1111111111111111
对应的十进制
3276816384此位码值将关闭对象捕捉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 函数的用法更加清楚,对 一个系统变量,对应多个值 ,表示不同状态有所理解。
同时,自己也可以创建这样的变量,编码实现不同值对应不同状态。
抛砖引玉,高手不要拍砖。
补充下:
5楼logand、logor的用法举例
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=56976 谢谢,学习了。 谢谢楼主 希望更多的高手来抛一抛 最后集成一块玉 本帖最后由 sfzyr 于 2012-5-23 16:05 编辑
秋枫 在这个帖子
[函数] 请问 LOGAND 的详细用法 (陈老师你那本书也说得太不详细了,就HELP里那两个例子,
的6楼讲到
autocad的许多系统变量与位运算有关,比如undoctl, pickstyle。使用位存储是比较节省空间的方法
并以 一组undo函数为例,源码详见http://bbs.mjtd.com/thread-2747-1-1.html 讲解了。
并在此帖的
12楼,回答了:4楼所说,为什么判断多义线是否闭合,dxf 的70 码值,为什么不直接判断是否及值等于1
(setq en (car(entsel))
el (entget en)
flag70 (cdr (assoc 70 el))
)
(if (= (logand flag70 1) 1)
(print "此多义线闭合")
)
你也许要说我直接判断其是否等于1不就好了回答详见http://bbs.mjtd.com/thread-2747-2-1.html 12楼
页:
[1]