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值越小,繪圖次序越靠后(為什么這里不直接設計成long而一定要用handle呢)
那么我們只需要獲取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傳入了克隆函數即可
完

浙公網安備 33010602011771號