读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
- 读DWG,提取坐标并按照一定间隔离散化,包括"代理实体"如何提取坐标
- 圆心坐标的提取
- 圆心坐标的提取
- C#坐标提取
- 【坐标离散化】矩形面积求并
- 霍夫变换提取圆心坐标,并拟合直线
- 直接提取四个顶点坐标
- java提取PDF文字坐标
- 如何使用ArcMap提取地图数据的坐标信息
- 如何让用ARCMAP提取地图坐标信息
- 如何使用ArcMap提取地图数据的坐标信息
- 坐标离散化技巧
- 坐标离散化处理
- 坐标离散化
- 坐标离散化
- 区域坐标离散化
- 坐标的离散化
- 坐标离散化,imos
- 一.Contiki之进程(2)——创建进程
- 常用的正则表达式
- 设计模式--原型模式、其他模式--徐旸
- Linux中bash基础
- OracleServiceORCL服务无法找到
- 读DWG,提取坐标并按照一定间隔离散化,包括"代理实体"如何提取坐标
- C#控制台屏蔽关闭按钮
- php+中文分词scws+sphinx+mysql打造千万级数据全文搜索
- 欧拉工程第13题 找出100个50位数之和的前十位数字
- JavaWeb文件上传、下载
- dagger2 让你爱不释手:基础依赖注入框架篇
- How to install Desktop Environments on CentOS 7?
- AlarmManager
- MFC CWinThread Class成员变量及成员函数