LINQ还是很方便的
很长时间没有LINQ了,
除了知道LINQ外,
基本上都忘了。
昨天快下班时,
一个项目要统计图中的图块(BlockReference)数量及位置信息,
开始还想自己写排序及分组的代码,
忽然想到可以使用LINQ,
这使得代码简单了很多很多。
//使用LINQ排序、分组 var group = from blk in blks orderby blk.Name,blk.Position.X,blk.Position.Y,blk.Position.Z group blk by blk.Name;
完整代码如下:
大部分代码是插入AutoCAD表格的,
如果把信息输出到命令行,
代码会少很多。
表格的列宽,
我是统计每一列文本的长度得出的,
所以代码显得复杂了些。
using System; using System.Collections.Generic; using System.Linq; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.Civil.ApplicationServices; namespace ModelingTools { class BlockStatics { Document doc; Editor ed; double textHeigt = 2.5;//文本高度 double xScale = 1; //文本宽度系数 double obliquingAngle = 0;//文本倾角 double nameColumWidth = 15;//用于名称那一列的宽度,第1种列宽 double lengthColumWidth1 = 10; //第2种列宽 double lengthColumWidth2 = 10; //第3种列宽 ObjectId textStyleId;//文本样式Id public void Statics() { doc = Application.DocumentManager.MdiActiveDocument; ed = doc.Editor; //文本样式相关的 using (Transaction tr = doc.TransactionManager.StartTransaction()) { SymbolTable symTable = (SymbolTable)tr.GetObject( doc.Database.TextStyleTableId, OpenMode.ForRead); textStyleId = symTable["Standard"]; var textStyle = textStyleId.GetObject(OpenMode.ForRead) as TextStyleTableRecord; xScale = textStyle.XScale; obliquingAngle = textStyle.ObliquingAngle; tr.Commit(); } //选择要统计的块 //这里用过设置过滤器,我的图里没有对象,所以给省略了 PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n选择块"; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; //拾取表格插入点 //创建表格 Autodesk.AutoCAD.DatabaseServices.Table table = new Autodesk.AutoCAD.DatabaseServices.Table(); //设置表格样式 table.SetSize(2, 5); table.Cells.TextHeight = textHeigt; table.Rows[0].Height = textHeigt * 3; table.Rows[0].TextHeight = textHeigt + 1; table.Rows[1].Height = textHeigt * 2; table.Rows[1].TextHeight = textHeigt + 0.5; //表格名称 table.Cells[0, 0].TextString = "主要乔木统计表"; table.Rows[0].Borders.Top.IsVisible = false; table.Rows[0].Borders.Left.IsVisible = false; table.Rows[0].Borders.Right.IsVisible = false; //标题行 table.Cells[1, 0].TextString = "名称"; table.Cells[1, 1].TextString = "X"; table.Cells[1, 2].TextString = "Y"; table.Cells[1, 3].TextString = "Z"; table.Cells[1, 4].TextString = "数量"; //拾取表格插入点 // PromptPointResult pr = ed.GetPoint("\n点取表格插入点"); if (pr.Status == PromptStatus.OK) { table.Position = pr.Value; } else { return; } //获取块对象集合 List<BlockReference> blks = new List<BlockReference>(); using (Transaction tr = doc.TransactionManager.StartTransaction()) { foreach (ObjectId id in psr.Value.GetObjectIds()) { var block = id.GetObject(OpenMode.ForRead) as BlockReference; if (block != null) { blks.Add(block); } } tr.Commit(); } //使用LINQ排序、分组 var group = from blk in blks orderby blk.Name,blk.Position.X,blk.Position.Y,blk.Position.Z group blk by blk.Name; Array.ForEach(group.ToArray(), x => { //添加树种的信息:名称,数量 //ed.WriteMessage("\n" + x.Key); //ed.WriteMessage("\t数量为:" + x.Count()); table.InsertRows(table.Rows.Count, textHeigt * 2, 1); int rn = table.Rows.Count - 1; table.Rows[rn].TextHeight = 2.5; //单元格内输入名称 table.Cells[rn, 0].TextString = x.Key; table.Cells[rn, 0].Alignment = CellAlignment.MiddleLeft; table.Cells[rn, 0].Borders.Horizontal.Margin = 2; nameColumWidth = Math.Max(nameColumWidth, GetTextLength(x.Key, textHeigt)); //单元格内输入数量 table.Cells[rn, 4].TextString = x.Count().ToString("f0"); lengthColumWidth2 = Math.Max(lengthColumWidth2, GetTextLength(x.Count().ToString("f0"), textHeigt)); table.Cells[rn, 4].Alignment = CellAlignment.MiddleRight; table.Cells[rn, 4].Borders.Horizontal.Margin = 2; Array.ForEach(x.ToArray(), y => { //添加每棵树的位置信息,X,Y,Z //ed.WriteMessage("\n\t" + y.Position.ToString()); table.InsertRows(table.Rows.Count, textHeigt * 2, 1); rn = table.Rows.Count - 1; table.Rows[rn].TextHeight = 2.5; //单元格内输入坐标X string coorX = y.Position.X.ToString("f2"); table.Cells[rn, 1].TextString = coorX; lengthColumWidth1 = Math.Max(lengthColumWidth1, GetTextLength(coorX, textHeigt)); table.Cells[rn, 1].Alignment = CellAlignment.MiddleRight; table.Cells[rn, 1].Borders.Horizontal.Margin = 2; //单元格内输入坐标Y string coorY =y.Position.Y.ToString("f2"); table.Cells[rn, 2].TextString = coorY; lengthColumWidth1 = Math.Max(lengthColumWidth1, GetTextLength(coorY, textHeigt)); table.Cells[rn, 2].Alignment = CellAlignment.MiddleRight; table.Cells[rn, 2].Borders.Horizontal.Margin = 2; //单元格内输入坐标Z string coorZ = y.Position.Z.ToString("f2"); table.Cells[rn, 3].TextString = coorZ; lengthColumWidth1 = Math.Max(lengthColumWidth1, GetTextLength(coorZ, textHeigt)); table.Cells[rn, 3].Alignment = CellAlignment.MiddleRight; table.Cells[rn, 3].Borders.Horizontal.Margin = 2; }); }); using (Transaction tr = doc.TransactionManager.StartTransaction()) { ///设置表格文本样式 table.Cells.TextStyleId = textStyleId; ///设置表格列宽 table.Columns[0].Width = nameColumWidth + 6; table.Columns[1].Width = lengthColumWidth1 + 6; table.Columns[2].Width = lengthColumWidth1 + 6; table.Columns[3].Width = lengthColumWidth1 + 6; table.Columns[4].Width = lengthColumWidth2 + 6; BlockTable bt = (BlockTable)tr.GetObject(Autodesk.AutoCAD .ApplicationServices.Application.DocumentManager .MdiActiveDocument.Database.BlockTableId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject( bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); btr.AppendEntity(table); tr.AddNewlyCreatedDBObject(table, true); tr.Commit(); } } //获取文本长度,用来设置表格列宽 //对中文貌似不太灵 double GetTextLength(string str, double height) { if (str == "" || str == null) { return 0; } else { DBText tmp = new DBText(); tmp.TextStyleId = textStyleId; tmp.WidthFactor = xScale; tmp.Oblique = obliquingAngle; tmp.TextString = str; tmp.Height = height; var ext = tmp.GeometricExtents; return ext.MaxPoint.X - ext.MinPoint.X; } } } }
结果如下: