这周加更,原因有二:(1)本来昨天上午是买了票回家的,但一时失算没有预留候车的时间,光是从售票处走到检票口,几十米的距离,挪了近半个小时,结果很顺利地没赶上车,又很顺利地改签失败,最终无奈退票😂,买了今天的火车票再次启程🚋,所以昨晚有时间整理自己的东西,加推一篇技术类文章;(2)也是主要原因啦,就在昨晚,由我创建的 CATIA V6 二次开发群 在三个月不到的时间里实现了成员 破百的小目标,故而加推以表庆祝👏。当然,这其中也不乏有同事、朋友和所有群成员的共同努力和支持🙏。
这里需要跟群友们致歉的是:一方面由于我正式接触CATIA这个软件的时间并不长,所以群里的很多问题我都显得有心无力,所以只能靠其他管理员或者大佬们提供反馈;另一方面我目前的开发以VBA为主,编程语言采用C#,算是目前最方便、最容易入门的一种开发方式了,但就目前来看,群里的开发方式其实是以CAA为主,我同样是两手一摊,束手无策。但我仍然会持续输出我所涉及的CATIA开发相关的技术经验,供大家参考,并会分享一些相关的高水平论文和技术资料给大家,做好服务工作。
好了,进入正题。这一期咱们聊一聊让无数CATIA开发者(包括我自己在内)头疼的==参数单位(Unit)==问题。
一、技术实现
第一步 看看API怎么说
Except when explicitly documented, numerical values stored and internally handled for computations are expressed using the MKSA unit system except for two dimensions:
Length are expressed in mm
Angles are expressed in decimal degrees
译文如下:
除非特别指定是哪个单位,软件内部存储和运算的数值都是使用国际基本单位制,即MKSA,但是呢有两个例外:
长度不是用m,而是mm
角度不是用弧度制,而是用十进制的度
那什么是MKSA呢,其实就是米—千克—秒—安培制(Meter-Kilogram Second Ampere),这些都是国际基本单位。那么我们就很明确了,CATIA软件内部单位的设定应该是如下表所示。
量纲 | 单位 |
长度 | mm |
角度 | deg |
时间 | s |
质量 | kg |
面积 | m2 |
体积 | m3 |
细心的读者肯定会注意到这样一个问题:在长度单位采用mm的情况下,面积和体积仍然采用m2和m3。是的没错,API已经写得很清楚了,只有两个例外,其它都应该按国际基本单位来执行。
第二步 创建参数时,其值的量纲由谁决定?
大家都知道三维建模软件都会给予用户修改默认单位的权限,以提高软件的自由度。但是,这样的灵活度反而给代码的编制增加了难度,例如我有这么一串代码,如果跑在单位配置不同的计算机上是不是会出现不同的结果呢?你所创建的参数有可能是2000mm,也有可能是2000m,同样有可能是2000cm,这样就乱套了。
paras.CreateDimension("长度",“LENGTH”,2000);
所以,软件就需要一套用于内部运算的量纲设定,这个设定独立于当前计算机中软件本身的单位设定,是内在集成的。所以在CATIA二次开发中,对于创建参数时的数值量纲直接按上表考虑,无需关心本机的单位配置。
第三步 修改参数值时,量纲由谁决定?
修改参数值时的量纲选择是我一直感觉奇怪的地方,CATIA反而摒弃了自己内部运算的那一套,改用纯的MKSA国际单位制,也就是说长度单位变成了m,角度变成了弧度制。但是,好处是由于修改参数时是采用字符串赋值,而且软件可以识别字符串中的单位,所以这里强烈建议大家在参数写入时加上你想要赋予的单位。
// 此时参数值被修改为2
// 此时参数值被修改为2000 m para.ValuateFromString("2000") // 此时参数值被修改为2000 mm para.ValuateFromString("2000mm")
第四步 读取参数值时,量纲由谁决定?
其实上述的创建啊、修改啊还不算复杂,你只需要记住它默认的量纲即可,但参数的读取是真的令人头大,因为这会关联到当前计算机中软件的单位配置,而每个人的配置又可能不一样,例如同样的一个参数,A电脑打开显示为5m;B电脑打开则显示5000mm,虽然值都是相等的,但程序如何做出判断,并统一转换为标准的数值还是个问题。在之前 CATIA二次开发—参数那点事 那一期里,我也提及了使用正则表达式来解决这一问题的办法,但这个方法是存在漏洞的,因为你不可能把所有单位都罗列一遍并给出转换系数。
作为一个有强迫症的程序员,我一直在寻觅更好的办法。最后还是被我找到了。其实也很简单,只是我们被现有的功能代码限制住了思维。现有的做法是拿到Parameter实例就立马去拿参数的值,而这里的Parameter定义太广,包含了字符串、实数、量纲值等等,所以此时你只能拿到一个String,然后自己再去判断。然而没人问过:为什么当我们拿到Parameter之后就要停下来呢,我们其实是明确知道自己想要拿的参数是什么类型的,完全可以进一步细化成Parameter的子类(如下图),例如Dimension。所以我们的问题就迎刃而解了,一旦我们拿到Dimension,那么通过它的属性Value,就可以获取到参数值所对应的软件内部运算值,也就是说如果是长度,你会直接拿到以mm为单位的数值。
三、参考资料
《3DEXPEROENCE Automation Help》