将Autocad的图形填充(Hatch)转化为三角形

目前在研究通过DirectX 或者OpenGL来显示Dwg图纸,一些基本的功能已经完成,但是对于图形填充遇到了一些问题。

DirectX中基本的元素只有三角形,但是Autocad的图形填充可以是任意几何图形,所以我们需要将Autocad的图形填充转换为三角形。

将Autocad的图形填充(Hatch)转化为三角形

虽然有很多图形计算理论,但是以前没做这一块,决定还是找现有的类库来完成这个过程。

由于Hatch的定义为若干个Loop之间的运算,目前看来是Xor 计算,所以,第一步为确定图块计算的类库。考虑到图块计算基于点线,而结果也是点线,暂时排除了C# 默认的System.Drawing里面的Geometry和WPF 里面的Path类库。而是采用了Clipper(http://angusj.com/delphi/clipper.php#features)。

参考代码如下:

     Clipper cpr = new Clipper();
            int idx = 0;
            foreach (var subitem in item.SubItems) {
                var path = new Path();
                foreach (var p in subitem.Points) {
                    path.Add(new IntPoint(p.X, p.Y));
                }
                var txt = GetPointsText(path);
                if (idx == 0)
                {
                    cpr.AddPath(path, PolyType.ptSubject, true);
                    idx++;
                }
                else {
                    cpr.AddPath(path, PolyType.ptClip, true);
                }
                
            }

,cpr.Execute(ClipType.ctXor, shapes, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

这里得到的结果shapes是若干个图形,其中第一个是图形是外轮廓,其他是内部的空洞,所以建立了2个三角形几何,一个是图形,一个是内部孔洞。

为了简化计算,图形使用Hatch自己的颜色绘制,而空洞采用背景色绘制。

  idx = 0;
            C2DPolygon hull = null;
            bool isHole = false;
            foreach (var shape in shapes) {
                List<C2DPoint> pts = new List<C2DPoint>();
                foreach (var p in shape) {
                    pts.Add(new C2DPoint(p.X, p.Y));
                }
                C2DPolygon plyg = new C2DPolygon(pts,true); //获取到几何对象
                if (idx == 0)
                {
                    hull = plyg;
                    isHole = false;
                }
                else {
                    isHole = hull.Contains(plyg);
                }
                plyg.CreateConvexSubAreas();//将当前对象拆分为多个凸角结合图形
                subareas = new List<C2DPolygon>();
                plyg.GetConvexSubAreas(subareas);//得到拆分后的几何图形。
                foreach (var area in subareas)
                {
                    c2dpoints.Clear();
                    area.GetPointsCopy(c2dpoints);
                    for (int i = 2; i < c2dpoints.Count; i++)
                    {
                        Point3D[] triangle = new Point3D[3];
                        triangle[0] = new Point3D(c2dpoints[0].x, c2dpoints[0].y, 0);
                        triangle[1] = new Point3D(c2dpoints[i - 1].x, c2dpoints[i - 1].y, 0);
                        triangle[2] = new Point3D(c2dpoints[i].x, c2dpoints[i].y, 0);
                        if (!isHole)
                        {
                            triangles.Add(triangle);
                        }
                        else {
                            holes.Add(triangle);
                        }
                    }
                   
                }
                idx++;
            }


在获取三角形的时候,我们用到了另外一个组件:GeoLib(http://www.geolib.co.uk/)

关键代码如下:

 C2DPolygon plyg = new C2DPolygon(pts,true); //获取到几何对象

 plyg.CreateConvexSubAreas();//将当前对象拆分为多个凸角结合图形

 plyg.GetConvexSubAreas(subareas);//得到拆分后的几何图形。

得到凸角几何对象后,就可以很轻松的将结果拆分为三角形。

将Autocad的图形填充(Hatch)转化为三角形