1. 需求分析
有时候我们可能需要为CAD用户提供这样的功能:
- 用户可以连续点击多个点,然后我们自动为用户绘制多段线。
- 用户可以点击多个点,然后在这些点位置自动绘制图形。
- 同时需要删除和直线,图形有相交的块BlockReference。
这两个功能怎么实现呢 ?
自动绘制多段线
实现思路:
- 提示用户选中需要操作的整个区域图形
- 利用选择集筛选出当前区域内块参照所在图层的所有块。
- 新建多段线图层。
- 开始循环让用户绘制多个多段线。
- 再在每个多段线中,递归执行,拾取用户的点操作(PromptPointOptions)。
- 把用户的点集合进行分析,进行排序,找出最短路径的连接方式。
- 再在指定的图层上进行多段线绘制。
- 再利用CAD的相交(IntersectWith)API来判断多段线和哪些块参照有交点。
- 删除掉这些相交的块参照即可。
代码如下:
/// <summary>
///
/// </summary>
[CommandMethod("DL")]
public void AddRoad()
{
string layer = CommonConstant.PHALANX_DIVISION_LAYER;
var doc = Application.DocumentManager.MdiActiveDocument;
Editor editor = doc.Editor;
Database db = doc.Database;
TypedValue[] tv = {
// 筛选出所有块参照
new TypedValue((int)DxfCode.Start, "INSERT"),
// 块参照所在图层
new TypedValue((int)DxfCode.LayerName, layer)
};
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult psr = editor.GetSelection(sf);
if (psr.Status == PromptStatus.OK)
{
//获取所有选中的块
SelectionSet ss = psr.Value;
editor.WriteMessage("\n所选块总数:{0}", ss.Count);
List<BlockReference> blockReferences = new List<BlockReference>();
using (Transaction ts = db.TransactionManager.StartTransaction())
{
foreach (SelectedObject so in ss)
{
BlockReference en = so.ObjectId.GetObject(OpenMode.ForWrite) as BlockReference;
blockReferences.Add(en);
}
ts.Commit();
}
//新建图层
AddLayerResult addLayerResult = LayerTool.AddLayer(db, CommonConstant.ROAD_LAYER);
int roadNumber = 1;
bool isContinue = true;
while (isContinue)
{
int nodeNumber = 1;
PromptPointOptions ppo = new PromptPointOptions("\n开始绘制第"+roadNumber+"条多段线的第"+nodeNumber+"个节点的坐标:");
PromptPointResult pointResult = editor.GetPoint(ppo);
List<Point3d> roadNodes = new List<Point3d>();
if (pointResult.Status == PromptStatus.OK)
{
roadNodes.Add(pointResult.Value);
roadService.UserInteraction(roadNodes,roadNumber, nodeNumber, editor);
roadService.AddRoad(blockReferences,roadNodes,addLayerResult.layerName);
}
else
{
isContinue = false;
}
roadNumber += 1;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="roadNodes">多段线节点集合</param>
/// <param name="roadNumber">第几条多段线</param>
/// <param name="nodeNumber">节点个数</param>
/// <param name="editor"></param>
public void UserInteraction(List<Point3d> roadNodes,int roadNumber,int nodeNumber,Editor editor)
{
nodeNumber += 1;
PromptPointOptions ppo = new PromptPointOptions("\n请选择第"+roadNumber+"条多段线的第"+nodeNumber+"个节点的坐标:");
PromptPointResult pointResult = editor.GetPoint(ppo);
var point3d = pointResult.Value;
if (pointResult.Status == PromptStatus.OK)
{
roadNodes.Add(point3d);
UserInteraction(roadNodes,roadNumber,nodeNumber,editor);
}
}
/// <summary>
///
/// </summary>
/// <param name="blockReferences"></param>
/// <param name="roadNodes"></param>
/// <param name="layerName"></param>
public void AddRoad(List<BlockReference> blockReferences,List<Point3d> roadNodes,string layerName)
{
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
if (blockReferences.Count > 0)
{
//找出最短路径连接方式
roadNodes = PolylineTool.ShortPathRank(roadNodes);
List<Point2d> points2D = roadNodes.Select(p => new Point2d(p.X, p.Y)).ToList();
//多段线绘制
ObjectId objectId = db.AddPolyLineToModelSpace(false, 10,layerName, points2D.ToArray());
//删除和多段线相交的块
DBObject dbObj = tr.GetObject(objectId, OpenMode.ForWrite);
if (dbObj is Polyline)
{
Polyline polyline = (Polyline)dbObj;
//相交
List<Point3d> point3ds = new List<Point3d>();
for (var i = 0; i < blockReferences.Count; i++)
{
var intersectWithResult = new Point3dCollection();
polyline.IntersectWith(blockReferences[i], Intersect.OnBothOperands, intersectWithResult, IntPtr.Zero, IntPtr.Zero);
if (intersectWithResult.Count > 0)
{
point3ds.Add(blockReferences[i].Position);
}
}
BlockTool.DeleteBlockRefByBlockName(db,CommonConstant.BRACKET_BLOCK_NAME,point3ds);
}
}
tr.Commit();
}
}
里面有一些图层操作的工具方法(LayerTool),多段线的工具方法(PolylineTool)后续会给大家分享出来,块删除的方法其实上篇文章已经分享了。
效果如下:
指定点位置自动绘制图形
[CommandMethod("PS")]
public void AddTransformer()
{
string layer = CommonConstant.PHALANX_DIVISION_LAYER;
var doc = Application.DocumentManager.MdiActiveDocument;
Editor editor = doc.Editor;
Database db = doc.Database;
TypedValue[] tv = {
// 筛选出所有块
new TypedValue((int)DxfCode.Start, "INSERT"),
// 筛选出块所在图层
new TypedValue((int)DxfCode.LayerName, layer)
};
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult psr = editor.GetSelection(sf);
if (psr.Status == PromptStatus.OK)
{
//获取所有选中的块
SelectionSet ss = psr.Value;
editor.WriteMessage("\n所选块总数:{0}", ss.Count);
List<BlockReference> blockReferences = new List<BlockReference>();
using (Transaction ts = db.TransactionManager.StartTransaction())
{
foreach (SelectedObject so in ss)
{
BlockReference en = so.ObjectId.GetObject(OpenMode.ForWrite) as BlockReference;
blockReferences.Add(en);
}
ts.Commit();
}
//新建图层
AddLayerResult addLayerResult = LayerTool.AddLayer(db, CommonConstant.TRANSFORMER_LAYER);
electricService.AddTransformer(blockReferences,addLayerResult,doc);
}
}
/// <summary>
/// 获取位置
/// </summary>
/// <param name="blockReferences"></param>
/// <param name="roadList"></param>
public void AddTransformer(List<BlockReference> blockReferences, AddLayerResult addLayerResult,Document doc)
{
if (blockReferences.Count > 0)
{
Editor editor = doc.Editor;
Database db = doc.Database;
//根据颜色分组
var blockReferencesMap = blockReferences.GroupBy(reference => reference.Color)
.ToDictionary(group => group.Key,
group => group.ToList());
var number = blockReferencesMap.Count;
List<Point3d> transformerNodes = new List<Point3d>();
while (number>0)
{
PromptPointOptions ppo = new PromptPointOptions("\n选中第"+number+"个箱变位置");
PromptPointResult pointResult = editor.GetPoint(ppo);
if (pointResult.Status == PromptStatus.OK)
{
transformerNodes.Add(pointResult.Value);
}
number -= 1;
}
foreach (var transformer in transformerNodes)
{
Dictionary<string, double> dictionary = BlockTool.getBlockMaxBlock(db,blockReferences[0]);
ObjectId objectId = db.AddPolygonToModelSpace(new Point2d(transformer.X,transformer.Y),dictionary["maxXSpacing"]/2,5,90,addLayerResult.layerName);
using (Transaction tr = doc.TransactionManager.StartTransaction())
{
DBObject dbObj = tr.GetObject(objectId, OpenMode.ForWrite);
if (dbObj is Polyline)
{
Polyline polyline = (Polyline)dbObj;
//相交
List<Point3d> point3ds = new List<Point3d>();
for (var i = 0; i < blockReferences.Count; i++)
{
var intersectWithResult = new Point3dCollection();
polyline.IntersectWith(blockReferences[i], Intersect.OnBothOperands, intersectWithResult, IntPtr.Zero, IntPtr.Zero);
if (intersectWithResult.Count > 0)
{
point3ds.Add(blockReferences[i].Position);
}
}
if (point3ds.Count > 0)
{
//清理周边相交块
BlockTool.DeleteBlockRefByBlockName(db,CommonConstant.BRACKET_BLOCK_NAME,point3ds);
}
//添加文字
TextTool.AddText(db, "PS", new Point2d(transformer.X,transformer.Y), dictionary["maxYSpacing"],addLayerResult.layerName);
}
tr.Commit();
}
}
}
}
效果如下: