杨淑德21 翟晓庆22 华顺刚21
(1 大连理工大学机械工程学院 2 山东理工大学机械工程学院)
摘 要: 结合 OpenGL和ActiveX技术,研究了三维装箱的可视化问题,在Visual Studio环境下,进行面向装箱布局的三维显示控件开发。通过接口方法获得货物配载信息,实现货物配载结果的可视化;为了观察集装箱内货物布局,根据用户观察方向与箱壁平面法线方向,判别集装箱箱壁平面是否绘制。以线框形式显示货物,便于查看整体重心和集装箱几何中心的位置,从而判断配载方案的稳定性。控件测试表明,该控件可以根据配载货物的特征信息和位置信息,实现货物配载整体效果显示、货物摆放方式和堆码层数显示、重心显示和货物高亮显示等功能,直观地展示装箱配载结果,便于用户调用、观察、验证和修改装箱布局方案。
关键词: ActiveX控件; 装箱布局; OpenGL; 可视化
1 引言
随着物流业的快速发展,物流技术的应用和研究受到越来越多的重视。产品的配送效率成为影响物流成本和竞争力的重要因素。集装箱配载优化布局作为物流配送过程中的一个关键性技术, 对提高
配送业务的自动化水平,提高配送业务的工作效率和规范业务流程等方面都有重要意义[1]。
国内外诸多学者对装箱布局问题开展了研究,提出了利用遗传算法、启发式算法和模拟退火算法等进行配载的解决方案[2-3]。通过配载算法对货物进行布局,快速地设计集装箱装箱方案,达到对集装箱空间和载重能力的更好利用。装箱布局结果的三维可视化可以直观的显示货物的放置情况,有利于设计人员验证配载结果的正确性,便于指导装箱工人完成装箱任务。与现有的多种配载算法相比,对装载结果的可视化研究较为欠缺。Bortfeldt[4]对启发式算法改进后没有给出直观的装箱效果图,没有提供细节的显示。Chien[5]结合三维裁剪提出配载算法并实现装载结果的显示,但是只绘制了集装箱和货物的轮廓,不容易区分外形尺寸相近的货物。郭贝贝[6]开发的装箱可视化系统可以显示货物给定角度的放置情况和某类货物的放置情况,无法全方位的观察货物的放置情况。桂思怡等[7]开发的立体装箱可视化系统虽然可以实现手动编辑,但是该系统是基于特定算法开发的。
基于此,本研究对图形绘制显示代码进行封装,开发装箱布局三维可视化控件,便于用户调用。用Visual Studio MFC 开发ActiveX控件,根据配载优化结果,利用图形应用程序接口OpenGL,根据视线方向选择性绘制集装箱箱壁,完成货物不同视角观察结果的绘制,显示整体重心和集装箱几何中心,高亮显示用户查询的某一托盘单元或货物。
2 OpenGL和ActiveX技术
OpenGL是独立于硬件设备、窗口系统和操作系统的开放式三维图形库,是图形硬件的软件接口。具有高度的可移植性和很快的渲染速度。在涉及图形图像显示及处理的应用程序开发中得到了广泛应用[8]。在三维实体建模、物体坐标变换以及纹理贴图等方面具有强大功能。
组件对象模型(COM)是关于如何建立组件以及如何通过组件构建应用程序的一个规范。在软件项目中,开发人员使用COM能快速地定制出新的应用程序,从而实现并行开发和真正意义上的软件复用。ActiveX是基于COM技术基础,实现对象链接与嵌入的技术集,包括ActiveX控件、ActiveX文档和ActiveX脚本。其中ActiveX控件是最基本和最重要的,程序员可以在Basic、C#、C++以及Java等程序中调用ActiveX控件进行应用程序或web页面开发。由于ActiveX控件结合了OLE功能而能在任何控件容器中正确工作,使其能够为各种不同的编程语言系统和开发工具所兼容。Visual C++提供了两种ActiveX控件的开发工具MFC和ATL。其中MFC封装了OLE复杂的接口的特性,包括窗口对象特性和方法、属性及事件等,无需深入了解COM对象原理和机制,开发过程中只需关注控件本身设计[9-10]。
3 装箱布局三维可视化控件接口
接口是控件与外部程序进行通信的协议。外部程序通过接口提供的属性和方法来传送消息给控件。控件的属性一般用于描述控件的外观。控件的方法是控件内部的实现函数,从控件对象的外部调用对象的方法完成特定功能[9]。本文在可视化控件内部编写接口实现函数,外部程序通过调用控件方法将配载结果数据传递到控件内部的。
装箱配载结果数据由集装箱和一定数量货物的特征信息、位置信息组成。结合装箱的实际情况,本文中认为长方体类货物为规则形状货物,其他形状货物均为不规则货物。体积大的规则货物可以直接装载,体积小较为零碎的规则货物可以利用托盘进行装载;不规则形状货物,用长方体纸箱或者木箱进行包装后装载。假设集装箱箱体、托盘和打包后的货物密度均匀,建立描述集装箱、托盘和货物信息的数据结构体。
本研究设计了若干结构体用于存放描述集装箱、托盘和货物的位置、外形和颜色的数据。用于描述集装箱的CONTAINER结构体中包括表示集装箱长宽高、集装箱角件长宽高、角件中心的XYZ坐标等数据成员;用于描述货物和托盘的CARGO结构体中包括表示货物(或者托盘)中心XYZ坐标、货物(或者托盘)长宽高和货物(或者托盘)颜色的数据成员;用于描述整体重心和集装箱几何中心的SPHERE结构体中包括表示球心XYZ坐标、球体半径和球体颜色的数据成员。
在Visual C++中,VARIANT 是一个支持跨语言访问的结构体[11]。该结构体包括vt和union两个域,其中vt指定union域中的数据类型。SAFEARRAY是Visual C++中的一种结构体,成员数据包括数组成员和说明数组的维数、长度、边界、元素类型等信息的成员。
SAFEARRAY变量一般用于VARIANT中数组型参数的传递。VARIANT类型变量的成员vt = VT_ARRAY时,可以使用union域中的成员parray,使其指向存有数组数据的SAFEARRAY指针。可以利用API函数SafeArrayCreate (VARTYPE v, unsigned int cDims, SAFE- ARRRAYBOUND FAR* rgsabound )在堆上创建一维数组和二维数组。其中,v指定SAFEARRAY中数组的数据类型;cDims指定SAFEARRAY中数组的维数;rgsabound指向描述SAFEARRAY中数组边界的矢量。
本研究控件方法获取的数据中包含结构体数组,不能作为ActiveX控件方法的参数。同时为保证用户可以跨语言调用控件,因此需要将存放集装箱、托盘和货物的数据的结构体数组通过SAFEARRAY变量封装到VARIANT变量中。绘制图形所需的数据就存储在SAFEARRAY数组数据成员pvData指针指向的内存中。
利用Visual Studio 2010创建MFC ActiveX 控件工程。在自动生成的_DGLActiveX类中中添加控件接口方法函数Display (VARIANT &Sphere, VARIANT &CargoSolid, VARI- ANT&CargoMesh, VARIANT &Contain,VARIANT_BOOL isShowSphere, VARIANT_BOOL MeshAndFill, LONG CargoMeshAmount, LONG CargoSolidAmount)。
其中,方法函数中各参数的含义如下:Sphere中存放整体重心和集装箱几何中心的数据;CargoSolid中存放需要以实体显示的货物数据;CargoMesh中存放需要以线框形式显示的货物的数据;Contain中存放集装箱的数据;isShowSphere用来表示是否需要显示整体重心和集装箱的几何中心;MeshAndFill表示货物的显示模式;CargoMeshAmount存放需要以线框形式显示的货物数量;CargoSolidAmount存放需要以实体显示的货物数量。
在控件中,调用SafeArrayCreate函数创建SAFEARRAY指针作为中间变量,使其指向接口方法中VARIANT类型参数的union中的parray数据成员。在CGLActiveX控件工程的CGLActiveXCtrl类定义中,声明SAFEARRAY类型的全局指针变量pArraySp、pArrayCon、pArrayMesh和pArraySolid,在控件方法函数中调用SafeArrayCreate函数在堆上为它们分配存储空间。将Sphere、Contain、CargoMesh和CargoSolid的成员parray分别赋值给上述四个SAFEARRAY指针变量。
控件方法函数中创建安全数组并赋值的代码如下:
pArraySp = SafeArrayCreate(VT_I4,2, BoundSp);
//创建存储重心数据的二维数组
pArraySp = Sphere.parray;
pArrayCon = SafeArrayCreate(VT_I4,1,BoundCon);
//创建存储箱体数据的一维数组
pArrayCon = Contain.parray;
pArraySolid = SafeArrayCreate(VT_I4,2, BoundSolid);
//创建存储实体货物数据的二维数组
pArraySolid = CargoSolid.parray;
pArrayMesh = SafeArrayCreate(VT_I4,2, BoundMesh);
//创建存储边框货物数据的二维数组
pArrayMesh = CargoMesh.parray;
4 基于OpenGL的装箱布局图形绘制
OpenGL绘制几何图元的方法有立即模式、显示列表和缓冲区对象。其中,立即模式是指定完图元之后将所有数据发往渲染管线后立即被渲染。一次一个顶点地指定几何对象,或者使用顶点数组,一次性的绘制大量图元。显示列表模式是利用预编译的命令列表的渲染模式。把绘图命令和数据先进行预处理,然后保存起来,以后调用的时候可以快速地拷贝到命令缓冲区然后执行。缓冲区对象多用于纹理贴图与动画制作中[8]。
显示列表中不能存入传递参数或返回值的函数。索引顶点数组的顶点变换工作量也比立即模式和显示列表少得多。在有较大平滑表面的模型或静态图形中,索引顶点数组的效率高于显示列表[12]。
本研究中绘图命令中包含返回值的函数,同时绘制的是表面光滑的静态图形,因此采用立即模式,使用索引顶点数组方式,完成几何图元绘制。
4.1 OpenGL绘图环境设置
OpenGL采用渲染上下文Render Context (RC) 的绘图方式,绘图前需要设置渲染环境[13-15]。为了获得模型更全面的信息,需要对三维模型进行几何变换。几何变换包括模型变换和视点变换。模型变换时,固定观察点的位置和方向,在观察范围内对模型进行旋转、平移和缩放操作,获得不同的观察效果图。视点变换是改变观察点的位置和方向后对模型进行观察,而不对模型进行变换。模型变换需要调用GL库中的glTranslate函数和glScale函数配合使用完成。视点变换利用GLU函数库中的gluLookAt函数设置观察点的位置坐标、被观察点的位置坐标和向上方向的向量完成。模型变换矩阵和视点变换矩阵共同构成模型视景矩阵。
本研究在控件工程自动生成的CGLActiveXCtrl类中添加设置OpenGL像素格式和渲染环境的成员函数,完成像素格式和渲染环境RC设置。通过视点变换指定观察点的位置和方向,根据观察点的位置和方向,选择性绘制集装箱的各个平面,通过模型变换在适当位置绘制出指定尺寸的货物。通过视点变换和模型变换相结合实现集装箱装载的三维可视化,控件的绘图流程如图1所示。
图1 ActiveX控件绘图流程图
4.2 集装箱面的显示
OpenGL对三角形图元和四边形图元均提供了加速处理。集装箱和货物均为长方体,因此本研究采用四边形图元绘制集装箱箱壁。为了观察集装箱内货物的放置情况,选择性绘制箱壁,采用填充图完成需要显示箱壁的绘制。
如图2(a)所示长方体代表集装箱,给定8个顶点 A(xa,ya,za)、B(xb,yb,zb) 、C(xc,yc,zc) 、D(xd,yd,zd) 、O(xo,yo,zo) 、E(xe,ye,ze) 、F(xf,yf,zf) 、G(xgyg,zg) 的坐标。矢量ɑ所示的方向代表视线方向。根据每个箱壁平面的三个顶点,计算对应箱壁的外法线方向。
以平面ABCD为例,根据点A、B、C坐标计算外法线方向
(1)
给定观察的视线方向a,计算视线方向与外法线夹角θ 余弦
(2)
若cosθ,表示该平面为集装箱的背面(远离观察者),应绘制平面;若cosθ≤ 0,不绘制该平面,便于观察内部货物。如图2(a)所示视点位置和方向,通过公式(1)和(2)对集装箱的六个平面分别进行判断,只需绘制平面AOGD、平面ABEO和平面OEFG,箱体绘制结果示意图如图2(b)所示。
图2 箱体绘制示意图
为改善箱体的空间立体感,采用与填充面不同的颜色绘制箱体轮廓。箱体轮廓线与箱体填充面的边界具有相同的深度值,发生像素重叠。由于在渲染环境设置中打开了深度检测功能,后绘制的轮廓线无法遮挡前面绘制的图形导致在重叠区域发生像素闪烁。在OpenGL渲染环境设置函数中启用多边形深度偏移量,并调用glPolygonOffset函数在深度缓存区中对多边形的深度进行修正,解决填充面和边框同时显示区域的像素闪烁问题,从而得到清晰立体的集装箱箱体图。进行视点变换通过改变gluLookAt的参数改变观察点的位置和方向,绘制不同的箱壁平面,绘制效果如图3所示。在后续的货物实体绘制工作中,采用与此相同的方式实现货物不同视角观察结果的图形绘制。
图3 不同视角观察箱壁绘制效果图
4.3 货物实体显示
根据货物的配载计算结果,利用OpenGL图形库在ActiveX控件上完成货物三维实体显示,实现了货物在集装箱内的布局情况的可视化和装箱过程的透明化。
OpenGL在显示物体的空间中定义一个始终固定不变的世界坐标系和一个以物体的中心为坐标原点的局部坐标系。物体的旋转或平移等操作都是围绕局部坐标系进行的。当物体模型进行旋转或平移等操作时,局部坐标系也执行相应的旋转或平移操作。对物体模型进行缩放则局部坐标系也进行相应的缩放[8]。先将局部坐标系移动到货物中心位置处,然后再对各个坐标轴进行缩放,保证在目标位置将货物绘出。
OpenGL创建三维实体对象时,利用提供的点、线、面等基本图元在三维空间进行组合而实现。OpenGL的GLUT工具包中提供了圆锥体、四面体、正方体等三维实体对象,因此可以直接调用GLUT工具包中的函数绘制三维实体。利用glutSolidCube函数绘制正方体,通过一系列的移动和拉伸命令在任意位置绘制任意尺寸的长方体。
以表1所示货物的装载为例,完成全部货物在集装箱内放置情况的显示。
表1 装载任务信息列表
货物名称货物尺寸/mm长宽高货物颜色RGB颜色示例货物数量个C1600300500255128128100C26003005002551280100C37203105602551280100C45504406601281280100C5400410450128105180100C6720310560189183180100
不同种类的货物以不同RGB值描述的颜色来表示,承载不同货物的托盘不予区分采用相同颜色绘制。调用glColor3f设置货物实体颜色,调用glTranslatef将坐标系移动到指定位置,调用glScalef对XYZ坐标方向尺寸进行缩放。调用glutSolidCube绘制指定位置的实体货物。此时绘制的三维实体均用当前绘图色以填充面形式绘出。
在一次绘图过程中可能要绘制许多的长方体模型,利用托盘装载的货物也需要体现在一个托盘上货物的放置情况。为了显示装载细节,区分同类货物的不同个体,清晰展示配载货物的行数、列数、层数,因此需要在绘制的实体模型基础上对每个货物绘制黑色边框来区分不同货物单体。将绘图色指定为黑色,然后使用glutWireCube命令绘制货物边框。绘制的线框图与实体图尺寸和位置均相同,两者具有相同的深度偏移量,发生像素重叠,在OpenGL渲染环境设置函数中设置多边形深度偏移量消除像素闪烁。如图4所示为表1给定任务的用两个集装箱装载结果图,用两个集装箱完成装载的放置结果实体图。其中C1、C2、C3、C4、C5、C6所指的小长方体表示该类货物的一个单元体。在装载结果中可以根据需要高亮显示集装箱中任意一个托盘单元或者任意单个货物,如图5所示。
图4 装配结果
图5 装载货物高亮显示
4.4 整体重心和集装箱几何中心的显示
集装箱的装载货物时要满足运输稳定性约束,要求配载完成后整体的重心尽量接近于集装箱的几何中心。为了观察配载完成后的箱体几何中心和综合重心之间的位置关系,可以绘制货物的轮廓。两者的位置关系通过在相应位置处绘制球体示意,货物轮廓的颜色与实体颜色一致以区分不同种类的货物。
将整体重心和集装箱几何中心的数据分别读取到SPHERE结构体变量MultiCenter和GeoCenter中。使用glLineWidth函数和glColor3f函数设置线条宽度和当前绘图颜色。调用GLUT工具包函数glutWireCube完成货物轮廓的绘制。整体重心和集装箱几何中心以实体的形式通过glutSolidSphere函数完成显示。程序默认的初始输出结果是三维实体状态,此时不进行重心绘制。在显示模式下拉列表中将当前模式设置为重心显示,绘制货物轮廓、整体重心和集装箱几何中心,图6所示为整体重心和集装箱几何中心不重合情况的显示效果图。图中A点为集装箱几何中心,B点为整体重心。
图6 显示整体重心和集装箱几何中心
4.5 装箱布局可视化控件测试
将控件工程拷贝到货物配载解决方案目录下,打开货物配载解决方案。在解决方案管理器中配载解决方案上右键选择add->existing project,完成控件工程的添加。在add existing project对话框中选择货物配载解决方案目录下的控件工程,将控件工程添加到货物配载解决方案中。在需要调用控件的项目中添加控件工程的引用,这样就可以在工程中使用该控件了。
对表1所示任务进行优化配载后,第一个集装箱的输出结果如图7所示。
图7 程序运行结果图
5 结语
本研究在Visual Studio2010环境下,用MFC实现了基于OpenGL的三维图形显示ActiveX控件开发。该控件围绕装箱布局三维可视化进行开发,读取并显示装箱布局结果。可以根据用户需要高亮显示部分货物或者从不同角度观察集装箱内货物的布局情况,使装箱配载方案变得清晰直观。本研究对装箱布局优化的显示模块进行封装,在需要进行三维显示的地方只需调用控件即可,降低了程序的复杂度,便于程序的升级维护。可以直观地查看几何中心和综合重心的位置关系,便于配载设计人员对装箱配载结果的稳定性进行初步判断。
参 考 文 献
[1] 薛莲. 同一规格货物集装箱装载问题研究及其在物流行业的应用[D]. 天津: 天津大学, 2008.
[2] 翟钰. 三维装箱问题的混合遗传算法[D].上海: 上海交通大学, 2007.
[3] 赵钟荣. 基于改进遗传算法的集装箱装载优化方法研究[D].上海: 上海交通大学, 2010.
[4] BORTFELDT A,MACK D. A Heuristic for the Three-dimensional Strip Packing Problem[J].European Journal of Operational Research,2007,183(3):1267- 1279.
[5] CHIEN C F,DENG J F.A Container Packing Support System for Determining and Visualizing Container Packing Patterns[J].Decision Support Systems,2004,37(1):23-34.
[6] 郭贝贝. 复杂集装箱装载问题研究及可视化实现[D].大连:大连海事大学, 2009.
[7] 桂思怡. 基于DirectX的立体装箱系统3D可视化技术研究[D]. 大连: 大连海事大学, 2014.
[8] WRIGHT R S,LIPCHAK B,HAEMEL N.OpenGL超级宝典[M].张琪, 付飞, 译. 4版. 北京: 人民邮电出版社, 2010:18-409.
[9] 孙鑫, 余安萍. VC++深入详解[M]. 北京: 电子工业出版社, 2006: 660-699.
[10] KRUGLINSKI D,WINGO S,SHEPHERD G.Programming Visual C++6.0技术内幕[M]. 希望图书创作室,译. 5版. 北京: 北京希望电子出版社, 2002:550-666.
[11] MICROSOFT. Development Tools and Languages[EB/OL]. https://msdn.microsoft.com/en-us/library/aa187916.aspx, [2015-06-22].
[12] 曹洪军, 原英. 利用OpenGL实现三维绘图[J]. 内蒙古农业大学学报(自然科学版), 2002,23(3):98-102.
[13] 匡天君,滕远道,王乘等.基于MFC和OpenGL三维图形的开发[J]. 微计算机信息:测控仪表自动化, 2004, 20(6):115-116,119.
[14] 万浩.基于OpenGL的虚拟仪器三维控件设计[D].武汉: 华中科技大学, 2008.
[15] 黄常标, 江开勇, 林俊义. 基于OpenGL视景体的三维CAD模型交互显示研究[J]. 机械设计与制造, 2011,10:74-76.
Development of the 3D Visualization Control for Containers' Loading Layout
Yang Shude1 Zhai Xiaoqing2 Hua Shungang1
(1 School of Mechanical Engineering Dalian University of Technology 2 School of Machinery Engineering Shandong University of Technology)
Abstract: 3D visualization of the container loading layout is researched by using ActiveX and OpenGL in this paper. A visualization control is developed based on cargoes' shape and location under Visual Studio environment. The stowage data is obtained using the interface function to render the cargoes in the container. In order to observe the cargoes conveniently, surfaces of the container near observer are not rendered according to the relationship between the eye-gaze direction and the normal of surface. The gravity of cargoes is displayed and then we can predict the stability of entire container. The test results show that the control facilitates users to display the cargoes' layout involving placement mode, stack number, gravity center, as well as validate and modify the stowage scheme.
Key words: activeX control; container loading layout; OpenGL; visualization
DOI:10.3963/j.issn.1000-8969.2016.02.003
收稿日期: 2015-09-23
基金项目: 国家部委科研项目(104010103)
杨淑德: 116024, 辽宁省大连市甘井子区凌工路2号