为了作业方便,一般会将某个区域按照某种规则划分成单个的小区域,这样就会形成接合表。对于接合表重要的信息主要有单元名称和单元名称所对应的区域(在CAD中用Polyline2d表示)。作业过程中通常会统计接合表各作业单元的接合表面积。
以下是CAD.Net求算过程,在中间环节使用了NPOI,目的是用Excel表输出对应的接合表面积和单元名称。
首先申明输出Excel里面输出的列标题名称:
public const string strTHField = "图号"; public const string strJHBAreaField = "CAD结合表面积"; public const string strDwgAreaField = "DWG图FQ层面积";
求算接合表面积主要代码:
[CommandMethod("cadjhbarea")] public void CalCADJHBArea() { Document acDoc = Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; ArrayList layerArrayList = GetLayerName(acCurDb); Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; string strJHBLayerGeometryName = "FQ"; string strJHBLayerTextName = "MC"; PromptStringOptions pStrOpts = new PromptStringOptions("\n请输入结合表二维线图层名称: "); pStrOpts.AllowSpaces = false; pStrOpts.UseDefaultValue = true; pStrOpts.DefaultValue = strJHBLayerGeometryName; PromptResult pStrRes = acDoc.Editor.GetString(pStrOpts); if (pStrRes.Status == PromptStatus.OK) { strJHBLayerGeometryName = pStrRes.StringResult; ed.WriteMessage("您输入的结合表二维线图层名称为" + strJHBLayerGeometryName); if (!layerArrayList.Contains(strJHBLayerGeometryName)) { Application.ShowAlertDialog("未找到结合表二维线图层名称" + strJHBLayerGeometryName); return; } } pStrOpts = new PromptStringOptions("\n请输入结合表文字图层名称: "); pStrOpts.AllowSpaces = false; pStrOpts.UseDefaultValue = true; pStrOpts.DefaultValue = strJHBLayerTextName; pStrRes = acDoc.Editor.GetString(pStrOpts); if (pStrRes.Status == PromptStatus.OK) { strJHBLayerTextName = pStrRes.StringResult; ed.WriteMessage("您输入的结合表文字图层名称为" + strJHBLayerTextName); if (!layerArrayList.Contains(strJHBLayerTextName)) { Application.ShowAlertDialog("未找到结合表文字图层名称" + strJHBLayerTextName); return; } } string strAppExcel = System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "JHBArea.xls"); HSSFWorkbook wk = null; ISheet pSheet = null; if (File.Exists(strAppExcel)) { using (System.IO.FileStream fs = new System.IO.FileStream(strAppExcel, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { wk = new HSSFWorkbook(fs); pSheet = wk.GetSheet("mysheet"); if (pSheet == null) { pSheet = wk.CreateSheet("mysheet"); } ///创建列标题 CreateHeader(pSheet, wk, new string[] { strTHField, strJHBAreaField }); } } else { using (System.IO.FileStream fs = new System.IO.FileStream(strAppExcel, FileMode.CreateNew, FileAccess.ReadWrite)) { wk = new HSSFWorkbook(); pSheet = wk.GetSheet("mysheet"); if (pSheet == null) { pSheet = wk.CreateSheet("mysheet"); } CreateHeader(pSheet, wk, new string[] { strTHField, strJHBAreaField }); } } //理论上iRowCount最后应该等于objJHBCol.Length int iRowCount = 0; ObjectIdCollection objJHBNameCol = GetObjectidsAtLayer(strJHBLayerTextName); ObjectIdCollection objJHBGeometryCol = GetObjectidsAtLayer(strJHBLayerGeometryName); List<DBText> allDBTextList = null; using (Transaction trans = acCurDb.TransactionManager.StartTransaction()) { foreach (ObjectId strJHBGeometryID in objJHBGeometryCol) { Entity jhbPolyline2dEntity = trans.GetObject(strJHBGeometryID, OpenMode.ForRead) as Entity; Point3dCollection pPoint3DCol = new Point3dCollection(); Polyline2d pJHBPolyline2d = jhbPolyline2dEntity as Polyline2d; if (pJHBPolyline2d != null) { foreach (ObjectId verId in pJHBPolyline2d) { Vertex2d ver2d = trans.GetObject(verId, OpenMode.ForRead) as Vertex2d; if (!pPoint3DCol.Contains(ver2d.Position)) { pPoint3DCol.Add(ver2d.Position); } } TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.LayerName, strJHBLayerTextName) }; SelectionFilter pSelectionFilter = new SelectionFilter(filList); PromptSelectionResult pPromptSelectionResult = ed.SelectCrossingPolygon(pPoint3DCol, pSelectionFilter); if (pPromptSelectionResult.Status == PromptStatus.OK) { SelectionSet pSelectionSet = pPromptSelectionResult.Value; ObjectId[] oids = pSelectionSet.GetObjectIds(); if (oids.Length == 1) { DBText pText = trans.GetObject(oids[0], OpenMode.ForRead) as DBText; if (pText != null) { int iRowIndex = GetTHRowIndexFromNOPIExcel(pText.TextString, pSheet); IRow pRow = null; if (iRowIndex == -1) { pRow = pSheet.CreateRow(++iRowCount); ed.WriteMessage("\n正在写入第" + iRowCount.ToString() + "个@@@单元名:" + pText.TextString + "@@@的面积"); } else { pRow = pSheet.GetRow(iRowIndex); ed.WriteMessage("\n正在写入第" + String.Format("{0}", iRowIndex) + "个@@@单元名:" + pText.TextString + "@@@的面积"); } ICell pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) : 0); pCell.SetCellValue(pText.TextString); pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) : 0); pCell.SetCellValue(pJHBPolyline2d.Area.ToString("f4")); } } else { if (allDBTextList == null) { allDBTextList = new List<DBText>(); foreach (ObjectId objJHBName in objJHBNameCol) { Entity jhbNameEntity = trans.GetObject(objJHBName, OpenMode.ForRead) as Entity; DBText everyDBText = jhbNameEntity as DBText; if (everyDBText != null) { allDBTextList.Add(everyDBText); } } } List<DBText> DaYu1DBTextList = GetDBTextInPolyline2D(allDBTextList, pPoint3DCol); if (DaYu1DBTextList.Count == 1) { foreach (DBText theRightDBText in DaYu1DBTextList) { int iRowIndex = GetTHRowIndexFromNOPIExcel(theRightDBText.TextString, pSheet); IRow pRow = null; if (iRowIndex == -1) { pRow = pSheet.CreateRow(++iRowCount); ed.WriteMessage("\n正在写入第" + iRowCount.ToString() + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } else { pRow = pSheet.GetRow(iRowIndex); ed.WriteMessage("\n正在写入第" + String.Format("{0}", iRowIndex) + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } ICell pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) : 0); pCell.SetCellValue(theRightDBText.TextString); pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) : 0); pCell.SetCellValue(pJHBPolyline2d.Area.ToString("f4")); } } else { //超过一个在多边形范围内 for (int i = 0; i < DaYu1DBTextList.Count; i++) { //如果文本的AlignmentPoint不在多边形范围内,则进行排除 if (!PointInPolygon(DaYu1DBTextList[i].AlignmentPoint, pPoint3DCol)) { DaYu1DBTextList.Remove(DaYu1DBTextList[i]); i--; } } if (DaYu1DBTextList.Count == 1) { foreach (DBText theRightDBText in DaYu1DBTextList) { int iRowIndex = GetTHRowIndexFromNOPIExcel(theRightDBText.TextString, pSheet); IRow pRow = null; if (iRowIndex == -1) { pRow = pSheet.CreateRow(++iRowCount); ed.WriteMessage("\n正在写入第" + iRowCount.ToString() + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } else { pRow = pSheet.GetRow(iRowIndex); ed.WriteMessage("\n正在写入第" + String.Format("{0}", iRowIndex) + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } ICell pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) : 0); pCell.SetCellValue(theRightDBText.TextString); pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) : 0); pCell.SetCellValue(pJHBPolyline2d.Area.ToString("f4")); } } } } } else { if (allDBTextList == null) { allDBTextList = new List<DBText>(); foreach (ObjectId objJHBName in objJHBNameCol) { Entity jhbNameEntity = trans.GetObject(objJHBName, OpenMode.ForRead) as Entity; DBText everyDBText = jhbNameEntity as DBText; if (everyDBText != null) { allDBTextList.Add(everyDBText); } } } List<DBText> reRightDBTextList = GetDBTextInPolyline2D(allDBTextList, pPoint3DCol); if (reRightDBTextList.Count == 1) { foreach (DBText theRightDBText in reRightDBTextList) { int iRowIndex = GetTHRowIndexFromNOPIExcel(theRightDBText.TextString, pSheet); IRow pRow = null; if (iRowIndex == -1) { pRow = pSheet.CreateRow(++iRowCount); ed.WriteMessage("\n正在写入第" + iRowCount.ToString() + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } else { pRow = pSheet.GetRow(iRowIndex); ed.WriteMessage("\n正在写入第" + String.Format("{0}", iRowIndex) + "个@@@单元名:" + theRightDBText.TextString + "@@@的面积"); } ICell pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strTHField, pSheet) : 0); pCell.SetCellValue(theRightDBText.TextString); pCell = pRow.CreateCell(GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) > -1 ? GetFieldColumnIndexFromNOPIExcel(strJHBAreaField, pSheet) : 0); pCell.SetCellValue(pJHBPolyline2d.Area.ToString("f4")); } } } } } trans.Commit(); ed.WriteMessage("处理完成:总共处理" + pSheet.PhysicalNumberOfRows.ToString() + "个单元;图号面积存储在" + strAppExcel); } using (System.IO.FileStream fs = File.OpenWrite(strAppExcel)) { wk.Write(fs); fs.Close(); } }
创建Excel表格列标题:
/// <summary> /// 创建列标题 /// </summary> /// <param name="pSheet"></param> /// <param name="wk"></param> public static void CreateHeader(ISheet pSheet, HSSFWorkbook wk, string[] strHeaderTextArray) { IRow pHeaderRow = null; //第一行一定是列标题 if (pSheet.PhysicalNumberOfRows > 1) { pHeaderRow = pSheet.GetRow(0); } else { pHeaderRow = pSheet.CreateRow(0); pHeaderRow.Height = 20 * 20; } //创建单元样式 ICellStyle cellStyle = wk.CreateCellStyle(); IFont font = wk.CreateFont(); font.FontHeightInPoints = 10; font.FontName = "微软雅黑"; cellStyle.Alignment = HorizontalAlignment.CENTER; cellStyle.SetFont(font); for (int i = 0; i < strHeaderTextArray.Length; i++) { //i表示该行第i列,从0开始算起 int iColumnIndex = GetFieldColumnIndexFromNOPIExcel(strHeaderTextArray[i], pSheet); if (iColumnIndex == -1) { ICell pHeaderCell = pHeaderRow.CreateCell(pHeaderRow.Cells.Count); pHeaderCell.CellStyle = cellStyle; pHeaderCell.SetCellValue(strHeaderTextArray[i]); } } }
获取某层下的所有实体
/// <summary> /// 获取某层下的所有对象ID /// </summary> /// <param name="name"></param> /// <returns></returns> public static ObjectIdCollection GetObjectidsAtLayer(string name) { ObjectIdCollection ids = new ObjectIdCollection(); TypedValue[] filList = new TypedValue[1] { new TypedValue((int)DxfCode.LayerName, name) }; SelectionFilter pSelectionFilter = new SelectionFilter(filList); Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; PromptSelectionResult pPromptSelectionResult = ed.SelectAll(pSelectionFilter); if (pPromptSelectionResult.Status == PromptStatus.OK) { SelectionSet pSelectionSet = pPromptSelectionResult.Value; ObjectId[] oids = pSelectionSet.GetObjectIds(); for (int i = 0; i < oids.Length; i++) { ids.Add(oids[i]); } } return ids; }
获取cad的所有图层
/// <summary> /// 遍历层名 /// </summary> /// <param name="db"></param> /// <returns></returns> public static ArrayList GetLayerName(Database db) { ArrayList layers = new ArrayList(); using (Transaction trans = db.TransactionManager.StartTransaction()) { using (LayerTable layerTable = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead)) { foreach (ObjectId id in layerTable) { LayerTableRecord lyrTableRecord = (LayerTableRecord)trans.GetObject(id, OpenMode.ForRead); layers.Add(lyrTableRecord.Name); } } trans.Commit(); } return layers; }
由于cad算法有限,判断点是否在多边形范围内
/// <summary> /// 判断点是否在点集所构成的多边形范围内 /// </summary> /// <param name="pPoint">点</param> /// <param name="pPointCol">多边形点集s</param> /// <returns></returns> public static bool PointInPolygon(Point3d pPoint, Point3dCollection pPointCol) { try { List<System.Drawing.PointF> pList = new List<System.Drawing.PointF>(); foreach (Point3d pPoint3d in pPointCol) { pList.Add(new System.Drawing.PointF(float.Parse(pPoint3d.X.ToString()), float.Parse(pPoint3d.Y.ToString()))); } System.Drawing.Drawing2D.GraphicsPath myGraphicsPath = new System.Drawing.Drawing2D.GraphicsPath(); System.Drawing.Region myRegion = new System.Drawing.Region(); myGraphicsPath.Reset(); myGraphicsPath.AddPolygon(pList.ToArray()); myRegion.MakeEmpty(); myRegion.Union(myGraphicsPath); return myRegion.IsVisible(new System.Drawing.PointF(float.Parse(pPoint.X.ToString()), float.Parse(pPoint.Y.ToString()))); } catch { return false; } }
获取某多边形范围内所有的文本集合
/// <summary> /// 返回文本图层在点集所对应的多边形范围内的文本集合 /// </summary> /// <param name="allDBTextList">所有的文本集合</param> /// <param name="pPointCol">点集所对应的多边形</param> /// <returns></returns> public static List<DBText> GetDBTextInPolyline2D(List<DBText> allDBTextList, Point3dCollection pPointCol) { List<DBText> listExistDBText = new List<DBText>(); foreach (DBText singleDBText in allDBTextList) { if (PointInPolygon(singleDBText.Position, pPointCol)) { if (!listExistDBText.Contains(singleDBText)) { listExistDBText.Add(singleDBText); } } } return listExistDBText; }
查找Excel表是否存在图名
/// <summary> /// 判断图号在Excel表中是否存在.-1表示不存在,如果存在则返回行索引 /// </summary> /// <param name="strTH"></param> /// <param name="pSheet"></param> /// <returns></returns> public static int GetTHRowIndexFromNOPIExcel(string strTH, ISheet pSheet) { int iResult = -1; for (int i = 0; i < pSheet.PhysicalNumberOfRows; i++) { IRow pRow = pSheet.GetRow(i); foreach (ICell pCell in pRow.Cells) { if (pCell.CellType != NPOI.SS.UserModel.CellType.FORMULA) { if (pCell.StringCellValue.Equals(strTH, StringComparison.CurrentCultureIgnoreCase)) { iResult = pRow.RowNum; break; } } } if (iResult != -1) { break; } } return iResult; }
返回某个字段所在单元格的列索引,-1表示未找到,否则则返回索引
/// <summary> /// 返回某个字段所在单元格的列索引,-1表示未找到,否则则返回索引 /// </summary> /// <param name="strField"></param> /// <param name="pSheet"></param> /// <returns></returns> public static int GetFieldColumnIndexFromNOPIExcel(string strHeaderField, ISheet pSheet) { int iResult = -1; if (pSheet.PhysicalNumberOfRows >= 1) { IRow pRow = pSheet.GetRow(0); foreach (ICell pCell in pRow.Cells) { if (pCell.StringCellValue.Equals(strHeaderField, StringComparison.CurrentCultureIgnoreCase)) { iResult = pCell.ColumnIndex; break; } } } return iResult; }