AutoCAD按坐标打印图纸

时间:2021-09-07 18:07:38

前几天公司要求按坐标打印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.SheetSetProgre*tion,
"Sheet Set Progress"); acPlProgDlg.set_PlotMsgString(PlotMessageIndex.SheetProgre*tion,
"正在生成" + 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;
}

先写这么多了,欢迎交流吐槽,