• 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://1001night.blogbus.com/logs/2771974.html

        这件事的发展过程总的说来就是个傻字。
        一开始,我用MFC做了个雏形,想要试用后优化。限于技术能力,输入是人工的,而输出则是简单的文本文件,中间算法更是简单得要命,是类似画正字的数组递增。初步打算如果程序逻辑没有问题的话,就使用ActiveX之类的技术从CAD读入数据,然后可以在几种不同的输出方式中选一种,既可以直接输出到文本,也可以产生一个表格,甚至可以直接在CAD的绘图环境中画出最终的统计表。但是正如我前面已经提到,数据在不同程序间的传输是个很头疼的问题,既涉及到协议还涉及到安全性。不过我根本没前进到需要解决这些问题的阶段,因为用户们(也就是同事们和我自己)的试用反馈已经到达。画图画到一半,要从CAD环境退出,启动另一个程序,操作之后再抄录数据到CAD,我们都非常不习惯这种使用方式。于是我转向CAD二次开发。
        我先前并不想玩二次开发,因为那意味着要阅读很多CAD的文档,不过显然独立程序同样要读这些文档,那么还是二次开发容易些。AutoCAD面向不同的开发需求,提供了不同的方式。主要有使用lisp语言类似脚本语言的VisualLisp,使用VB、Delphi等语言的ActiveX,和使用C/C++语言的ObjectARX技术。我会在另外的文字里详细介绍这些开发方式。考虑到我对C++还算比较熟悉,决定使用ARX。
        由于ARX的开发包包含了大量的文档和示例,CAD内部的数据结构以及系统提供的功能都只需要查阅手册就可以而代码堆砌其实也是很容易的事情,所以寻找解决方案才是关键。首先是确定需求。在初期这很明确,就是要能够自动统计材料。至于以后要增加别的功能,那以后再说。这时我参考了天正给排水。天正是一套运行于CAD环境上,包括结构、电气、给排水等很多建筑专业应用的行业软件,是综合使用各种二次开发技术制作的。我着重分析了天正给排水的实现方案,希望能对我的工作有所帮助。这里我要解释下,给排水其实分好几个分支,有市政、建筑、水处理等。天正做的是室内,而我的领域是市政。有过装修经验的人知道,室内给排水的材料其实可以分成两大类,以长度计算的管材和以个数计算的配件。天正把管材都处理成多段线,而配件则是带属性的块。所有的块和多段线都预先保存为库,绘图时当用户输入必需的参数后就直接从库中读取,程序会自动完成其他的计算。市政的材料有类似的情况,我当然也想采用这样的方案,但问题很快出现了。室内的一个特点是大量使用完全一样的配件,比如一栋60层高的宾馆,他所使用的洗手池虽然数量有很多,但只有一到两个型号规格,这就使一图一物成为可能。可以一个块用来表示一种洗手池,另一个略有差别的块用来表示另一种。这样整个图上的配件只需定义少量的块就可以,而且在使用块的时候也不容易出错。而市政的情况大为不同,配件的品种很少而规格却很多。比如闸门这种常见的配件,在口径上从直径20mm以下到直径2000mm以上就有超过20个规格,如果加上其他附属特性就更多了。而按照设计规范的要求,所有闸门的图例都是一模一样的,这就带来了困扰。从模仿天正开始,我设计了几种解决方案。
        第一种是每个规格都定义为一个块,直接后果首先是块库极度膨胀,同时用户从巨大的块库中选择配件时相当容易出错,误选其他规格的同类配件。由于外观相似,这种错误极难发现,所以这个方案立刻就否定了。第二个方案要进步些,同一品种的配件可以用同一块来表示,但在插入设计图的时候,要求用户立刻输入参数,以达到记录规格的目的。这个方案最大的问题在于增加了用户的工作量,使得最终程序所提供的便利完全被抵消了,哪个用户愿意为了仅仅十几分钟的便利而花上2个小时的额外劳动呢。同时这种方式的准确度也依赖于用户,输入错误几乎不可避免,因此这个方案也不予考虑。但是,如果能以某种方法自动而且准确的填入那些参数,那么结合这个方案就有实现的价值。幸运的是,我找到这种方法了。
        作为设计人员,我清楚的知道,管线和配件具有关联性。就以室内给排水为例,直径20的水龙头不可能直接安装在直径200的管道上,在没有别的配件的时候,管道直径不会突然从100变成50,材质也不会突然从水泥管变成镀锌管。由于这种关联性,一个管网上其实只需要给出特定的几个参数,其它的参数都是可以通过推导得来。那么现在问题变成了,如何在程序中体现这种推导传递的性质,如何找出这些关键参数。先来讨论参数的问题,这很象多元方程组方程的数量比未知数的个数少的情况,自由变量的数量确定,但不特定是哪个。在管网中任意给定一个管材或配件的参数就可以推导出一个范围内的所有值,这个范围我称他为连通的。一个已经设计完成的管网必然可以划分成若干个可连通的子网,只要向各个连通子网给出参数,每个子网都是可解的,最终整个管网可解。而连通子网的参数可以在后期要求用户输入,这个工作量是用户可以接受的,同时正确率也有保证。这样就剩下建立连通性的问题。我找到了两个解决方案。第一是人工智能,第二是最近匹配。人工智能就是实现图像的识别,在图上找出管线和配件,再判别出他们的关系。这是一劳永逸的解决方案,理论上说只要人能阅读的图纸,机器也行,那样即使用户没有按照标准绘图也没关系。但其中的算法真是太繁琐了。最近匹配要简单得多,配件做成块,管线则是多段线,他们寻找离自己最近的对象建立连接,算法简单,实现容易。当然其中还有些细节,我就不讨论了。
        那么最后,我的程序是按这个方案制作的么,赫赫,不是。在试过各种各样的策略之后,最后我用了一种非常简单的方法,简单而有效。程序为什么还要试图理解图纸呢,还要自己去读参数呢,所有的东西,设计人都会标注出来。阅读这些标注就可以解决所有的问题。于是最后,我的程序成了这样一个东西,他只是扫描选中的标注,然后文本处理,结果就出来了。绕了一圈,最后我使用的算法的核心竟然就是一开始的那一个程序,数组元素递增。果然老话有道理,最简单的也最有效。


    收藏到:Del.icio.us




    评论

  • 感谢博主分享。