cad.net 图元做块后保留绘图次序
今天水友在群里提出一个问题,选中一部分对象,做成块后,绘图次序发生了变化,如何保留原来的绘图次序。
这是一个十分有用的问题,以前从未考虑过,于是我研究了一下
1.验证
我先后在cad中创建了3条多段线(多段线设置宽度后可以很方便的看到绘图次序),这里命名为1、2、3,
然后我写了一个较为简单的做块代码,不考虑基点位置,代码如下
using var tr = new DBTrans();
var objectIdList = tr.CurrentSpace.OfType<ObjectId>().ToList();
if (objectIdList.Count == 0)
return;
var drt = (DrawOrderTable)tr.CurrentSpace.DrawOrderTableId.GetObject(OpenMode.ForRead);
var btrId = tr.BlockTable.Add("*U", btr => { btr.DeepCloneEx(objectIdList.ToCollection()); });
tr.CurrentSpace.InsertBlock(Point3d.Origin, btrId);
foreach (var ent in objectIdList.GetObject<Entity>(OpenMode.ForWrite))
{
ent.Erase();
}
此段代码使用了ifox,但我相信大家都能看懂它的主要逻辑,即拿到当前空间所有对象,克隆到一个新的块表记录中,然后做成块参照插入图纸中,然后将原来的图元删除
由于是测试使用所以此处未考虑锁定图层等问题。
经过测试我发现,无论我如何调整原图的顺序,块内对象绘图次序从最后到最前都是1->2->3
2.猜想
于是我猜想,新块表记录中的绘图次序应该与克隆的ObjectIdCollection中id的排列顺序一致,实际上从平时我们画图的时候,后画的对象总是在先画的对象上面,就可以判断出来
3.解决方案
那么既然克隆后的绘图次序,与ObjectIdCollection中id的排列顺序一致,那么我们只需要在克隆前对ObjectIdCollection中id按照绘图次序从后到前的顺序对id进行排序,就可以实现保留原来绘图次序的目的。
那么如何获得原来的绘图次序呢?
经查阅官方文档DrawOrderTable.GetSortHandle()(id)方法,可以获得一个handle,此handle并不对应数据库中的图元,仅使用其value值,value值越小,绘图次序越靠后
那么我们只需要获取id对应的此value值,然后按从小到大的顺序排序,再克隆即可
修改后的代码如下
using var tr = new DBTrans();
var objectIdList = tr.CurrentSpace.OfType<ObjectId>().ToList();
if (objectIdList.Count == 0)
return;
var drt = (DrawOrderTable)tr.CurrentSpace.DrawOrderTableId.GetObject(OpenMode.ForRead);
var objectIdCollection = objectIdList.OrderBy(id => drt.GetSortHandle(id).Value).ToCollection();
var btrId = tr.BlockTable.Add("*U", btr => { btr.DeepCloneEx(objectIdCollection); });
tr.CurrentSpace.InsertBlock(Point3d.Origin, btrId);
foreach (var ent in objectIdList.GetObject<Entity>(OpenMode.ForWrite))
{
ent.Erase();
}
增加了一行linq排序,并将排序后的ObjectIdCollection传入了克隆函数即可
完