最近要做一個cad檔案的7參數坐标轉換的程式,想基于cad進行二次開發,初次學習。
為了友善快捷開發,基于cad.net進行二次開發,網上查了很多資料,有基于acad等各種,總是遇到這樣那樣的問題,經過自己研究,最終選擇了直接開發指令的方式進行開發,但有時候還是用到acad相關函數,比如将Docmuent轉換為AcadDocument進行相關操作等
( Autodesk.AutoCAD.Interop.AcadDocument acadDoc = adoc.GetAcadDocument() as Autodesk.AutoCAD.Interop.AcadDocument;
acadDoc.SendCommand("zoom e\n");
)。
如果直接用document的SendStringToExecute執行cad指令,由于是異步的,需要等到動态庫執行完成才執行指令,不滿足我的要求,是以,轉換為acad文檔進行同步指令執行。
1、開發環境搭建
(1)vs版本:vs2015
(2)cad版本:cad2018
(3)cad.net開發包(2個,objectarx庫和.net庫):Autodesk_ObjectARX_2018_Win_64_and_32_Bit.sfx.exe,AutoCAD_2018_dotnet_wizards。
開發包可以網上找,也可以官網下載下傳,官網位址為:
https://www.autodesk.com/developer-network/platform-technologies/autocad。
官網.net下載下傳如下圖(objectarx貌似需要注冊才能下載下傳,我是網上下載下傳的,由于網上找的.net庫老是不行,是以通過官網下載下傳):
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL90zdjBHZXV2a1clWv50MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3EDOwQDNzgDM5AjNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
逐次安裝以上軟體,就可以進行開發了。
2、開發入門
安裝完成後,打開vs,就可以建立cad.net的開發了。
在vs中建立項目,選擇cad模闆,如下圖所示:
安裝完cad.net才能在模闆中選擇autocad 2018 plugin in,.net架構選擇4.6,完成後,就建立了一個cad插件程式。
建立完成後,主要有兩個檔案:
myCommands.cs寫指令,myPlugin.cs設定插件相關資訊。
(1)插件初始化(myPlugin.cs)
比如,我要在插件初始化時檢查實際,并在完成後提示插件加載成功等消息,在myPlugin.cs的初始化函數void IExtensionApplication.Initialize()中添加如下代碼:
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
MyCommands.isLinced = checkTime(2020, 7, 7);
if (MyCommands.isLinced)
{
ed.WriteMessage("\n加載 坐标轉換成功!\n坐标轉換指令:\n ZBSH\n\n\n");
load();
}
else
{
ed.WriteMessage("\n加載 坐标轉換 失敗!\n時間過期!!!!!!\n");
}
其中checkTime函數是我自己寫的時間許可,檢查完後根據需要提示相關資訊。
void IExtensionApplication.Terminate()函數為插件退出執行的函數。
(2)指令編寫(myCommands.cs)
在myCommands.cs中加入一個指令,比如建立dwg指令,
[CommandMethod("NewDwg", CommandFlags.Modal)]
public void NewDwg()
{
string tmppath = "acad.dwt";
DocumentCollection dcol = Application.DocumentManager;
Document adoc = dcol.Add(tmppath);
dcol.MdiActiveDocument = adoc;
}
這樣在cad中輸入“newdwg”指令即可實作建立dwg功能。
(3)執行指令
調試狀态下直接F5運作程式(Debug模式),即可調試(通過cad模闆建立的項目,已經将調試裡面的啟動外部程式設定為cad執行程式了,是以不需要自己設定)。
編譯完成後,自動打開cad程式。
在cad中輸入指令“netload”(每次啟動都需要輸入該指令,全局設定請百度),
選擇生成目錄下的dll檔案,可顯示資訊,如下圖所示:
然後輸入“newdwg”指令,即可建立一個dwg檔案。
部署時,通過release編譯,加載方式也是一樣,打開cad程式,先執行“netload”指令,加載dll檔案,然後就可以輸入相關指令了。
3、7參數坐标轉換
我自己做了一個窗體,選擇控制點進行坐标轉換(具體轉換程式百度)。
[CommandMethod("sh", "zbsh", "zbsh", CommandFlags.Modal | CommandFlags.UsePickSet)]
public void MyCommand() // This method can have any name
{
// Put your command code here
if (!checkLince())
{
return;
}
frmZBZH frm = new frmZBZH();
System.Windows.Forms.IWin32Window w = System.Windows.Forms.Form.FromHandle(Application.MainWindow.Handle);
frm.Show(w);
}
寫轉換代碼就和.net寫是一樣的了。
private void transFromOneFile(string dwgFile, Transform7CSH tf, ref List<string> allNotSupported, bool onlyMove = false)
{
if (null == allNotSupported)
{
allNotSupported = new List<string>();
}
Autodesk.AutoCAD.ApplicationServices.DocumentCollection dcol = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
Autodesk.AutoCAD.ApplicationServices.Document adoc = dcol.Open(dwgFile, false);
//dcol.MdiActiveDocument = adoc;
//dcol.MdiActiveDocument = adoc;
//dcol.MdiActiveDocument.LockDocument();
adoc.LockDocument();//必須鎖定,否則 acTrans.GetObject利用OpenMode.ForWrite會出錯
// adoc = dcol.MdiActiveDocument;
Database acCurDb = adoc.Database;
using (Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
{
// Open the Block table for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;
// Open the Block table record Model space for write
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;
List<string> notSupported = new List<string>();
foreach (ObjectId asObjId in acBlkTblRec)
{
DBObject obj = acTrans.GetObject(asObjId, OpenMode.ForWrite);
bool ok = transformEntity(obj, acTrans, tf, onlyMove);
if (false == ok)
{
string strobj = obj.ToString();
if (false == notSupported.Contains(strobj))
{
notSupported.Add(strobj);
}
if (false == allNotSupported.Contains(strobj))
{
allNotSupported.Add(strobj);
}
}
}
if (notSupported.Count > 0)
{
txtmsg.AppendText(string.Format("檔案\"{0}\"不支援的格式:\n", dwgFile));
txtmsg.AppendText(string.Join(";\n", notSupported));
txtmsg.AppendText("\n");
}
// Commit the changes and dispose of the transaction
acTrans.Commit();
}
// 縮放到視圖,用這個才是同步執行
//Autodesk.AutoCAD.Interop.AcadApplication app = Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication as Autodesk.AutoCAD.Interop.AcadApplication;
//app.ActiveDocument.SendCommand("zoom e\n");
Autodesk.AutoCAD.Interop.AcadDocument acadDoc = adoc.GetAcadDocument() as Autodesk.AutoCAD.Interop.AcadDocument;
acadDoc.SendCommand("zoom e\n");
// adoc.SendStringToExecute("\003\003zoom\ne\n", false, true, true);//異步執行,需要等到執行完後才執行該指令
// 關閉
if (chkCloseDealedFile.Checked)
{
//adoc.SendStringToExecute("e\n", false, true, true);
adoc.CloseAndSave(adoc.Database.Filename);
adoc.Dispose();
acCurDb.Dispose();
}
}
其中transformEntity()函數,實作實體的坐标轉換。
Transform7CSH類是我寫的7參數轉換的類。
運作界面如下圖所示: