很长时间没有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 = "
选择块";
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("
点取表格插入点");
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("
" + x.Key);
//ed.WriteMessage(" 数量为:" + 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("
" + 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;
}
}
}
}
结果如下:
