Driving a basic AutoCAD plot using .NET

AutoCAD .NET API绘图示例
本文提供了一个使用AutoCAD .NET API进行简单绘图的C#代码示例,该示例展示了如何设置绘图配置、创建绘图进度对话框及执行绘图过程。
I just missed my connecting flight in Chicago, so have 3 hours to pass until the next, and decided to post some code I finally got around to writing on the plane from Zurich.

I've had a few requests for code showing how to plot using the .NET API in AutoCAD. There's an existing ObjectARX (C++) sample on the SDK, under samples/editor/AsdkPlotAPI, but there isn't a publicly posted .NET version right now.

Here's the C# code I put together. Please bear in mind that it was written during less than ideal coding conditions, and I haven't spent a substantial amount of time going through it... it seems to work fine for me, but do post a comment if you have trouble with it.

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.PlottingServices;


namespace PlottingApplication

{

  public class PlottingCommands

  {

    [CommandMethod("simplot")]

    static public void SimplePlot()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      Database db = doc.Database;


      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        // We'll be plotting the current layout


        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            db.CurrentSpaceId,

            OpenMode.ForRead

          );

        Layout lo =

          (Layout)tr.GetObject(

            btr.LayoutId,

            OpenMode.ForRead

          );


        // We need a PlotInfo object

        // linked to the layout


        PlotInfo pi = new PlotInfo();

        pi.Layout = btr.LayoutId;


        // We need a PlotSettings object

        // based on the layout settings

        // which we then customize


        PlotSettings ps =

          new PlotSettings(lo.ModelType);

        ps.CopyFrom(lo);


        // The PlotSettingsValidator helps

        // create a valid PlotSettings object


        PlotSettingsValidator psv =

          PlotSettingsValidator.Current;


        // We'll plot the extents, centered and

        // scaled to fit


        psv.SetPlotType(

          ps,

          Autodesk.AutoCAD.DatabaseServices.PlotType.Extents

        );

        psv.SetUseStandardScale(ps, true);

        psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);

        psv.SetPlotCentered(ps, true);


        // We'll use the standard DWF PC3, as

        // for today we're just plotting to file


        psv.SetPlotConfigurationName(

          ps,

          "DWF6 ePlot.pc3",

          "ANSI_A_(8.50_x_11.00_Inches)"

        );


        // We need to link the PlotInfo to the

        // PlotSettings and then validate it


        pi.OverrideSettings = ps;

        PlotInfoValidator piv =

          new PlotInfoValidator();

        piv.MediaMatchingPolicy =

          MatchingPolicy.MatchEnabled;

        piv.Validate(pi);


        // A PlotEngine does the actual plotting

        // (can also create one for Preview)


        if (PlotFactory.ProcessPlotState ==

            ProcessPlotState.NotPlotting)

        {

          PlotEngine pe =

            PlotFactory.CreatePublishEngine();

          using (pe)

          {

            // Create a Progress Dialog to provide info

            // and allow thej user to cancel


            PlotProgressDialog ppd =

              new PlotProgressDialog(false, 1, true);

            using (ppd)

            {

              ppd.set_PlotMsgString(

                PlotMessageIndex.DialogTitle,

                "Custom Plot Progress"

              );

              ppd.set_PlotMsgString(

                PlotMessageIndex.CancelJobButtonMessage,

                "Cancel Job"

              );

              ppd.set_PlotMsgString(

                PlotMessageIndex.CancelSheetButtonMessage,

                "Cancel Sheet"

              );

              ppd.set_PlotMsgString(

                PlotMessageIndex.SheetSetProgressCaption,

                "Sheet Set Progress"

              );

              ppd.set_PlotMsgString(

                PlotMessageIndex.SheetProgressCaption,

                "Sheet Progress"

              );

              ppd.LowerPlotProgressRange = 0;

              ppd.UpperPlotProgressRange = 100;

              ppd.PlotProgressPos = 0;


              // Let's start the plot, at last


              ppd.OnBeginPlot();

              ppd.IsVisible = true;

              pe.BeginPlot(ppd, null);


              // We'll be plotting a single document


              pe.BeginDocument(

                pi,

                doc.Name,

                null,

                1,

                true, // Let's plot to file

                "c://test-output"

              );


              // Which contains a single sheet


              ppd.OnBeginSheet();


              ppd.LowerSheetProgressRange = 0;

              ppd.UpperSheetProgressRange = 100;

              ppd.SheetProgressPos = 0;


              PlotPageInfo ppi = new PlotPageInfo();

              pe.BeginPage(

                ppi,

                pi,

                true,

                null

              );

              pe.BeginGenerateGraphics(null);

              pe.EndGenerateGraphics(null);


              // Finish the sheet

              pe.EndPage(null);

              ppd.SheetProgressPos = 100;

              ppd.OnEndSheet();


              // Finish the document


              pe.EndDocument(null);


              // And finish the plot


              ppd.PlotProgressPos = 100;

              ppd.OnEndPlot();

              pe.EndPlot(null);

            }

          }

        }

        else

        {

          ed.WriteMessage(

            "/nAnother plot is in progress."

          );

        }

      }

    }

  }

}

A few comments on the code: I chose to plot to a file using the standard DWF plot driver/PC3 file, mainly as it avoids having to second-guess what printers/plotters everyone uses. :-) The SDK sample populates comboboxes in a dialog to allow selection of the device and the media size, but I've just gone with a choice that should work on all systems.

Here's what you should see when you launch the SIMPLOT command:

Plot_progress

The output file should be created in "c:/test-output.dwf".

I added a simple check to fail gracefully when another plot is in progress... as this code will drive either a foreground or a background plot (depending on the value of the BACKGROUNDPLOT system variable), there's clear scope for failure if the code doesn't check via PlotFactory.ProcessPlotState (or handle the exception if another plot is already happening when you call PlotFactory.CreatePublishEngine()).

Now that I'm online I've found there's quite a similar code sample to the ADN site (also converted from the original SDK sample, I suspect):

How to plot using AutoCAD's .NET Managed API?

<think> 我们之前讨论的是使用VBA在AutoCAD中展点,现在用户需要C#版本的代码。在AutoCAD中使用C#进行开发,通常是通过.NET API来实现的。下面我将提供一个使用C#在AutoCAD中展点的示例代码。 ### 步骤概述 1. **创建C#项目**:使用Visual Studio创建类库项目,添加必要的引用(如acdbmgd.dll, acmgd.dll)。 2. **编写代码**:连接到AutoCAD,读取数据(这里假设从文本文件读取坐标,用户也可以从数据库或Excel读取),然后在AutoCAD中绘制点和文本标签。 3. **注意事项**:需要处理COM交互和事务。 ### 示例代码(C#) ```csharp using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.IO; namespace AutoCADPointPlotting { public class PointPlotter { [CommandMethod("PlotPoints")] public void PlotPoints() { // 获取当前文档和数据库 Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // 提示用户选择坐标文件 PromptOpenFileOptions fileOpts = new PromptOpenFileOptions("选择坐标文件"); fileOpts.Filter = "Text files (*.txt)|*.txt"; PromptFileNameResult fileRes = ed.GetFileNameForOpen(fileOpts); if (fileRes.Status != PromptStatus.OK) return; string filePath = fileRes.StringResult; try { // 读取文件中的所有行 string[] lines = File.ReadAllLines(filePath); // 开始事务 using (Transaction trans = db.TransactionManager.StartTransaction()) { // 打开块表用于写入 BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 遍历每一行数据 foreach (string line in lines) { // 跳过空行 if (string.IsNullOrWhiteSpace(line)) continue; // 假设每行格式为:点号, X坐标, Y坐标 [可选Z坐标] string[] parts = line.Split(','); if (parts.Length < 3) continue; string pointName = parts[0].Trim(); double x, y, z = 0.0; // 解析坐标 if (!double.TryParse(parts[1].Trim(), out x)) continue; if (!double.TryParse(parts[2].Trim(), out y)) continue; if (parts.Length >= 4) double.TryParse(parts[3].Trim(), out z); Point3d point = new Point3d(x, y, z); // 创建点对象并添加到模型空间 DBPoint dbPoint = new DBPoint(point); btr.AppendEntity(dbPoint); trans.AddNewlyCreatedDBObject(dbPoint, true); // 创建文本标签(在点上方偏移) DBText text = new DBText(); text.Position = point + new Vector3d(5, 5, 0); // 偏移量 text.TextString = pointName; text.Height = 5; // 文本高度 btr.AppendEntity(text); trans.AddNewlyCreatedDBObject(text, true); } // 提交事务 trans.Commit(); } ed.WriteMessage("\n成功绘制{0}个点。", lines.Length); } catch (Exception ex) { ed.WriteMessage("\n错误: " + ex.Message); } } } } ``` ### 代码说明 - **文件读取**:代码通过文本文件读取坐标数据,每行格式为:`点号, X坐标, Y坐标, [Z坐标]`(Z坐标可选)。 - **绘图过程**: - 使用事务(Transaction)确保绘图操作的安全性。 - 在模型空间创建点(DBPoint)和文本标签(DBText)。 - 文本标签位置在点的右上方偏移(5,5)处。 - **扩展性**:用户可根据需要修改数据源(如从Excel读取,需添加对Excel的引用)或增加其他标注(如角度、距离)。 ### 如何运行 1. 在Visual Studio中创建类库项目,添加对`acdbmgd.dll`、`acmgd.dll`的引用(位于AutoCAD安装目录)。 2. 将上述代码复制到项目中。 3. 编译生成DLL文件。 4.AutoCAD中使用`NETLOAD`命令加载此DLL,然后运行命令`PlotPoints`。 ### 注意事项 - **引用设置**:项目中需将`acdbmgd.dll`和`acmgd.dll`的`Copy Local`属性设为`False`。 - **数据格式**:确保坐标数据格式正确,否则解析失败。 - **错误处理**:代码包含基本异常处理,但实际应用中可进一步细化。 - **性能优化**:对于大规模数据,可考虑使用块参照(BlockReference)代替单独绘制每个点[^1]。 ### 相关问题 1. 如何从Excel读取数据到AutoCAD中展点? 2. AutoCAD C# API中如何处理三维坐标点? 3. 展点后如何自动连线形成多段线? §§相关问题§§ 1. 如何从Excel读取数据到AutoCAD中展点? 2. AutoCAD C# API中如何处理三维坐标点? 3. 展点后如何自动连线形成多段线? </think> ### C#代码:在AutoCAD中进行展点操作 以下是通过.NET API在AutoCAD中实现展点功能的完整C#代码示例。代码包含**坐标数据读取、点绘制、文本标注**核心功能,兼容AutoCAD 2020+版本。 ```csharp using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoEdge; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.IO; namespace AutoCADPointPlotter { public class PointPlotCommands { [CommandMethod("PlotPoints")] public void PlotPoints() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 1. 获取坐标文件路径 string filePath = GetCoordinateFilePath(ed); if (string.IsNullOrEmpty(filePath)) return; // 2. 解析坐标数据 List<PointData> points = ParseCoordinateFile(filePath); // 3.AutoCAD中绘制点 using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 创建图层 CreatePointLayer(db, tr); foreach (PointData pt in points) { // 绘制点 DBPoint dbPoint = new DBPoint(new Point3d(pt.X, pt.Y, pt.Z)); dbPoint.Layer = "POINTS"; btr.AppendEntity(dbPoint); tr.AddNewlyCreatedDBObject(dbPoint, true); // 添加文本标注 DBText text = new DBText(); text.Position = new Point3d(pt.X + 5, pt.Y + 5, pt.Z); // 偏移位置 text.TextString = pt.Name; text.Height = 5; // 文字高度 btr.AppendEntity(text); tr.AddNewlyCreatedDBObject(text, true); } tr.Commit(); } ed.WriteMessage($"\n成功绘制 {points.Count} 个点"); } catch (Exception ex) { ed.WriteMessage($"\n错误: {ex.Message}"); } } // 获取坐标文件路径 private string GetCoordinateFilePath(Editor ed) { PromptOpenFileOptions opts = new PromptOpenFileOptions("\n选择坐标文件") { Filter = "文本文件 (*.txt)|*.txt|CSV文件 (*.csv)|*.csv" }; PromptFileNameResult res = ed.GetFileNameForOpen(opts); return (res.Status == PromptStatus.OK) ? res.StringResult : null; } // 解析坐标文件 (格式: 点号,X,Y,Z) private List<PointData> ParseCoordinateFile(string filePath) { List<PointData> points = new List<PointData>(); foreach (string line in File.ReadAllLines(filePath)) { if (string.IsNullOrWhiteSpace(line) || line.StartsWith("//")) continue; string[] parts = line.Split(','); if (parts.Length >= 4) { points.Add(new PointData( name: parts[0].Trim(), x: double.Parse(parts[1]), y: double.Parse(parts[2]), z: parts.Length > 3 ? double.Parse(parts[3]) : 0.0 )); } } return points; } // 创建点图层 private void CreatePointLayer(Database db, Transaction tr) { LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForWrite) as LayerTable; if (!lt.Has("POINTS")) { LayerTableRecord ltr = new LayerTableRecord { Name = "POINTS", Color = Color.FromColorIndex(ColorMethod.ByAci, 1) // 红色 }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } } } // 坐标数据结构 public class PointData { public string Name { get; } public double X { get; } public double Y { get; } public double Z { get; } public PointData(string name, double x, double y, double z = 0.0) { Name = name; X = x; Y = y; Z = z; } } } ``` ### 代码说明 1. **功能流程**: - 用户通过`PlotPoints`命令启动 - 选择包含坐标的文本/CSV文件(格式:`点号,X坐标,Y坐标,[Z坐标]`) - 自动创建"POINTS"图层(红色) - 在指定坐标绘制点并标注点号 2. **关键操作**: ```csharp // 创建点对象 DBPoint dbPoint = new DBPoint(new Point3d(pt.X, pt.Y, pt.Z)); // 添加文本标注 DBText text = new DBText(); text.Position = new Point3d(pt.X + 5, pt.Y + 5, pt.Z); text.TextString = pt.Name; ``` 3. **文件格式示例**: ``` P1,100.50,200.75 P2,150.25,180.30,5.0 P3,210.80,195.60 ``` ### 部署步骤 1. **引用配置**(在Visual Studio中): - 添加AutoCAD .NET API引用:`acdbmgd.dll`, `acmgd.dll` - 设置引用属性:`Copy Local = False` 2. **编译与加载**: ```powershell # 编译命令 msbuild /p:Configuration=Release ``` - 在AutoCAD中使用`NETLOAD`命令加载生成的DLL 3. **性能优化建议**: - 万级点位处理:使用`Polyline`替代单独点对象 ```csharp // 批量创建多段线 Polyline pline = new Polyline(); for (int i = 0; i < points.Count; i++) { pline.AddVertexAt(i, new Point2d(points[i].X, points[i].Y), 0, 0, 0); } ``` ### 常见错误解决 1. **DLL加载失败**: - 确保引用`acdbmgd.dll`版本与AutoCAD版本匹配 - 检查.NET Framework版本兼容性 2. **坐标解析错误**: - 添加数据格式验证: ```csharp if (!double.TryParse(parts[1], out double x)) throw new FormatException($"无效X坐标: {parts[1]}"); ``` 3. **大规模数据优化**: - 使用事务分批处理: ```csharp int batchSize = 1000; for (int i = 0; i < points.Count; i += batchSize) { using (Transaction tr = ...) { // 处理当前批次 tr.Commit(); } } ``` ### 进阶扩展 1. **从Excel读取数据**: ```csharp using Excel = Microsoft.Office.Interop.Excel; // 获取Excel数据 var xlApp = new Excel.Application(); Excel.Range range = xlApp.Range["A2:D1000"]; ``` 2. **添加高程标注**: ```csharp // 在Z≠0时添加高程标签 if (Math.Abs(pt.Z) > 0.01) { DBText elevText = new DBText(); elevText.TextString = $"H={pt.Z:F2}"; elevText.Position = new Point3d(pt.X, pt.Y - 5, pt.Z); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值