前几天公司要求按坐标打印DWG文件,中间走了不少弯路,好在已经搞定了,整理一下分享给大家,希望后来人少走弯路。
1. 设计需求:
公司的图纸用AutoCAD2010做成,通常一个项目的所有图纸都存放在一个DWG文件内,根据具体的子项不同,放在不同的块引用里,我要做的是找到每一个块引用,并把他打印到bmp文件里。
2.实现思路:
利用AutoCAD的.net API,找到符合条件的快引用,得到块引用左下角和右上角的点的坐标,把两点坐标框选的矩形区域发给打印机打印
3.遇到的问题
有的图纸打印没有问题,有的图纸打印出一张空白图。
4.解决问题(在这里向业界大牛Kean同志表示强烈的感谢,感谢他无私的帮助)
之所以有些图纸打印出白图是因为坐标体系的问题,AutoCAD中有很多种坐标体系,例如UCS世界坐标,DCS显示设备坐标,UCS用户坐标等等,除了UCS坐标其他各坐标体系都是UCS坐标推衍而来,UCS坐标是永远不变的。.net API取出的块引用坐标是UCS,而要向打印机输出坐标打印命令需要用DCS坐标。也就是说不把UCS转换为DCS,图纸就会打印出白图,碰巧打印出来的是因为UCS和DCS重合。
很遗憾,AutoCAD .net API并没有转换坐标的函数,幸运的是ObjectARX 中有acedTrans()函数,于是先要把此函数引入我们自己的工程,加入如下代码
public partial class BlockSelectForm : Form { [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans") ] static extern int acedTrans( double[] point, IntPtr fromRb, IntPtr toRb, int disp, double[] result ); ....
private Extents2d Ucs2Dcs(Point3d objStart,Point3d objEnd) { ResultBuffer rbFrom = new ResultBuffer(new TypedValue(5003, 1)), rbTo = new ResultBuffer(new TypedValue(5003, 2)); double[] firres = new double[] { 0, 0, 0 }; double[] secres = new double[] { 0, 0, 0 };
acedTrans( objStart.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, firres ); acedTrans( objEnd.ToArray(), rbFrom.UnmanagedObject, rbTo.UnmanagedObject, 0, secres ); Extents2d window = new Extents2d( firres[0], firres[1], secres[0], secres[1] ); return window; }
下面是打印函数代码
private string PrintBMP(Point3d objStart, Point3d objEnd, string strPrintName, string strPaperName, string strStyleName, string strRotation) { // 打开文档数据库 Document acDoc =Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; Extents2d objPoint = Ucs2Dcs(objStart, objEnd); string strFileName = string.Empty; using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)acTrans.GetObject( acCurDb.CurrentSpaceId, OpenMode.ForRead ); Layout acLayout = (Layout)acTrans.GetObject( btr.LayoutId, OpenMode.ForRead ); // Get the PlotInfo from the layout PlotInfo acPlInfo = new PlotInfo(); acPlInfo.Layout = btr.LayoutId; // Get a copy of the PlotSettings from the layout PlotSettings acPlSet = new PlotSettings(acLayout.ModelType); acPlSet.CopyFrom(acLayout); // Update the PlotSettings object PlotSettingsValidator acPlSetVdr = PlotSettingsValidator.Current; acPlSetVdr.SetPlotWindowArea(acPlSet, objPoint); // Set the plot type acPlSetVdr.SetPlotType(acPlSet, Autodesk.AutoCAD.DatabaseServices.PlotType.Window); // Set the plot scale acPlSetVdr.SetUseStandardScale(acPlSet, true); acPlSetVdr.SetStdScaleType(acPlSet, StdScaleType.ScaleToFit); // Center the plot acPlSetVdr.SetPlotCentered(acPlSet, true); // Set the plot device to use acPlSetVdr.SetPlotConfigurationName(acPlSet, strPrintName, strPaperName); acPlSetVdr.RefreshLists(acPlSet); acPlSetVdr.SetCurrentStyleSheet(acPlSet, strStyleName); switch (strRotation) { case "0": acPlSetVdr.SetPlotRotation(acPlSet,PlotRotation.Degrees000); break; case "90": acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees090); break; case "180": acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees180); break; case "270": acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees270); break; } // Set the plot info as an override since it will // not be saved back to the layout acPlInfo.OverrideSettings = acPlSet; // Validate the plot info PlotInfoValidator acPlInfoVdr = new PlotInfoValidator(); acPlInfoVdr.MediaMatchingPolicy = MatchingPolicy.MatchEnabled; acPlInfoVdr.Validate(acPlInfo); // Check to see if a plot is already in progress if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting) { using (PlotEngine acPlEng = PlotFactory.CreatePublishEngine()) { // Track the plot progress with a Progress dialog PlotProgressDialog acPlProgDlg = new PlotProgressDialog(false, 1, false); using (acPlProgDlg) { // Define the status messages to display when plotting starts acPlProgDlg.set_PlotMsgString(PlotMessageIndex.DialogTitle, "我们公司名,隐去了"); acPlProgDlg.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job"); acPlProgDlg.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet"); acPlProgDlg.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet Set Progress"); acPlProgDlg.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "正在生成" + acDoc.Name); // Set the plot progress range acPlProgDlg.LowerPlotProgressRange = 0; acPlProgDlg.UpperPlotProgressRange = 100; acPlProgDlg.PlotProgressPos = 0; // Display the Progress dialog acPlProgDlg.OnBeginPlot(); acPlProgDlg.IsVisible = true; // Start to plot the layout acPlEng.BeginPlot(acPlProgDlg, null); string strTempPath = System.IO.Path.GetTempPath(); strFileName = Path.Combine(strTempPath, acDoc.Name.Substring(acDoc.Name.LastIndexOf("\")+1).Replace("dwg","") + DateTime.Now.ToString("yyyyMMddhhmmssfff") + "Compare" + ".bmp"); // Define the plot output acPlEng.BeginDocument(acPlInfo, acDoc.Name, null, 1, true, strFileName); // Display information about the current plot acPlProgDlg.set_PlotMsgString(PlotMessageIndex.Status, "Plotting: " + acDoc.Name + " - " + acLayout.LayoutName); // Set the sheet progress range acPlProgDlg.OnBeginSheet(); acPlProgDlg.LowerSheetProgressRange = 0; acPlProgDlg.UpperSheetProgressRange = 100; acPlProgDlg.SheetProgressPos = 0; // Plot the first sheet/layout PlotPageInfo acPlPageInfo = new PlotPageInfo(); acPlEng.BeginPage(acPlPageInfo, acPlInfo, true, null); acPlEng.BeginGenerateGraphics(null); acPlEng.EndGenerateGraphics(null); // Finish plotting the sheet/layout acPlEng.EndPage(null); acPlProgDlg.SheetProgressPos = 100; acPlProgDlg.OnEndSheet(); // Finish plotting the document acPlEng.EndDocument(null); // Finish the plot acPlProgDlg.PlotProgressPos = 100; acPlProgDlg.OnEndPlot(); acPlEng.EndPlot(null); } } } } return strFileName; }
先写这么多了,欢迎交流吐槽,