读DWG,提取坐标并按照一定间隔离散化,包括"代理实体"如何提取坐标

来源:互联网 发布:淘宝买衣服肩宽怎么量 编辑:程序博客网 时间:2024/06/08 02:09

一、背景

笔者研究的背景是读取dwg的指定图层,获取图层中的对象坐标信息,并按照一定间隔(模型长度)离散化,获取点的集合,然后用于建模。

用途:比如用于ArcGIS平台、Skyline平台的自动化建模。

二,笔者读取dwg设计的对象类型有:直线、样条线、代理实体、圆、弧和三种多段线(acdbpolyline\acdb2dpolyline\acdb3dpolyline)

代码中笔者自定义的数据结构忽略即可。

简单介绍下“代理”:一般不是CAD自带的图形样式,而是基于CAD二次开发绘制的图形或者是AutoDesk家族的产品绘制的图形,这些图形加载到AutoCAD之后不能完全识别它,所以以代理实体的形式存在。假设代理实体属于图层A,将其炸开之后获得N个实体,这N个实体很可能不属于同一个图层,有的不属于图层A,这点需要明白。另外,代理实体炸开之后,有时候可能还存在代理实体,需要炸开多次才能完全获得简单的实体。

using gis.@base.GisBase;using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using Teigha.DatabaseServices;using Teigha.Geometry;using Teigha.Runtime;namespace Skyline.app.DWG2SKModel{    class DWGRead    {              Database mDB = null;        DWGTool mDwgTool;        //存储原始实体        Dictionary<string, List<long>> mLyrObjDic;        Dictionary<long, Entity> mEntityDic;        //存储简单实体和炸开之后,重新组织的实体        public Dictionary<string, List<long>> Explode_LyrObjDic;        public Dictionary<long, Entity> Explode_EntityDic;                public List<Switch> DaochaList        {            get { return mDaochas; }        }        List<Switch> mDaochas = new List<Switch>();                //离散化的间隔阈值        double mSpaceValue = 5;        Teigha.Runtime.Services mRServices;        public ProgressBar mProcessBar;        public DWGRead()        {            mRServices = new Teigha.Runtime.Services();            mDwgTool = new DWGTool();            Explode_LyrObjDic = new Dictionary<string, List<long>>();            Explode_EntityDic = new Dictionary<long, Entity>();        }                public void Open(string pDWGFilePath)        {            if (pDWGFilePath == string.Empty) return;            if (!File.Exists(pDWGFilePath)) return;            mDB = new Database(false, false);            mDB.ReadDwgFile(pDWGFilePath, FileOpenMode.OpenForReadAndAllShare, false,string.Empty);            OpenLayer();            OpenModel();        }        public void Close()        {            mLyrObjDic.Clear();            mEntityDic.Clear();            mLyrObjDic = null;            mEntityDic = null;            mDwgTool = null;            Explode_LyrObjDic.Clear();            Explode_EntityDic.Clear();            mDaochas.Clear();            if (!mDB.IsDisposed)            {                mDB.Dispose();                        }                 }        private void OpenLayer()        {            mLyrObjDic = new Dictionary<string, List<long>>();            TransactionManager pTMgr = mDB.TransactionManager;            using (Transaction pTransac = pTMgr.StartTransaction())            {                LayerTable pLTable = pTMgr.GetObject(mDB.LayerTableId, OpenMode.ForRead) as LayerTable;                IEnumerator pIterator = pLTable.GetEnumerator();                while(pIterator.MoveNext())                {                    ObjectId objId = (ObjectId)pIterator.Current;                    LayerTableRecord pLTRecord = pTMgr.GetObject(objId, OpenMode.ForRead) as LayerTableRecord;                    mLyrObjDic.Add(pLTRecord.Name, new List<long>());                }                pTransac.Commit();            }                     }        private void OpenModel()        {            mEntityDic = new Dictionary<long, Entity>();            TransactionManager pTMgr = mDB.TransactionManager;            using (Transaction pTransac = pTMgr.StartTransaction())            {                BlockTable pBTable = pTMgr.GetObject(mDB.BlockTableId, OpenMode.ForRead) as BlockTable;                ObjectId pModelSpaceId = pBTable[BlockTableRecord.ModelSpace];                BlockTableRecord pBTRecord = pTMgr.GetObject(pModelSpaceId, OpenMode.ForRead) as BlockTableRecord;                                IEnumerator pIterator = pBTRecord.GetEnumerator();                long i = 0;                while (pIterator.MoveNext())                {                    ObjectId objId = (ObjectId)pIterator.Current;                    Entity pEntity = pTMgr.GetObject(objId, OpenMode.ForRead) as Entity;                    if (!mLyrObjDic.ContainsKey(pEntity.Layer)) continue;                    i++;                    mEntityDic.Add(i, pEntity);                    mLyrObjDic[pEntity.Layer].Add(i);//按照图层名进行组织                }                pTransac.Commit();            }        }        /// <summary>        /// 获取原始图层对象的图层名称集合        /// </summary>        /// <returns></returns>        public List<string> GetLayersName()        {            return mLyrObjDic.Keys.ToList();        }        /// <summary>        /// 获取炸开之后的图层名称集合        /// </summary>        /// <returns></returns>        public List<string> GetExplode_LayersName()        {            return Explode_LyrObjDic.Keys.ToList();        }        /// <summary>        /// 读取指定原始图层的存储对象,并将其炸开,获取新的图层、实体        /// </summary>        /// <param name="lyrName"></param>        public void ExplodeLyrObjs(string lyrName)        {            Explode_EntityDic.Clear();            Explode_LyrObjDic.Clear();            mDaochas.Clear();            List<long> ObjIDList = mLyrObjDic[lyrName];            //Init ProcessBar            if(mProcessBar!=null)            {                mProcessBar.Minimum = 0;                mProcessBar.Maximum = ObjIDList.Count - 1;                mProcessBar.Step = 1;                mProcessBar.Value = 0;            }            int j = 0;            for(int i=0;i<ObjIDList.Count;i++)            {                if(mProcessBar!=null)                {                    mProcessBar.PerformStep();                }                Entity entity = mEntityDic[ObjIDList[i]];                switch(entity.GetRXClass().Name.ToLower())                {                    case "acdbarc":                    case "acdbcircle":                    case "acdbline":                    case "acdbspline":                        //简单实体,直接存储;                        if (!Explode_LyrObjDic.ContainsKey(entity.Layer))                        {                            Explode_LyrObjDic.Add(entity.Layer, new List<long>());                        }                        Explode_LyrObjDic[entity.Layer].Add(j);                        Explode_EntityDic[j] = entity;                        j++;                        break;                    case "acdbpolyine":                        ExplodePolyline(entity as Teigha.DatabaseServices.Polyline);                        break;                    case "acdbproxyentity":                        ProxyEntity proxyEnt = entity as ProxyEntity;                        //道岔单独处理                        if (proxyEnt.OriginalClassName.ToLower().Equals("daocha"))                        {                            Switch daocha = new Switch();                            daocha.SetEntity(proxyEnt);                            daocha.ExplodeDaoCha();                            DaochaList.Add(daocha);                        }                        else                        {                            ExplodeProxyEntity(proxyEnt);                        }                        break;                    //其他类型暂时未处理                }            }        }        private void ExplodeProxyEntity(ProxyEntity pProxyEntity)        {            //这里性能很低,耗时最长;            //减少Explode的实体,增加性能;关键是找到哪些实体不可Explode            //pProxyEntity.GetReferences().Count==0不能作为是否可以炸开的依据            int j = Explode_EntityDic.Count;                      DBObjectCollection dbObjColl = new DBObjectCollection();            try            {                pProxyEntity.Explode(dbObjColl);            }            catch (System.Exception)            {                return;            }            foreach (DBObject dbObj in dbObjColl)            {                Entity entity = dbObj as Entity;                switch (dbObj.GetRXClass().Name.ToLower())                {                    //炸开之后可能还存在代理实体                    case "acdbcircle":                    case "acdbline":                    case "acdbspline":                    case "acdbarc":                        if (!Explode_LyrObjDic.ContainsKey(entity.Layer))                        {                            Explode_LyrObjDic.Add(entity.Layer, new List<long>());                        }                        Explode_LyrObjDic[entity.Layer].Add(j);                        Explode_EntityDic[j] = entity;                        j++;                        break;                    case "acdbpolyine":                        ExplodePolyline(entity as Teigha.DatabaseServices.Polyline);                        break;                    case "acdbproxyentity":                        ExplodeProxyEntity(entity as ProxyEntity);                        break;                }            }        }        private void ExplodePolyline(Teigha.DatabaseServices.Polyline pyline)        {            int j = Explode_EntityDic.Count;            DBObjectCollection dbObjColl = new DBObjectCollection();            try            {                pyline.Explode(dbObjColl);            }            catch (System.Exception)            {                return;            }            foreach (DBObject dbObj in dbObjColl)            {                Entity entity = dbObj as Entity;                switch (dbObj.GetRXClass().Name.ToLower())                {                    //炸开之后还有acdbpolyline类型                    case "acdbcircle":                    case "acdbline":                    case "acdbspline":                    case "acdbarc":                        if (!Explode_LyrObjDic.ContainsKey(entity.Layer))                        {                            Explode_LyrObjDic.Add(entity.Layer, new List<long>());                        }                        Explode_LyrObjDic[entity.Layer].Add(j);                        Explode_EntityDic[j] = entity;                        j++;                        break;                    case "acdbpolyline":                        ExplodePolyline(entity as Teigha.DatabaseServices.Polyline);                        break;                }            }        }        /// <summary>        /// 获取指定图层中所有实体的坐标,姿态角已经计算调整;        /// </summary>        /// <param name="lyrName">图层名</param>        /// <param name="Threshold">长度小于指定阈值的实体,放弃掉;</param>        /// <returns></returns>        //相比'GetObjCoords'函数返回Point3DFList,然后再统一计算姿态角的方法,本方法针对各个实体进行计算姿态角更合适,效果更'顺滑'.        public LinePointList GetLyrObjsCoords(string lyrName, double Threshold = 5)        {            LinePointList result = new LinePointList();            List<long> ObjIDList = Explode_LyrObjDic[lyrName];            if (lyrName.Contains("信号"))            {                //单独处理,炸开后取圆的中心坐标,非圆则过滤掉                Point3DFList mPointList = new Point3DFList();                foreach (long index in ObjIDList)                {                    Entity ent = Explode_EntityDic[index];                    if (ent.GetRXClass().Name.ToLower().Equals("acdbcircle"))                    {                        Point3d center = (ent as Circle).Center;                        mPointList.Add(new Point3DF(center.Y, center.X, center.Z));                    }                }                result.SetPoint3DFList(mPointList);                result.GetNodeRollDirection();                result.GetNodeYawDirection();                return result;            }            else            {                foreach (long index in ObjIDList)                {                    Entity ent = Explode_EntityDic[index];                    Point3DFList pList = new Point3DFList();                    switch (ent.GetRXClass().Name.ToLower())                    {                        case "acdbline":                            if ((ent as Line).Length < Threshold)                                continue;                            else                            {                                pList = GetSimpleEntityCoords(ent, mSpaceValue);                            }                            break;                        case "acdbspline":                            if ((ent as Line).Length < Threshold)                                continue;                            else                            {                                pList = GetSimpleEntityCoords(ent, mSpaceValue);                            }                            break;                        case "acdbcircle":                        case "acdbarc":                            pList = GetSimpleEntityCoords(ent, mSpaceValue);                            break;                    }                    if (pList.Count <= 1) { continue; }//有助于去掉那些琐碎的小线条                    LinePointList pPointList = new LinePointList();                    pPointList.SetPoint3DFList(pList);                    pPointList.GetNodeRollDirection();                    pPointList.GetNodeYawDirection();                    result.AddRange(pPointList);                }                return result;            }        }        private Point3DFList GetSimpleEntityCoords(Entity pEntity, double ParamSpace)        {            Point3DFList result = new Point3DFList();            switch (pEntity.GetRXClass().Name.ToLower())            {                //弧线与直线、样条曲线的阈值计算不同,单独考虑                case "acdbarc":                    Arc arc = pEntity as Arc;                    double param1 = ParamSpace / arc.Radius;                    result.AddRange(GetCurveCoords(pEntity, param1));                    break;                case "acdbcircle":                    Circle circle = pEntity as Circle;                    double param2 = ParamSpace / circle.Radius;                    result.AddRange(GetCurveCoords(pEntity,param2));                    break;                case "acdbline":                case "acdbspline":                                 result.AddRange(GetCurveCoords(pEntity,ParamSpace));                    break;                default:                    //                    return result;            }            return result;        }        /// <summary>        /// 计算圆、圆弧上按圆心角param离散的点坐标        /// </summary>        /// <param name="pEntity"></param>        /// <param name="param">距离或圆心角</param>        /// <returns></returns>        private Point3DFList GetCurveCoords(Entity pEntity, double param)        {            Point3DFList result = new Point3DFList();            Curve curve = pEntity as Curve;            if (curve.StartParam == curve.EndParam) return result;            Point3DF pPt3DF = new Point3DF();            double StartParam = curve.StartParam+ param/2;            while (StartParam <= curve.EndParam)            {                Point3d pt3d = curve.GetPointAtParameter(StartParam);                result.Add(new Point3DF(pt3d.Y, pt3d.X, pt3d.Z));                StartParam += param;            }            return result;        }    }}

三、半自动化建模效果

之所以称“半自动化”是因为模型不是代码构建的,而是sketchup建模完成的。




0 0
原创粉丝点击