Plotting a window from AutoCAD using .NET
来源:互联网 发布:python 输入 编辑:程序博客网 时间:2024/05/16 09:55
First order of business was to allow the user to select the window to plot. For this I used the classic combination of Editor.GetPoint() for the first corner) and Editor.GetCorner() for the second. All well and good, but the points returned by these functions are in UCS (User Coordinate System) coordinates. Which meant that as it stood, the code would work just fine if (and only if) the view we were using to select the window was parallell with the World Coordinate System (and no additional UCS was in place). In order to deal with the very common scenario of either a UCS being used or the current modelspace view being orbited (etc.), we need to transform the current UCS coordinates into DCS, the Display Coordinate System.
Thankfully that's pretty easy: no need for matrices or anything, we simply use another old friend, acedTrans() (the ObjectARX equivalent of the (trans) function, for you LISPers out there). There isn't a direct equivalent for this function in the managed API (that I'm aware of), so we have to use P/Invoke to call the ObjectARX function. The technique is shown in this DevNote, for those of you that have access to the ADN website:
How to call acedTrans from .NET application?
Otherwise the changes to the original code are very minor: we need to set the extents of the window to plot and then set the plot type to "window", apparently in that order. AutoCAD complained when I initially made the calls in the opposite sequence.
Here's the C# code:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.Geometry;
using System.Runtime.InteropServices;
using System;
namespace PlottingApplication
{
public class SimplePlottingCommands
{
[DllImport("acad.exe",
CallingConvention = CallingConvention.Cdecl,
EntryPoint="acedTrans")
]
static extern int acedTrans(
double[] point,
IntPtr fromRb,
IntPtr toRb,
int disp,
double[] result
);
[CommandMethod("winplot")]
static public void WindowPlot()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptPointOptions ppo =
new PromptPointOptions(
"/nSelect first corner of plot area: "
);
ppo.AllowNone = false;
PromptPointResult ppr =
ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
Point3d first = ppr.Value;
PromptCornerOptions pco =
new PromptCornerOptions(
"/nSelect second corner of plot area: ",
first
);
ppr = ed.GetCorner(pco);
if (ppr.Status != PromptStatus.OK)
return;
Point3d second = ppr.Value;
// Transform from UCS to DCS
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 };
// Transform the first point...
acedTrans(
first.ToArray(),
rbFrom.UnmanagedObject,
rbTo.UnmanagedObject,
0,
firres
);
// ... and the second
acedTrans(
second.ToArray(),
rbFrom.UnmanagedObject,
rbTo.UnmanagedObject,
0,
secres
);
// We can safely drop the Z-coord at this stage
Extents2d window =
new Extents2d(
firres[0],
firres[1],
secres[0],
secres[1]
);
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.SetPlotWindowArea(ps, window);
psv.SetPlotType(
ps,
Autodesk.AutoCAD.DatabaseServices.PlotType.Window
);
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."
);
}
}
}
}
}
- Plotting a window from AutoCAD using .NET
- Previewing and plotting a single sheet in AutoCAD using .NET
- Previewing and plotting multiple sheets in AutoCAD using .NET
- Creating a multileader in AutoCAD using a jig from .NET
- Updating a specific attribute inside a folder of AutoCAD drawings using RealDWG from .NET
- Using a palette from .NET to display properties of multiple AutoCAD objects
- Purging registered application names from a folder of AutoCAD drawings using .NET
- Updating an Excel spreadsheet from a linked AutoCAD table using .NET
- Driving a basic AutoCAD plot using .NET
- Moving entities from one AutoCAD layer to another using .NET
- Using AutoCAD's file selection dialog from .NET
- Using a modal .NET dialog to display AutoCAD object properties
- Using a modeless .NET dialog to display AutoCAD object properties
- Updating a specific attribute inside an AutoCAD drawing using .NET
- Creating a spline-segment multileader in AutoCAD using .NET
- Driving a multi-sheet AutoCAD plot using .NET
- Creating an AutoCAD multileader spraying out from central text using .NET
- Updating a specific attribute inside a folder of AutoCAD drawings using .NET
- CSMA/CA协议 80211
- 初学者来认识OLEDB和ODBC的区别
- Microsoft to release source for .NET Framework Libraries
- Allowing selection of an AutoCAD plot device and media name using .NET
- 测试
- Plotting a window from AutoCAD using .NET
- 使用Spring JdbcTemplate实现SQL批处理
- Streaming 技术/原理
- 单元测试与功能测试之间的区别
- symbian C++ 各种类型之间的转换
- Free webcast: "AutoCAD: .NET for LISP Programmers"
- 调整浏览器窗口
- 客户端性能检测
- 模拟浏览器菜单