├── .gitattributes
├── .gitignore
├── Gile.AutoCAD.Extension.sln
├── Gile.AutoCAD.R20.Extension
├── AbstractViewTableRecordExtension.cs
├── Active.cs
├── Assert.cs
├── AttributeCollectionExtension.cs
├── BlockReferenceExtension.cs
├── BlockTableExtension.cs
├── BlockTableRecordExtension.cs
├── DBDictionaryExtension.cs
├── DBObjectCollectionExtension.cs
├── DBObjectExtension.cs
├── DBTextExtension.cs
├── DatabaseExtension.cs
├── DisposableList.cs
├── DisposableSet.cs
├── DocumentCollectionExtension.cs
├── EditorExtension.cs
├── EntityExtension.cs
├── Gile.AutoCAD.R20.Extension.csproj
├── IDisposableCollection.cs
├── IEnumerableExtension.cs
├── MTextExtension.cs
├── ObjectIdCollectionExtension.cs
├── ObjectIdExtension.cs
├── PolylineExtension.cs
├── Properties
│ └── AssemblyInfo.cs
├── ResultBufferExtension.cs
├── SymbolTableExtension.cs
└── WorkingDatabase.cs
├── Gile.AutoCAD.R25.Extension
├── AbstractViewTableRecordExtension.cs
├── Active.cs
├── AttributeCollectionExtension.cs
├── BlockReferenceExtension.cs
├── BlockTableExtension.cs
├── BlockTableRecordExtension.cs
├── DBDictionaryExtension.cs
├── DBObjectCollectionExtension.cs
├── DBObjectExtension.cs
├── DBTextExtension.cs
├── DatabaseExtension.cs
├── DisposableList.cs
├── DisposableSet.cs
├── DocumentCollectionExtension.cs
├── EditorExtension.cs
├── EntityExtension.cs
├── Gile.AutoCAD.R25.Extension.csproj
├── IDisposableCollection.cs
├── IEnumerableExtension.cs
├── MTextExtension.cs
├── ObjectIdCollectionExtension.cs
├── ObjectIdExtension.cs
├── PolylineExtension.cs
├── Properties
│ └── AssemblyInfo.cs
├── RuntimeExtension.cs
├── SymbolTableExtension.cs
└── WorkingDatabase.cs
├── LICENSE
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
--------------------------------------------------------------------------------
/Gile.AutoCAD.Extension.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.8.34511.84
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gile.AutoCAD.R20.Extension", "Gile.AutoCAD.R20.Extension\Gile.AutoCAD.R20.Extension.csproj", "{32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gile.AutoCAD.R25.Extension", "Gile.AutoCAD.R25.Extension\Gile.AutoCAD.R25.Extension.csproj", "{2F921473-0497-44E3-A535-76BC7900035D}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {2F921473-0497-44E3-A535-76BC7900035D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {2F921473-0497-44E3-A535-76BC7900035D}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {2F921473-0497-44E3-A535-76BC7900035D}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {2F921473-0497-44E3-A535-76BC7900035D}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {FBC4AA09-A2F5-4BD5-A6E7-69F0E397BDE4}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/AbstractViewTableRecordExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | namespace Gile.AutoCAD.R20.Extension
5 | {
6 | ///
7 | /// Provides extension for the AbstractViewTableRecord type.
8 | ///
9 | public static class AbstractViewTableRecordExtension
10 | {
11 | ///
12 | /// Gets the transformation matrix from the view Display Coordinate System (DCS) to World Coordinate System (WCS).
13 | ///
14 | /// Instance to which the method applies.
15 | /// The DCS to WCS transformation matrix.
16 | /// Thrown if is null.
17 | public static Matrix3d EyeToWorld(this AbstractViewTableRecord view)
18 | {
19 | Assert.IsNotNull(view, nameof(view));
20 |
21 | return
22 | Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
23 | Matrix3d.Displacement(view.Target.GetAsVector()) *
24 | Matrix3d.PlaneToWorld(view.ViewDirection);
25 | }
26 |
27 | ///
28 | /// Gets the transformation matrix from World Coordinate System (WCS) to the view Display Coordinate System (DCS).
29 | ///
30 | /// Instance to which the method applies.
31 | /// The WCS to DCS transformation matrix.
32 | /// Thrown if is null.
33 | public static Matrix3d WorldToEye(this AbstractViewTableRecord view)
34 | {
35 | Assert.IsNotNull(view, nameof(view));
36 |
37 | return
38 | Matrix3d.WorldToPlane(view.ViewDirection) *
39 | Matrix3d.Displacement(view.Target.GetAsVector().Negate()) *
40 | Matrix3d.Rotation(view.ViewTwist, view.ViewDirection, view.Target);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/Active.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices.Core;
2 | using Autodesk.AutoCAD.DatabaseServices;
3 | using Autodesk.AutoCAD.EditorInput;
4 |
5 | using AcAp = Autodesk.AutoCAD.ApplicationServices;
6 |
7 | // Inspired by Scott McFarlane
8 | // https://www.autodesk.com/autodesk-university/class/Being-Remarkable-C-NET-AutoCAD-Developer-2015#handout
9 |
10 | namespace Gile.AutoCAD.R20.Extension
11 | {
12 | ///
13 | /// Provides easy access to several "active" objects in AutoCAD runtime environment.
14 | ///
15 | public static class Active
16 | {
17 | ///
18 | /// Gets the active Document object.
19 | ///
20 | public static AcAp.Document Document => Application.DocumentManager.MdiActiveDocument;
21 |
22 | ///
23 | /// Gets the active Database object.
24 | ///
25 | public static Database Database => Document.Database;
26 |
27 | ///
28 | /// Gets the active Editor object.
29 | ///
30 | public static Editor Editor => Document.Editor;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/Assert.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 |
5 | namespace Gile.AutoCAD.R20.Extension
6 | {
7 | ///
8 | /// Provides methods to throw an exception if an assertion is wrong.
9 | ///
10 | /// This class is not available for projects tageting .NET 8.0 (since AutoCAD 2025).
11 | public static class Assert
12 | {
13 | ///
14 | /// Throws ArgumentNullException if the object is null.
15 | ///
16 | /// Type of the object.
17 | /// The instance to which the assertion applies.
18 | /// Name of the parameter.
19 | public static void IsNotNull(T obj, string paramName) where T : class
20 | {
21 | if (obj == null)
22 | {
23 | throw new System.ArgumentNullException(paramName);
24 | }
25 | }
26 |
27 | ///
28 | /// Throws eNullObjectId if the ObjectId is null.
29 | ///
30 | /// The ObjectId to which the assertion applies.
31 | /// Name of the parameter.
32 | public static void IsNotObjectIdNull(ObjectId id, string paramName)
33 | {
34 | if (id.IsNull)
35 | {
36 | throw new Exception(ErrorStatus.NullObjectId, paramName);
37 | }
38 | }
39 |
40 | ///
41 | /// Throws ArgumentException if the string is null or empty.
42 | ///
43 | /// The string to which the assertion applies.
44 | /// Name of the parameter.
45 | public static void IsNotNullOrWhiteSpace(string str, string paramName)
46 | {
47 | if (string.IsNullOrWhiteSpace(str))
48 | {
49 | throw new System.ArgumentException("eNullOrWhiteSpace", paramName);
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/AttributeCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace Gile.AutoCAD.R20.Extension
6 | {
7 | ///
8 | /// Provides extension methods for the AttributeCollection type.
9 | ///
10 | public static class AttributeCollectionExtension
11 | {
12 | ///
13 | /// Opens the attribute references in the given open mode.
14 | ///
15 | /// Attribute collection.
16 | /// Transaction or OpenCloseTransaction to use.
17 | /// Open mode to obtain in.
18 | /// Value indicating whether to obtain erased objects.
19 | /// Value indicating if locked layers should be opened.
20 | /// The sequence of attribute references.
21 | /// Thrown if is null.
22 | /// Thrown if is null.
23 | public static IEnumerable GetObjects(
24 | this AttributeCollection source,
25 | Transaction tr,
26 | OpenMode mode = OpenMode.ForRead,
27 | bool openErased = false,
28 | bool forceOpenOnLockedLayers = false)
29 | {
30 | Assert.IsNotNull(source, nameof(source));
31 | Assert.IsNotNull(tr, nameof(tr));
32 |
33 | if (source.Count > 0)
34 | {
35 | foreach (ObjectId id in source)
36 | {
37 | if (!id.IsErased || openErased)
38 | {
39 | yield return (AttributeReference)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
40 | }
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/BlockTableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | namespace Gile.AutoCAD.R20.Extension
4 | {
5 | ///
6 | /// Provides extension methods for the BlockTable type.
7 | ///
8 | public static class BlockTableExtension
9 | {
10 | ///
11 | /// Gets the objectId of a block definition (BlockTableRecord) from its name.
12 | /// If the block is not found in the block table, a dwg file is searched in the support paths and added to the block table.
13 | ///
14 | /// Block table.
15 | /// Block name.
16 | /// The ObjectId of the block table record or ObjectId.Null if not found.
17 | /// Thrown if is null.
18 | /// Thrown if is null or empty.
19 | public static ObjectId GetBlock(this BlockTable blockTable, string blockName)
20 | {
21 | Assert.IsNotNull(blockTable, nameof(blockTable));
22 | Assert.IsNotNullOrWhiteSpace(blockName, nameof(blockName));
23 |
24 | if (blockTable.Has(blockName))
25 | return blockTable[blockName];
26 | try
27 | {
28 | string blockPath = HostApplicationServices.Current.FindFile(blockName + ".dwg", blockTable.Database, FindFileHint.Default);
29 | using (var tmpDb = new Database(false, true))
30 | {
31 | tmpDb.ReadDwgFile(blockPath, FileOpenMode.OpenForReadAndAllShare, true, null);
32 | return blockTable.Database.Insert(blockName, tmpDb, true);
33 | }
34 | }
35 | catch
36 | {
37 | return ObjectId.Null;
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/BlockTableRecordExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 | using Autodesk.AutoCAD.Runtime;
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gile.AutoCAD.R20.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the BlockTableRecord type.
12 | ///
13 | public static class BlockTableRecordExtension
14 | {
15 | ///
16 | /// Opens the entities which type matches to the given one, and return them.
17 | ///
18 | /// Type of objects to return.
19 | /// Block table record.
20 | /// Transaction or OpenCloseTransaction to use.
21 | /// Open mode to obtain in.
22 | /// Value indicating whether to obtain erased objects.
23 | /// Value indicating if locked layers should be opened.
24 | /// The sequence of opened objects.
25 | /// Thrown if is null.
26 | /// Thrown if is null.
27 | public static IEnumerable GetObjects(
28 | this BlockTableRecord btr,
29 | Transaction tr,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayers = false) where T : Entity
33 | {
34 | Assert.IsNotNull(btr, nameof(btr));
35 | Assert.IsNotNull(tr, nameof(tr));
36 |
37 | var source = openErased ? btr.IncludingErased : btr;
38 | if (typeof(T) == typeof(Entity))
39 | {
40 | foreach (ObjectId id in source)
41 | {
42 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
43 | }
44 | }
45 | else
46 | {
47 | var rxClass = RXObject.GetClass(typeof(T));
48 | foreach (ObjectId id in source)
49 | {
50 | if (id.ObjectClass.IsDerivedFrom(rxClass))
51 | {
52 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// Appends the entities to the BlockTableRecord.
60 | ///
61 | /// Instance to which the method applies.
62 | /// Transaction or OpenCloseTransaction to use.
63 | /// Sequence of entities.
64 | /// The collection of added entities ObjectId.
65 | /// Thrown if is null.
66 | /// Thrown if is null.
67 | /// Thrown if is null.
68 | public static ObjectIdCollection Add(this BlockTableRecord owner, Transaction tr, IEnumerable entities)
69 | {
70 | Assert.IsNotNull(owner, nameof(owner));
71 | Assert.IsNotNull(tr, nameof(tr));
72 | Assert.IsNotNull(entities, nameof(entities));
73 |
74 | var ids = new ObjectIdCollection();
75 | using (var ents = new DisposableSet(entities))
76 | {
77 | foreach (Entity ent in ents)
78 | {
79 | ids.Add(owner.AppendEntity(ent));
80 | tr.AddNewlyCreatedDBObject(ent, true);
81 | }
82 | }
83 | return ids;
84 | }
85 |
86 | ///
87 | /// Appends the entities to the BlockTableRecord.
88 | ///
89 | /// Instance to which the method applies.
90 | /// Active transaction
91 | /// Collection of entities.
92 | /// The collection of added entities ObjectId.
93 | /// Thrown if is null.
94 | /// Thrown if is null.
95 | /// Thrown if is null.
96 | public static ObjectIdCollection AddRange(this BlockTableRecord owner, Transaction tr, params Entity[] entities)
97 | {
98 | Assert.IsNotNull(owner, nameof(owner));
99 | Assert.IsNotNull(tr, nameof(tr));
100 | Assert.IsNotNull(entities, nameof(entities));
101 |
102 | return owner.Add(tr, entities);
103 | }
104 |
105 | ///
106 | /// Appends the entity to the BlockTableRecord.
107 | ///
108 | /// Instance to which the method applies.
109 | /// Transaction or OpenCloseTransaction to use.
110 | /// Entity to add.
111 | /// The ObjectId of added entity.
112 | /// Thrown if is null.
113 | /// Thrown if is null.
114 | /// Thrown if is null.
115 | public static ObjectId Add(this BlockTableRecord owner, Transaction tr, Entity entity)
116 | {
117 | Assert.IsNotNull(owner, nameof(owner));
118 | Assert.IsNotNull(tr, nameof(tr));
119 | Assert.IsNotNull(entity, nameof(entity));
120 |
121 | try
122 | {
123 | var id = owner.AppendEntity(entity);
124 | tr.AddNewlyCreatedDBObject(entity, true);
125 | return id;
126 | }
127 | catch
128 | {
129 | entity.Dispose();
130 | throw;
131 | }
132 | }
133 |
134 | ///
135 | /// Inserts a block reference.
136 | ///
137 | /// Instance to which the method applies.
138 | /// Transaction or OpenCloseTransaction to use.
139 | /// Nlock name.
140 | /// Insertion point.
141 | /// X scale factor.
142 | /// Y scale factor.
143 | /// Z scale factor.
144 | /// Rotation
145 | /// Collection of key/value pairs (Tag/Value).
146 | /// The newly created BlockReference.
147 | /// Thrown if is null.
148 | /// Thrown if is null.
149 | /// Thrown if is null or empty.
150 | public static BlockReference InsertBlockReference(
151 | this BlockTableRecord target,
152 | Transaction tr,
153 | string blkName,
154 | Point3d insertPoint,
155 | double xScale = 1.0,
156 | double yScale = 1.0,
157 | double zScale = 1.0,
158 | double rotation = 0.0,
159 | Dictionary attribValues = null)
160 | {
161 | Assert.IsNotNull(target, nameof(target));
162 | Assert.IsNotNull(tr, nameof(tr));
163 | Assert.IsNotNullOrWhiteSpace(blkName, nameof(blkName));
164 |
165 | var db = target.Database;
166 | BlockReference br = null;
167 | var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
168 | var btrId = bt.GetBlock(blkName);
169 | if (btrId != ObjectId.Null)
170 | {
171 | br = new BlockReference(insertPoint, btrId) { ScaleFactors = new Scale3d(xScale, yScale, zScale), Rotation = rotation };
172 | var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
173 | if (btr.Annotative == AnnotativeStates.True)
174 | {
175 | var objectContextManager = db.ObjectContextManager;
176 | var objectContextCollection = objectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES");
177 | Autodesk.AutoCAD.Internal.ObjectContexts.AddContext(br, objectContextCollection.CurrentContext);
178 | }
179 | target.Add(tr, br);
180 | br.AddAttributeReferences(tr, attribValues);
181 | }
182 | return br;
183 | }
184 |
185 | ///
186 | /// Synchronizes the attributes of all block references.
187 | ///
188 | /// Instance which the method applies.
189 | /// Transaction or OpenCloseTransaction to use.
190 | /// Thrown if is null.
191 | /// Thrown if is null.
192 | public static void SynchronizeAttributes(this BlockTableRecord target, Transaction tr)
193 | {
194 | Assert.IsNotNull(target, nameof(target));
195 | Assert.IsNotNull(tr, nameof(tr));
196 |
197 | AttributeDefinition[] attDefs = target.GetObjects(tr).ToArray();
198 | foreach (BlockReference br in target.GetBlockReferenceIds(true, false).GetObjects(tr, OpenMode.ForWrite))
199 | {
200 | br.ResetAttributes(tr, attDefs);
201 | }
202 | if (target.IsDynamicBlock)
203 | {
204 | target.UpdateAnonymousBlocks();
205 | foreach (BlockTableRecord btr in target.GetAnonymousBlockIds().GetObjects(tr))
206 | {
207 | attDefs = btr.GetObjects(tr).ToArray();
208 | foreach (BlockReference br in btr.GetBlockReferenceIds(true, false).GetObjects(tr, OpenMode.ForWrite))
209 | {
210 | br.ResetAttributes(tr, attDefs);
211 | }
212 | }
213 | }
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DBDictionaryExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System.Collections.Generic;
5 |
6 | namespace Gile.AutoCAD.R20.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the DBDictionary type.
10 | ///
11 | public static class DBDictionaryExtension
12 | {
13 | ///
14 | /// Tries to open the object of the dictionary corresponding to the given type, in the given open mode.
15 | ///
16 | /// Type of the returned object.
17 | /// Instance to which the method applies.
18 | /// Transaction or OpenCloseTransaction to use.
19 | /// Key of the entry in the dictionary.
20 | /// Output object.
21 | /// Open mode to obtain in.
22 | /// Value indicating whether to obtain erased objects.
23 | /// true, if the operations succeeded; false, otherwise.
24 | /// Thrown if is null.
25 | /// Thrown if is null.
26 | /// Thrown if is null or empty.
27 | public static bool TryGetObject(
28 | this DBDictionary source,
29 | Transaction tr,
30 | string key,
31 | out T obj,
32 | OpenMode mode = OpenMode.ForRead,
33 | bool openErased = false) where T : DBObject
34 | {
35 | Assert.IsNotNull(source, nameof(source));
36 | Assert.IsNotNull(tr, nameof(tr));
37 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
38 |
39 | obj = default;
40 | return source.Contains(key) && source.GetAt(key).TryGetObject(tr, out obj, mode, openErased);
41 | }
42 |
43 | ///
44 | /// Tries to get the named dictionary.
45 | ///
46 | /// Instance to which the method applies.
47 | /// Transaction or OpenCloseTransaction to use.
48 | /// Name of the dictionary.
49 | /// Output dictionary.
50 | /// Open mode to obtain in.
51 | /// Value indicating whether to obtain erased objects.
52 | /// true, if the operations succeeded; false, otherwise.
53 | /// Thrown if is null.
54 | /// Thrown if is null.
55 | /// Thrown if is null or empty.
56 | public static bool TryGetNamedDictionary(
57 | this DBDictionary parent,
58 | Transaction tr,
59 | string key,
60 | out DBDictionary dictionary,
61 | OpenMode mode = OpenMode.ForRead,
62 | bool openErased = false)
63 | {
64 | Assert.IsNotNull(parent, nameof(parent));
65 | Assert.IsNotNull(tr, nameof(tr));
66 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
67 |
68 | dictionary = default;
69 | if (parent.Contains(key))
70 | {
71 | var id = parent.GetAt(key);
72 | if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(DBDictionary))))
73 | {
74 | dictionary = (DBDictionary)tr.GetObject(id, mode, openErased);
75 | return true;
76 | }
77 | }
78 | return false;
79 | }
80 |
81 | ///
82 | /// Opens the entities which type matches to the given one, and return them.
83 | ///
84 | /// Type of returned objects.
85 | /// Instance to which the method applies.
86 | /// Transaction or OpenCloseTransaction to use.
87 | /// Open mode to obtain in.
88 | /// Value indicating whether to obtain erased objects.
89 | /// The sequence of collected objects.
90 | /// Thrown if is null.
91 | /// Thrown if is null.
92 | public static IEnumerable GetObjects(
93 | this DBDictionary source,
94 | Transaction tr,
95 | OpenMode mode = OpenMode.ForRead,
96 | bool openErased = false)
97 | where T : DBObject
98 | {
99 | Assert.IsNotNull(source, nameof(source));
100 | Assert.IsNotNull(tr, nameof(tr));
101 |
102 | var rxc = RXObject.GetClass(typeof(T));
103 | foreach (DBDictionaryEntry entry in openErased ? source.IncludingErased : source)
104 | {
105 | if (entry.Value.ObjectClass.IsDerivedFrom(rxc))
106 | {
107 | yield return (T)tr.GetObject(entry.Value, mode, openErased, false);
108 | }
109 | }
110 | }
111 |
112 | ///
113 | /// Gets or creates the named dictionary.
114 | ///
115 | /// Instance to which the method applies.
116 | /// Transaction or OpenCloseTransaction to use.
117 | /// Name of the dictionary.
118 | /// The found or newly created dictionary.
119 | /// Thrown if is null.
120 | /// Thrown if is null.
121 | /// Thrown if is null or empty.
122 | /// Throw if the is not a DBDictionary.
123 | public static DBDictionary GetOrCreateNamedDictionary(
124 | this DBDictionary parent,
125 | Transaction tr,
126 | string name)
127 | {
128 | Assert.IsNotNull(parent, nameof(parent));
129 | Assert.IsNotNull(tr, nameof(tr));
130 | Assert.IsNotNullOrWhiteSpace(name, nameof(name));
131 |
132 | if (parent.Contains(name))
133 | {
134 | var id = parent.GetAt(name);
135 | if (!id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(DBDictionary))))
136 | throw new System.ArgumentException("Not a DBDictionary", nameof(name));
137 | return (DBDictionary)tr.GetObject(id, OpenMode.ForRead);
138 | }
139 | else
140 | {
141 | var dictionary = new DBDictionary();
142 | parent.OpenForWrite(tr);
143 | parent.SetAt(name, dictionary);
144 | tr.AddNewlyCreatedDBObject(dictionary, true);
145 | return dictionary;
146 | }
147 | }
148 |
149 | ///
150 | /// Tries to get the xrecord data.
151 | ///
152 | /// Instance to which the method applies.
153 | /// Transaction or OpenCloseTransaction to use.
154 | /// Key of the xrecord.
155 | /// Output data.
156 | /// true, if the operation succeeded; false, otherwise.
157 | /// Thrown if is null.
158 | /// Thrown if is null.
159 | /// Thrown if is null or empty.
160 | public static bool TryGetXrecordData(
161 | this DBDictionary dictionary,
162 | Transaction tr,
163 | string key,
164 | out ResultBuffer data)
165 | {
166 | Assert.IsNotNull(dictionary, nameof(dictionary));
167 | Assert.IsNotNull(tr, nameof(tr));
168 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
169 |
170 | data = default;
171 | if (dictionary.Contains(key))
172 | {
173 | var id = dictionary.GetAt(key);
174 | if (id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Xrecord))))
175 | {
176 | var xrecord = (Xrecord)tr.GetObject(id, OpenMode.ForRead);
177 | data = xrecord.Data;
178 | return data != null;
179 | }
180 | }
181 | return false;
182 | }
183 |
184 | ///
185 | /// Sets the xrecord data.
186 | ///
187 | /// Instance to which the method applies.
188 | /// Transaction or OpenCloseTransaction to use.
189 | /// Key of the xrecord, the xrecord is created if it does not already exist.
190 | /// Data
191 | /// The got or newlycreated Xrecord.
192 | /// Thrown if is null.
193 | /// Thrown if is null.
194 | /// Thrown if is null or empty.
195 | /// Thrown if is null.
196 | public static Xrecord SetXrecordData(this DBDictionary dictionary, Transaction tr, string key, params TypedValue[] data)
197 | {
198 | Assert.IsNotNull(dictionary, nameof(dictionary));
199 | Assert.IsNotNull(tr, nameof(tr));
200 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
201 |
202 | return dictionary.SetXrecordData(tr, key, new ResultBuffer(data));
203 | }
204 |
205 | ///
206 | /// Sets the xrecord data.
207 | ///
208 | /// Instance to which the method applies.
209 | /// Transaction or OpenCloseTransaction to use.
210 | /// Key of the xrecord, the xrecord is created if it does not already exist.
211 | /// Data
212 | /// The got or newlycreated Xrecord.
213 | /// Thrown if is null.
214 | /// Thrown if is null.
215 | /// Thrown if is null or empty.
216 | /// Thrown if is null.
217 | public static Xrecord SetXrecordData(this DBDictionary dictionary, Transaction tr, string key, ResultBuffer data)
218 | {
219 | Assert.IsNotNull(dictionary, nameof(dictionary));
220 | Assert.IsNotNull(tr, nameof(tr));
221 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
222 | Assert.IsNotNull(data, nameof(data));
223 | Xrecord xrecord;
224 | if (dictionary.Contains(key))
225 | {
226 | var id = dictionary.GetAt(key);
227 | if (!id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(Xrecord))))
228 | throw new System.ArgumentException("Not an Xrecord'", nameof(key));
229 | {
230 | xrecord = (Xrecord)tr.GetObject(id, OpenMode.ForWrite);
231 | }
232 | }
233 | else
234 | {
235 | xrecord = new Xrecord();
236 | dictionary.OpenForWrite(tr);
237 | dictionary.SetAt(key, xrecord);
238 | tr.AddNewlyCreatedDBObject(xrecord, true);
239 | }
240 | xrecord.Data = data;
241 | return xrecord;
242 | }
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DBObjectCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Linq;
4 |
5 | namespace Gile.AutoCAD.R20.Extension
6 | {
7 | ///
8 | /// Provides extension methods for the DBObjectCollection type.
9 | ///
10 | public static class DBObjectCollectionExtension
11 | {
12 | ///
13 | /// Disposes of all objects in the collections.
14 | ///
15 | /// Instance to which the method applies.
16 | /// Thrown if is null.
17 | public static void DisposeAll(this DBObjectCollection source)
18 | {
19 | Assert.IsNotNull(source, nameof(source));
20 |
21 | var list = source.Cast().ToList();
22 | source.Clear();
23 | list.DisposeAll();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DBObjectExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | namespace Gile.AutoCAD.R20.Extension
5 | {
6 | ///
7 | /// Provides extension methods for the DBObject type.
8 | ///
9 | public static class DBObjectExtension
10 | {
11 | ///
12 | /// Tries to get the object extension dictionary.
13 | ///
14 | /// Instance to which the method applies.
15 | /// Transaction or OpenCloseTransaction to use.
16 | /// Output dictionary.
17 | /// Open mode to obtain in.
18 | /// Value indicating whether to obtain erased objects.
19 | /// true, if the operation succeeded; false, otherwise.
20 | /// Thrown if is null.
21 | /// Thrown if is null.
22 | public static bool TryGetExtensionDictionary(
23 | this DBObject dbObject,
24 | Transaction tr,
25 | out DBDictionary dictionary,
26 | OpenMode mode = OpenMode.ForRead,
27 | bool openErased = false)
28 | {
29 | Assert.IsNotNull(dbObject, nameof(dbObject));
30 | Assert.IsNotNull(tr, nameof(tr));
31 |
32 | dictionary = default;
33 | var id = dbObject.ExtensionDictionary;
34 | if (id.IsNull)
35 | return false;
36 | dictionary = (DBDictionary)tr.GetObject(id, mode, openErased);
37 | return true;
38 | }
39 |
40 | ///
41 | /// Gets or creates the extension dictionary.
42 | ///
43 | /// Instance to which the method applies.
44 | /// Transaction or OpenCloseTransaction to use.
45 | /// Open mode to obtain in.
46 | /// The extension dictionary.
47 | /// Thrown if is null.
48 | /// Thrown if is null.
49 | public static DBDictionary GetOrCreateExtensionDictionary(
50 | this DBObject dbObject,
51 | Transaction tr,
52 | OpenMode mode = OpenMode.ForRead)
53 | {
54 | Assert.IsNotNull(dbObject, nameof(dbObject));
55 | Assert.IsNotNull(tr, nameof(tr));
56 |
57 | if (dbObject.ExtensionDictionary.IsNull)
58 | {
59 | dbObject.OpenForWrite(tr);
60 | dbObject.CreateExtensionDictionary();
61 | }
62 | return (DBDictionary)tr.GetObject(dbObject.ExtensionDictionary, mode);
63 | }
64 |
65 | ///
66 | /// Tries to get the xrecord data of the extension dictionary of the object.
67 | ///
68 | /// Instance to which the method applies.
69 | /// Transaction or OpenCloseTransaction to use.
70 | /// Xrecord key.
71 | /// Output data.
72 | /// The xrecord data or null if the xrecord does not exists.
73 | /// Thrown if is null.
74 | /// Thrown if is null.
75 | /// Thrown if is null or empty.
76 | public static bool TryGetXDictionaryXrecordData(this DBObject source, Transaction tr, string key, out ResultBuffer data)
77 | {
78 | Assert.IsNotNull(source, nameof(source));
79 | Assert.IsNotNull(tr, nameof(tr));
80 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
81 |
82 | data = default;
83 | return
84 | source.TryGetExtensionDictionary(tr, out DBDictionary xdict) &&
85 | xdict.TryGetXrecordData(tr, key, out data);
86 | }
87 |
88 | ///
89 | /// Sets the xrecord data of the extension dictionary of the object.
90 | ///
91 | /// Instance to which the method applies.
92 | /// Transaction or OpenCloseTransaction to use.
93 | /// The xrecord key.
94 | /// The new xrecord data.
95 | /// The got or newlycreated Xrecord.
96 | /// Thrown if is null.
97 | /// Thrown if is null.
98 | /// Thrown if is null or empty.
99 | public static Xrecord SetXDictionaryXrecordData(this DBObject target, Transaction tr, string key, params TypedValue[] values)
100 | {
101 | Assert.IsNotNull(target, nameof(target));
102 | Assert.IsNotNull(tr, nameof(tr));
103 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
104 |
105 | return target.SetXDictionaryXrecordData(tr, key, new ResultBuffer(values));
106 | }
107 |
108 | ///
109 | /// Sets the xrecord data of the extension dictionary of the object.
110 | ///
111 | /// Instance to which the method applies.
112 | /// Transaction or OpenCloseTransaction to use.
113 | /// The xrecord key.
114 | /// The new xrecord data.
115 | /// The got or newlycreated Xrecord.
116 | /// Thrown if is null.
117 | /// Thrown if is null.
118 | /// Thrown if is null or empty.
119 | public static Xrecord SetXDictionaryXrecordData(this DBObject target, Transaction tr, string key, ResultBuffer data)
120 | {
121 | Assert.IsNotNull(target, nameof(target));
122 | Assert.IsNotNull(tr, nameof(tr));
123 | Assert.IsNotNullOrWhiteSpace(key, nameof(key));
124 |
125 | return target.GetOrCreateExtensionDictionary(tr).SetXrecordData(tr, key, data);
126 | }
127 |
128 | ///
129 | /// Sets the object extended data (xdata) for the application.
130 | ///
131 | /// Instance to which the method applies.
132 | /// Transaction or OpenCloseTransaction to use.
133 | /// Extended data (the first TypedValue must be: (1001, <regAppName>)).
134 | /// Thrown if is null.
135 | /// Thrown if is null.
136 | /// Thrown if is null.
137 | /// eBadDxfSequence is thrown if the result buffer is not valid.
138 | public static void SetXDataForApplication(this DBObject target, Transaction tr, ResultBuffer data)
139 | {
140 | Assert.IsNotNull(target, nameof(target));
141 | Assert.IsNotNull(tr, nameof(tr));
142 | Assert.IsNotNull(data, nameof(data));
143 |
144 | var db = target.Database;
145 | var typedValue = data.AsArray()[0];
146 | if (typedValue.TypeCode != 1001)
147 | throw new Exception(ErrorStatus.BadDxfSequence);
148 | string appName = (string)typedValue.Value;
149 | var regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
150 | if (!regAppTable.Has(appName))
151 | {
152 | var regApp = new RegAppTableRecord
153 | {
154 | Name = appName
155 | };
156 | tr.GetObject(db.RegAppTableId, OpenMode.ForWrite);
157 | regAppTable.Add(regApp);
158 | tr.AddNewlyCreatedDBObject(regApp, true);
159 | }
160 | target.XData = data;
161 | }
162 |
163 | ///
164 | /// Opens the object for write.
165 | ///
166 | /// Instance to which the method applies.
167 | /// Transaction or OpenCloseTransaction to use.
168 | /// Thrown if is null.
169 | /// Thrown if is null.
170 | public static void OpenForWrite(this DBObject dbObj, Transaction tr)
171 | {
172 | Assert.IsNotNull(dbObj, nameof(dbObj));
173 | Assert.IsNotNull(tr, nameof(tr));
174 |
175 | if (!dbObj.IsWriteEnabled)
176 | {
177 | tr.GetObject(dbObj.ObjectId, OpenMode.ForWrite);
178 | }
179 | }
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DBTextExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace Gile.AutoCAD.R20.Extension
8 | {
9 | ///
10 | /// Provides extension methods for the DBText type.
11 | ///
12 | public static class DBTextExtension
13 | {
14 | ///
15 | /// Gets the 'text box' of the DBText instance.
16 | ///
17 | /// Instance to which the method applies.
18 | /// Lower left corner of the box ('DBText coordinate system').
19 | /// Upper right corner of the box ('DBText coordinate system')
20 | /// Transformation matrix from 'DBText coordinate system' to WCS.
21 | public static void GetTextBox(this DBText dbText, out Point3d point1, out Point3d point2, out Matrix3d transform)
22 | {
23 | Assert.IsNotNull(dbText, nameof(dbText));
24 |
25 | int mirrored = dbText.IsMirroredInX ? 2 : 0;
26 | mirrored |= dbText.IsMirroredInY ? 4 : 0;
27 | var rb = new ResultBuffer(
28 | new TypedValue(1, dbText.TextString),
29 | new TypedValue(40, dbText.Height),
30 | new TypedValue(41, dbText.WidthFactor),
31 | new TypedValue(51, dbText.Oblique),
32 | new TypedValue(7, dbText.TextStyleName),
33 | new TypedValue(71, mirrored),
34 | new TypedValue(72, (int)dbText.HorizontalMode),
35 | new TypedValue(73, (int)dbText.VerticalMode));
36 | var pt1 = new double[3];
37 | var pt2 = new double[3];
38 | acedTextBox(rb.UnmanagedObject, pt1, pt2);
39 | point1 = new Point3d(pt1);
40 | point2 = new Point3d(pt2);
41 | transform =
42 | Matrix3d.Displacement(dbText.Position.GetAsVector()) *
43 | Matrix3d.Rotation(dbText.Rotation, dbText.Normal, Point3d.Origin) *
44 | Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, dbText.Normal));
45 | }
46 |
47 | ///
48 | /// Gets the center of the text bounding box.
49 | ///
50 | /// Instance to which the method applies.
51 | /// The center point of the text.
52 | /// Thrown if is null.
53 | public static Point3d GetTextBoxCenter(this DBText dbText)
54 | {
55 | dbText.GetTextBox(out Point3d point1, out Point3d point2, out Matrix3d xform);
56 | return new Point3d(
57 | (point1.X + point2.X) / 2.0,
58 | (point1.Y + point2.Y) / 2.0,
59 | (point1.Z + point2.Z) / 2.0)
60 | .TransformBy(xform);
61 | }
62 |
63 | ///
64 | /// Gets the points at corners of the text bounding box.
65 | ///
66 | /// Instance to which the method applies.
67 | /// The points(counter-clockwise from lower left).
68 | /// Thrown if is null.
69 | public static Point3d[] GetTextBoxCorners(this DBText dbText)
70 | {
71 | dbText.GetTextBox(out Point3d point1, out Point3d point2, out Matrix3d xform);
72 | return new[]
73 | {
74 | point1.TransformBy(xform),
75 | new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform),
76 | point2.TransformBy(xform),
77 | new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform)
78 | };
79 | }
80 |
81 | ///
82 | /// Mirrors the text honoring the value of MIRRTEXT system variable.
83 | ///
84 | /// Instance to which the method applies.
85 | /// Transaction or OpenCloseTransaction to use.
86 | /// Axis of the mirroring operation.
87 | /// Value indicating if the source block reference have to be erased.
88 | /// Thrown if is null.
89 | /// Thrown if is null.
90 | /// Thrown if is null.
91 | public static void Mirror(this DBText source, Transaction tr, Line3d axis, bool eraseSource)
92 | {
93 | Assert.IsNotNull(source, nameof(source));
94 | Assert.IsNotNull(tr, nameof(tr));
95 | Assert.IsNotNull(axis, nameof(axis));
96 |
97 | var db = source.Database;
98 | DBText mirrored;
99 | if (eraseSource)
100 | {
101 | mirrored = source;
102 | mirrored.OpenForWrite(tr);
103 | }
104 | else
105 | {
106 | var ids = new ObjectIdCollection(new[] { source.ObjectId });
107 | var mapping = new IdMapping();
108 | db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
109 | mirrored = (DBText)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
110 | }
111 | mirrored.TransformBy(Matrix3d.Mirroring(axis));
112 | if (!db.Mirrtext)
113 | {
114 | var pts = mirrored.GetTextBoxCorners();
115 | var cen = new LineSegment3d(pts[0], pts[2]).MidPoint;
116 | var rotAxis = Math.Abs(axis.Direction.X) < Math.Abs(axis.Direction.Y) ?
117 | pts[0].GetVectorTo(pts[3]) :
118 | pts[0].GetVectorTo(pts[1]);
119 | mirrored.TransformBy(Matrix3d.Rotation(Math.PI, rotAxis, cen));
120 | }
121 | }
122 |
123 | ///
124 | /// P/Invokes the unmanaged acedTextBox method.
125 | ///
126 | /// ResultBuffer cotaining the DBtext DXF definition.
127 | /// Minimum point of the bounding box.
128 | /// Maximum point of the bounding box.
129 | /// RTNORM, if succeeds; RTERROR, otherwise.
130 | [System.Security.SuppressUnmanagedCodeSecurity]
131 | [DllImport("accore.dll", CharSet = CharSet.Unicode,
132 | CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTextBox")]
133 | static extern IntPtr acedTextBox(IntPtr rb, double[] point1, double[] point2);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DisposableList.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace Gile.AutoCAD.R20.Extension
8 | {
9 | ///
10 | /// Describes a list of disposable values.
11 | ///
12 | /// Type of the items.
13 | public class DisposableList : List, IDisposableCollection
14 | where T : IDisposable
15 | {
16 | ///
17 | /// Creates a new empty instance.
18 | ///
19 | public DisposableList() { }
20 |
21 | ///
22 | /// Creates a new instance by copying the sequence items.
23 | ///
24 | /// Sequence whose elements are copied into the new set.
25 | public DisposableList(IEnumerable collection)
26 | : base(collection) { }
27 |
28 | ///
29 | /// Creates a new instance by copying the collection items.
30 | ///
31 | /// Collection whose elements are copied into the new set.
32 | public DisposableList(DBObjectCollection collection)
33 | : base((IEnumerable)collection.Cast()) { }
34 |
35 | ///
36 | /// Creates a new empty instance.
37 | ///
38 | /// Initial cpacity
39 | public DisposableList(int capacity)
40 | : base(capacity) { }
41 |
42 | ///
43 | /// Disposes of all items.
44 | ///
45 | public void Dispose()
46 | {
47 | var list = this.ToList();
48 | Clear();
49 | list.DisposeAll();
50 | }
51 |
52 | ///
53 | /// Removes items from the active instance.
54 | ///
55 | /// Items to remove.
56 | /// The sequence of effectively removed items.
57 | public IEnumerable RemoveRange(IEnumerable items)
58 | {
59 | Assert.IsNotNull(items, nameof(items));
60 | foreach (T item in items)
61 | {
62 | if (Remove(item))
63 | {
64 | yield return item;
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DisposableSet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Gile.AutoCAD.R20.Extension
6 | {
7 | ///
8 | /// Describes a set of disposable values.
9 | ///
10 | /// Type of the items.
11 | public class DisposableSet : HashSet, IDisposableCollection
12 | where T : IDisposable
13 | {
14 | ///
15 | /// Creates a new empty instance using the default comparer.
16 | ///
17 | public DisposableSet()
18 | { }
19 |
20 | ///
21 | /// Creates a new instance using the default comparer by copying the sequence items.
22 | ///
23 | /// Sequence whose elements are copied into the new set.
24 | public DisposableSet(IEnumerable collection)
25 | : base(collection)
26 | { }
27 |
28 | ///
29 | /// Creates a new empty instance using the specified comparer.
30 | ///
31 | /// IEqualityComparer<T> implementation.
32 | public DisposableSet(IEqualityComparer comparer)
33 | : base(comparer)
34 | { }
35 |
36 | ///
37 | /// Creates a new instance using the specified comparer by copying the sequence items.
38 | ///
39 | /// Sequence whose elements are copied into the new set.
40 | /// IEqualityComparer<T> implementation.
41 | public DisposableSet(IEnumerable collection, IEqualityComparer comparer)
42 | : base(collection, comparer)
43 | { }
44 |
45 | ///
46 | /// Disposes of all items.
47 | ///
48 | public void Dispose()
49 | {
50 | var list = this.ToList();
51 | Clear();
52 | list.DisposeAll();
53 | }
54 |
55 | ///
56 | /// Adds items to the active instance.
57 | ///
58 | /// Items to add.
59 | public void AddRange(IEnumerable items)
60 | {
61 | Assert.IsNotNull(items, nameof(items));
62 |
63 | UnionWith(items);
64 | }
65 |
66 | ///
67 | /// Removes items from the active instance.
68 | ///
69 | /// Items to remove.
70 | /// The sequence of effectively removed items.
71 | public IEnumerable RemoveRange(IEnumerable items)
72 | {
73 | Assert.IsNotNull(items, nameof(items));
74 |
75 | ExceptWith(items);
76 | return items;
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/DocumentCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices;
2 |
3 | using System;
4 | using System.Threading.Tasks;
5 |
6 | using AcRx = Autodesk.AutoCAD.Runtime;
7 |
8 | namespace Gile.AutoCAD.R20.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the DocumentCollection type.
12 | ///
13 | public static class DocumentCollectionExtension
14 | {
15 | ///
16 | /// Invokes an action in the document context that can be safely called from the application context.
17 | /// Credit: Tony Tanzillo.
18 | ///
19 | /// Documents collection.
20 | /// Action to invoke.
21 | /// Task.CompletedTask.
22 | /// Thrown if is null;
23 | /// Thrown if is null;
24 | /// eNoDocument thrown if no active document.
25 | /// eInvalidContext thrown if not called from application context.
26 | /// Must be called in a try / catch statement.
27 | public static async Task InvokeAsCommandAsync(this DocumentCollection docs, Action action)
28 | {
29 | if (docs == null)
30 | throw new ArgumentNullException(nameof(docs));
31 |
32 | if (action == null)
33 | throw new ArgumentNullException(nameof(action));
34 |
35 | Document doc = docs.MdiActiveDocument ?? throw new AcRx.Exception(AcRx.ErrorStatus.NoDocument);
36 |
37 | if (!docs.IsApplicationContext)
38 | throw new AcRx.Exception(AcRx.ErrorStatus.InvalidContext);
39 |
40 | Task task = Task.CompletedTask;
41 | await docs.ExecuteInCommandContextAsync(
42 | (_) =>
43 | {
44 | try
45 | {
46 | action(doc);
47 | return task;
48 | }
49 | catch (Exception ex)
50 | {
51 | return task = Task.FromException(ex);
52 | }
53 | },
54 | null
55 | );
56 | if (task.IsFaulted)
57 | {
58 | throw task.Exception;
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/EditorExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices.Core;
2 | using Autodesk.AutoCAD.DatabaseServices;
3 | using Autodesk.AutoCAD.EditorInput;
4 | using Autodesk.AutoCAD.Geometry;
5 |
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | namespace Gile.AutoCAD.R20.Extension
10 | {
11 | ///
12 | /// Provides extension methods for the Editor type.
13 | ///
14 | public static class EditorExtension
15 | {
16 | #region Zoom
17 |
18 | ///
19 | /// Zooms to given extents in the current viewport.
20 | ///
21 | /// Instance to which the method applies.
22 | /// Extents of the zoom.
23 | /// Thrown if is null.
24 | public static void Zoom(this Editor ed, Extents3d ext)
25 | {
26 | Assert.IsNotNull(ed, nameof(ed));
27 |
28 | using (ViewTableRecord view = ed.GetCurrentView())
29 | {
30 | ext.TransformBy(view.WorldToEye());
31 | view.Width = ext.MaxPoint.X - ext.MinPoint.X;
32 | view.Height = ext.MaxPoint.Y - ext.MinPoint.Y;
33 | view.CenterPoint = new Point2d(
34 | (ext.MaxPoint.X + ext.MinPoint.X) / 2.0,
35 | (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
36 | ed.SetCurrentView(view);
37 | }
38 | }
39 |
40 | ///
41 | /// Zooms to the extents of the current viewport.
42 | ///
43 | /// Instance to which the method applies.
44 | /// Thrown if is null.
45 | public static void ZoomExtents(this Editor ed)
46 | {
47 | Assert.IsNotNull(ed, nameof(ed));
48 |
49 | Database db = ed.Document.Database;
50 | db.UpdateExt(false);
51 | Extents3d ext = (short)Application.GetSystemVariable("cvport") == 1 ?
52 | new Extents3d(db.Pextmin, db.Pextmax) :
53 | new Extents3d(db.Extmin, db.Extmax);
54 | ed.Zoom(ext);
55 | }
56 |
57 | ///
58 | /// Zooms to the given window.
59 | ///
60 | /// Instance to which the method applies.
61 | /// First window corner.
62 | /// Opposite window corner.
63 | /// Thrown if is null.
64 | public static void ZoomWindow(this Editor ed, Point3d p1, Point3d p2)
65 | {
66 | Assert.IsNotNull(ed, nameof(ed));
67 |
68 | var extents = new Extents3d();
69 | extents.AddPoint(p1);
70 | extents.AddPoint(p2);
71 | ed.Zoom(extents);
72 | }
73 |
74 | ///
75 | /// Zooms to the specified entity collection.
76 | ///
77 | /// Instance to which the method applies.
78 | /// Collection of the entities ObjectId on which to zoom.
79 | /// Thrown if is null.
80 | public static void ZoomObjects(this Editor ed, IEnumerable ids)
81 | {
82 | Assert.IsNotNull(ed, nameof(ed));
83 | Assert.IsNotNull(ids, nameof(ids));
84 |
85 | using (Transaction tr = ed.Document.TransactionManager.StartOpenCloseTransaction())
86 | {
87 | Extents3d ext = ids
88 | .GetObjects(tr)
89 | .Select(ent => ent.Bounds)
90 | .Where(b => b.HasValue)
91 | .Select(b => b.Value)
92 | .Aggregate((e1, e2) => { e1.AddExtents(e2); return e1; });
93 | ed.Zoom(ext);
94 | tr.Commit();
95 | }
96 | }
97 |
98 | ///
99 | /// Zooms in current viewport to the specified scale.
100 | ///
101 | /// Instance to which the method applies.
102 | /// Scale.
103 | /// Thrown if is null.
104 | public static void ZoomScale(this Editor ed, double scale)
105 | {
106 | Assert.IsNotNull(ed, nameof(ed));
107 |
108 | using (ViewTableRecord view = ed.GetCurrentView())
109 | {
110 | view.Width /= scale;
111 | view.Height /= scale;
112 | ed.SetCurrentView(view);
113 | }
114 | }
115 |
116 | ///
117 | /// Zooms in current viewport to the specified scale and center.
118 | ///
119 | /// Instance to which the method applies.
120 | /// Viewport center.
121 | /// Scale (default = 1).
122 | /// Thrown if is null.
123 | public static void ZoomCenter(this Editor ed, Point3d center, double scale = 1.0)
124 | {
125 | Assert.IsNotNull(ed, nameof(ed));
126 |
127 | using (ViewTableRecord view = ed.GetCurrentView())
128 | {
129 | center = center.TransformBy(view.WorldToEye());
130 | view.Height /= scale;
131 | view.Width /= scale;
132 | view.CenterPoint = new Point2d(center.X, center.Y);
133 | ed.SetCurrentView(view);
134 | }
135 | }
136 |
137 | #endregion
138 |
139 | #region Selection
140 |
141 | ///
142 | /// Gets a selection set using the supplied prompt selection options, the supplied filter and the supplied predicate.
143 | ///
144 | /// Instance to which the method applies.
145 | /// Selection options.
146 | /// Selection filter
147 | /// Selection predicate.
148 | /// The selection result.
149 | /// Thrown if is null.
150 | /// Thrown if is null.
151 | public static PromptSelectionResult GetSelection(this Editor ed, PromptSelectionOptions options, SelectionFilter filter, System.Predicate predicate) =>
152 | GetPredicatedSelection(ed, predicate, options, filter);
153 |
154 | ///
155 | /// Gets a selection set using the supplied prompt selection options and the supplied predicate.
156 | ///
157 | /// Instance to which the method applies.
158 | /// Selection options.
159 | /// Selection predicate.
160 | /// The selection result.
161 | /// Thrown if is null.
162 | /// Thrown if is null.
163 | public static PromptSelectionResult GetSelection(this Editor ed, PromptSelectionOptions options, System.Predicate predicate) =>
164 | GetPredicatedSelection(ed, predicate, options);
165 |
166 | ///
167 | /// Gets a selection set using the supplied filter and the supplied predicate.
168 | ///
169 | /// Instance to which the method applies.
170 | /// Selection filter
171 | /// Selection predicate.
172 | /// The selection result.
173 | /// Thrown if is null.
174 | /// Thrown if is null.
175 | public static PromptSelectionResult GetSelection(this Editor ed, SelectionFilter filter, System.Predicate predicate) =>
176 | GetPredicatedSelection(ed, predicate, null, filter);
177 |
178 | ///
179 | /// Gets a selection set using the supplied predicate.
180 | ///
181 | /// Instance to which the method applies.
182 | /// Selection predicate.
183 | /// The selection result.
184 | /// Thrown if is null.
185 | /// Thrown if is null.
186 | public static PromptSelectionResult GetSelection(this Editor ed, System.Predicate predicate) =>
187 | GetPredicatedSelection(ed, predicate, null, null);
188 |
189 | private static PromptSelectionResult GetPredicatedSelection(
190 | Editor ed,
191 | System.Predicate predicate,
192 | PromptSelectionOptions options = null,
193 | SelectionFilter filter = null)
194 | {
195 | Assert.IsNotNull(ed, nameof(ed));
196 | Assert.IsNotNull(predicate, nameof(predicate));
197 |
198 | void onSelectionAdded(object sender, SelectionAddedEventArgs e)
199 | {
200 | var ids = e.AddedObjects.GetObjectIds();
201 | for (int i = 0; i < ids.Length; i++)
202 | {
203 | if (!predicate(ids[i]))
204 | {
205 | e.Remove(i);
206 | }
207 | }
208 | }
209 |
210 | PromptSelectionResult result;
211 | ed.SelectionAdded += onSelectionAdded;
212 | if (options == null)
213 | {
214 | if (filter == null)
215 | {
216 | result = ed.GetSelection();
217 | }
218 | else
219 | {
220 | result = ed.GetSelection(filter);
221 | }
222 | }
223 | else
224 | {
225 | if (filter == null)
226 | {
227 | result = ed.GetSelection(options);
228 | }
229 | else
230 | {
231 | result = ed.GetSelection(options, filter);
232 | }
233 | }
234 | ed.SelectionAdded -= onSelectionAdded;
235 | return result;
236 | }
237 |
238 | #endregion
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/EntityExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | namespace Gile.AutoCAD.R20.Extension
4 | {
5 | ///
6 | /// Provides extension methods for the Entity type.
7 | ///
8 | public static class EntityExtension
9 | {
10 | ///
11 | /// Evaluates if the owner of is a Layout.
12 | ///
13 | /// Instance to which the method applies.
14 | /// Transaction or OpenCloseTransaction to use.
15 | /// true, if the owner is a Layout; false, otherwise.
16 | /// Thrown if is null.
17 | /// Thrown if is null.
18 | public static bool IsOwnedByLayout(this Entity entity, Transaction tr)
19 | {
20 | Assert.IsNotNull(entity, nameof(entity));
21 | Assert.IsNotNull(entity, nameof(tr));
22 |
23 |
24 | var owner = tr.GetObject(entity.OwnerId, OpenMode.ForRead);
25 | return owner is BlockTableRecord btr && btr.IsLayout;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/Gile.AutoCAD.R20.Extension.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {32EBFF40-CE54-4B05-AEBA-2EEFFEDB443B}
8 | Library
9 | Properties
10 | Gile.AutoCAD.R20.Extension
11 | Gile.AutoCAD.R20.Extension
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | Program
25 | C:\Program Files\Autodesk\AutoCAD 2017\acad.exe
26 | /nologo /b "start.scr"
27 |
28 |
29 |
30 |
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 | bin\Release\Gile.AutoCAD.R20.Extension.xml
38 |
39 |
40 |
41 | F:\ObjectARX 2016\inc\AcCoreMgd.dll
42 | False
43 |
44 |
45 | F:\ObjectARX 2016\inc\AcDbMgd.dll
46 | False
47 |
48 |
49 | F:\ObjectARX 2016\inc\AcMgd.dll
50 | False
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
96 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/IDisposableCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Gile.AutoCAD.R20.Extension
5 | {
6 | ///
7 | /// Defines methods to add or removes items from a sequence of disposable objects.
8 | ///
9 | /// Type of the items.
10 | public interface IDisposableCollection : ICollection, IDisposable
11 | where T : IDisposable
12 | {
13 | ///
14 | /// Adds items to the sequence.
15 | ///
16 | /// Items to add.
17 | void AddRange(IEnumerable items);
18 |
19 | ///
20 | /// Removes items from the sequence.
21 | ///
22 | /// Items to remove.
23 | /// The sequence of removed items.
24 | IEnumerable RemoveRange(IEnumerable items);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/IEnumerableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gile.AutoCAD.R20.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the IEnumerable(T) type.
12 | ///
13 | public static class IEnumerableExtension
14 | {
15 | ///
16 | /// Opens the objects which type matches to the given one, and return them.
17 | ///
18 | /// Type of object to return.
19 | /// Sequence of ObjectIds.
20 | /// Transaction or OpenCloseTransaction to use.
21 | /// Open mode to obtain in.
22 | /// Value indicating whether to obtain erased objects.
23 | /// Value indicating if locked layers should be opened.
24 | /// The sequence of opened objects.
25 | /// Thrown if is null.
26 | /// Thrown if is null.
27 | public static IEnumerable GetObjects(
28 | this IEnumerable source,
29 | Transaction tr,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayers = false) where T : DBObject
33 | {
34 | Assert.IsNotNull(source, nameof(source));
35 | Assert.IsNotNull(tr, nameof(source));
36 |
37 | if (source.Any())
38 | {
39 | var rxClass = RXObject.GetClass(typeof(T));
40 | foreach (ObjectId id in source)
41 | {
42 | if (id.ObjectClass.IsDerivedFrom(rxClass) &&
43 | (!id.IsErased || openErased))
44 | {
45 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
46 | }
47 | }
48 | }
49 | }
50 |
51 | ///
52 | /// Upgrades the open mode of all objects in the sequence.
53 | ///
54 | /// Type of objects.
55 | /// Sequence of DBObjects to upgrade.
56 | /// Transaction or OpenCloseTransaction to use.
57 | /// The sequence of opened for write objects (objets on locked layers are discared).
58 | /// Thrown if is null.
59 | /// Thrown if is null.
60 | public static IEnumerable UpgradeOpen(this IEnumerable source, Transaction tr) where T : DBObject
61 | {
62 | Assert.IsNotNull(source, nameof(source));
63 |
64 | foreach (T item in source)
65 | {
66 | try
67 | {
68 | item.OpenForWrite(tr);
69 | }
70 | catch (Autodesk.AutoCAD.Runtime.Exception ex)
71 | {
72 | if (ex.ErrorStatus != ErrorStatus.OnLockedLayer)
73 | {
74 | throw;
75 | }
76 | continue;
77 | }
78 | yield return item;
79 | }
80 | }
81 |
82 | ///
83 | /// Disposes of all items of the sequence.
84 | ///
85 | /// Type of the items.
86 | /// Sequence of disposable objects.
87 | /// Thrown if is null.
88 | public static void DisposeAll(this IEnumerable source) where T : IDisposable
89 | {
90 | Assert.IsNotNull(source, nameof(source));
91 |
92 | if (source.Any())
93 | {
94 | System.Exception last = null;
95 | foreach (T item in source)
96 | {
97 | if (item != null)
98 | {
99 | try
100 | {
101 | item.Dispose();
102 | }
103 | catch (System.Exception ex)
104 | {
105 | last = last ?? ex;
106 | }
107 | }
108 | }
109 | if (last != null)
110 | {
111 | throw last;
112 | }
113 | }
114 | }
115 |
116 | ///
117 | /// Runs the action for each item of the collection.
118 | ///
119 | /// Type of the items.
120 | /// Sequence to process.
121 | /// Action to run.
122 | /// Thrown if is null.
123 | /// Thrown if is null.
124 | public static void ForEach(this IEnumerable source, Action action)
125 | {
126 | Assert.IsNotNull(source, nameof(source));
127 | Assert.IsNotNull(action, nameof(action));
128 |
129 | foreach (T item in source)
130 | {
131 | action(item);
132 | }
133 | }
134 |
135 | ///
136 | /// Runs the indexed action for each item of the collection.
137 | ///
138 | /// Type of the items.
139 | /// Sequence to process.
140 | /// Indexed action to run.
141 | /// Thrown if is null.
142 | /// Thrown if is null.
143 | public static void ForEach(this IEnumerable source, Action action)
144 | {
145 | Assert.IsNotNull(source, nameof(source));
146 | Assert.IsNotNull(action, nameof(action));
147 |
148 | int i = 0;
149 | foreach (T item in source)
150 | {
151 | action(item, i++);
152 | }
153 | }
154 |
155 | ///
156 | /// Gets the greatest item of the sequence using with the function returned values.
157 | ///
158 | /// Type the items.
159 | /// Type of the returned value of function.
160 | /// Sequence to which the method applies.
161 | /// Mapping function from TSource to TKey.
162 | /// Comparer used for the TKey type; uses Comparer<TKey>.Default if null or omitted.
163 | /// The greatest item in the sequence.
164 | /// Thrown if is null.
165 | /// Thrown if is null.
166 | public static TSource MaxBy(
167 | this IEnumerable source,
168 | Func selector,
169 | IComparer comparer = null)
170 | {
171 | Assert.IsNotNull(source, nameof(source));
172 | Assert.IsNotNull(selector, nameof(selector));
173 |
174 | comparer = comparer ?? Comparer.Default;
175 | using (var iterator = source.GetEnumerator())
176 | {
177 | if (!iterator.MoveNext())
178 | {
179 | throw new InvalidOperationException("Empty sequence");
180 | }
181 | var max = iterator.Current;
182 | var maxKey = selector(max);
183 | while (iterator.MoveNext())
184 | {
185 | var current = iterator.Current;
186 | var currentKey = selector(current);
187 | if (comparer.Compare(currentKey, maxKey) > 0)
188 | {
189 | max = current;
190 | maxKey = currentKey;
191 | }
192 | }
193 | return max;
194 | }
195 | }
196 |
197 | ///
198 | /// Gets the smallest item of the sequence using the with the function returned values.
199 | ///
200 | /// Type the items.
201 | /// Type of the returned value of function.
202 | /// Sequence to which the method applies.
203 | /// Mapping function from TSource to TKey.
204 | /// Comparer used for the TKey type; uses Comparer<TKey>.Default if null or omitted.
205 | /// The smallest item in the sequence.
206 | /// Thrown if is null.
207 | /// Thrown if is null.
208 | public static TSource MinBy(
209 | this IEnumerable source,
210 | Func selector,
211 | IComparer comparer = null)
212 | {
213 | Assert.IsNotNull(source, nameof(source));
214 | Assert.IsNotNull(selector, nameof(selector));
215 |
216 | comparer = comparer ?? Comparer.Default;
217 | using (var iterator = source.GetEnumerator())
218 | {
219 | if (!iterator.MoveNext())
220 | {
221 | throw new InvalidOperationException("Empty sequence");
222 | }
223 | var min = iterator.Current;
224 | var minKey = selector(min);
225 | while (iterator.MoveNext())
226 | {
227 | var current = iterator.Current;
228 | var currentKey = selector(current);
229 | if (comparer.Compare(currentKey, minKey) < 0)
230 | {
231 | min = current;
232 | minKey = currentKey;
233 | }
234 | }
235 | return min;
236 | }
237 | }
238 | }
239 | }
240 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/MTextExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | using System;
5 |
6 | namespace Gile.AutoCAD.R20.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the MText Type.
10 | ///
11 | public static class MTextExtension
12 | {
13 | ///
14 | /// Gets the points at corners of the mtext bounding box.
15 | ///
16 | /// Instance to which the method applies.
17 | /// The points (counter-clockwise from lower left).
18 | /// Thrown if is null.
19 | public static Point3d[] GetMTextBoxCorners(this MText mtext)
20 | {
21 | Assert.IsNotNull(mtext, nameof(mtext));
22 |
23 | double width = mtext.ActualWidth;
24 | double height = mtext.ActualHeight;
25 | Point3d point1, point2;
26 | switch (mtext.Attachment)
27 | {
28 | case AttachmentPoint.TopLeft:
29 | default:
30 | point1 = new Point3d(0.0, -height, 0.0);
31 | point2 = new Point3d(width, 0.0, 0.0);
32 | break;
33 | case AttachmentPoint.TopCenter:
34 | point1 = new Point3d(-width * 0.5, -height, 0.0);
35 | point2 = new Point3d(width * 0.5, 0.0, 0.0);
36 | break;
37 | case AttachmentPoint.TopRight:
38 | point1 = new Point3d(-width, -height, 0.0);
39 | point2 = new Point3d(0.0, 0.0, 0.0);
40 | break;
41 | case AttachmentPoint.MiddleLeft:
42 | point1 = new Point3d(0.0, -height * 0.5, 0.0);
43 | point2 = new Point3d(width, height * 0.5, 0.0);
44 | break;
45 | case AttachmentPoint.MiddleCenter:
46 | point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0);
47 | point2 = new Point3d(width * 0.5, height * 0.5, 0.0);
48 | break;
49 | case AttachmentPoint.MiddleRight:
50 | point1 = new Point3d(-width, -height * 0.5, 0.0);
51 | point2 = new Point3d(0.0, height * 0.5, 0.0);
52 | break;
53 | case AttachmentPoint.BottomLeft:
54 | point1 = new Point3d(0.0, 0.0, 0.0);
55 | point2 = new Point3d(width, height, 0.0);
56 | break;
57 | case AttachmentPoint.BottomCenter:
58 | point1 = new Point3d(-width * 0.5, 0.0, 0.0);
59 | point2 = new Point3d(width * 0.5, height, 0.0);
60 | break;
61 | case AttachmentPoint.BottomRight:
62 | point1 = new Point3d(-width, 0.0, 0.0);
63 | point2 = new Point3d(0.0, height, 0.0);
64 | break;
65 | }
66 |
67 | var xform =
68 | Matrix3d.Displacement(mtext.Location.GetAsVector()) *
69 | Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) *
70 | Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal));
71 |
72 | return new[]
73 | {
74 | point1.TransformBy(xform),
75 | new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform),
76 | point2.TransformBy(xform),
77 | new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform)
78 | };
79 | }
80 |
81 | ///
82 | /// Mirrors the mtext honoring the value of MIRRTEXT system variable.
83 | ///
84 | /// Instance to which the method applies.
85 | /// Transaction or OpenCloseTransaction to use.
86 | /// Axis of the mirroring operation.
87 | /// Value indicating if the source block reference have to be erased.
88 | /// Thrown if is null.
89 | /// Thrown if is null.
90 | /// Thrown if is null.
91 | public static void Mirror(this MText source, Transaction tr, Line3d axis, bool eraseSource)
92 | {
93 | Assert.IsNotNull(source, nameof(source));
94 | Assert.IsNotNull(tr, nameof(tr));
95 | Assert.IsNotNull(axis, nameof(axis));
96 |
97 | var db = source.Database;
98 | MText mirrored;
99 | if (eraseSource)
100 | {
101 | mirrored = source;
102 | if (!mirrored.IsWriteEnabled)
103 | {
104 | tr.GetObject(mirrored.ObjectId, OpenMode.ForWrite);
105 | }
106 | }
107 | else
108 | {
109 | var ids = new ObjectIdCollection(new[] { source.ObjectId });
110 | var mapping = new IdMapping();
111 | db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
112 | mirrored = (MText)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
113 | }
114 | mirrored.TransformBy(Matrix3d.Mirroring(axis));
115 |
116 | if (!db.Mirrtext)
117 | {
118 | var pts = mirrored.GetMTextBoxCorners();
119 | var cen = new LineSegment3d(pts[0], pts[2]).MidPoint;
120 | var rotAxis = Math.Abs(axis.Direction.X) < Math.Abs(axis.Direction.Y) ?
121 | pts[0].GetVectorTo(pts[3]) :
122 | pts[0].GetVectorTo(pts[1]);
123 | mirrored.TransformBy(Matrix3d.Rotation(Math.PI, rotAxis, cen));
124 | }
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/ObjectIdCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System.Collections.Generic;
5 |
6 | namespace Gile.AutoCAD.R20.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the ObjectIdCollection type.
10 | ///
11 | public static class ObjectIdCollectionExtension
12 | {
13 |
14 | ///
15 | /// Opens the objects which type matches to the given one, and return them.
16 | ///
17 | /// Type of objects to return.
18 | /// Instance to which the method applies.
19 | /// Transaction or OpenCloseTransaction to use.
20 | /// Open mode to obtain in.
21 | /// Value indicating whether to obtain erased objects.
22 | /// Value indicating if locked layers should be opened.
23 | /// The sequence of opened objects.
24 | /// Thrown if is null.
25 | /// Thrown if is null.
26 | public static IEnumerable GetObjects(
27 | this ObjectIdCollection source,
28 | Transaction tr,
29 | OpenMode mode = OpenMode.ForRead,
30 | bool openErased = false,
31 | bool forceOpenOnLockedLayers = false)
32 | where T : DBObject
33 | {
34 | Assert.IsNotNull(source, nameof(source));
35 | Assert.IsNotNull(tr, nameof(tr));
36 |
37 | if (0 < source.Count)
38 | {
39 | var rxClass = RXObject.GetClass(typeof(T));
40 | foreach (ObjectId id in source)
41 | {
42 | if ((id.ObjectClass == rxClass || id.ObjectClass.IsDerivedFrom(rxClass)) &&
43 | (!id.IsErased || openErased))
44 | {
45 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/ObjectIdExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Gile.AutoCAD.R20.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the ObjectId type.
10 | ///
11 | public static class ObjectIdExtension
12 | {
13 | ///
14 | /// Tries to open an AutoCAD object of the given type in the given open mode.
15 | ///
16 | /// Type of the output object.
17 | /// ObjectId to open.
18 | /// Transaction or OpenCloseTransaction to use.
19 | /// Output object.
20 | /// Open mode to obtain in.
21 | /// Value indicating whether to obtain erased objects.
22 | /// Value indicating if locked layers should be opened.
23 | /// true, if the operation succeeded; false, otherwise.
24 | /// eNullObjectId is thrown if equals ObjectId.Null.
25 | /// Thrown if is null.
26 | public static bool TryGetObject(
27 | this ObjectId id,
28 | Transaction tr,
29 | out T obj,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayer = false)
33 | where T : DBObject
34 | {
35 | Assert.IsNotObjectIdNull(id, nameof(id));
36 | Assert.IsNotNull(tr, nameof(tr));
37 |
38 | obj = default;
39 | if (!id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(T))))
40 | {
41 | return false;
42 | }
43 | obj = (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayer);
44 | return true;
45 | }
46 |
47 | ///
48 | /// Opens an AutoCAD object of the given type in the given open mode.
49 | ///
50 | /// Type of the object to return.
51 | /// ObjectId to open.
52 | /// Transaction or OpenCloseTransaction to use.
53 | /// Open mode to obtain in.
54 | /// Value indicating whether to obtain erased objects.
55 | /// Value indicating if locked layers should be opened.
56 | /// The object opened in given open mode.
57 | /// Thrown if the object type does not match the given type
58 | /// eNullObjectId is thrown if equals ObjectId.Null.
59 | /// Thrown if is null.
60 | public static T GetObject(
61 | this ObjectId id,
62 | Transaction tr,
63 | OpenMode mode = OpenMode.ForRead,
64 | bool openErased = false,
65 | bool forceOpenOnLockedLayer = false)
66 | where T : DBObject
67 | {
68 | Assert.IsNotObjectIdNull(id, nameof(id));
69 | Assert.IsNotNull(tr, nameof(tr));
70 |
71 | return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayer);
72 | }
73 |
74 | ///
75 | /// Get the DXF definition data (like AutoLISP entget function).
76 | ///
77 | /// Instance to which the method applies.
78 | /// The DXF data.
79 | /// Thrown in case of invalid objectId.
80 | public static ResultBuffer EntGet(this ObjectId id)
81 | {
82 | var errorStatus = acdbGetAdsName(out AdsName ename, id);
83 | if (errorStatus != ErrorStatus.OK)
84 | {
85 | throw new Exception(errorStatus);
86 | }
87 | var result = acdbEntGet(ename);
88 | if (result != System.IntPtr.Zero)
89 | {
90 | return ResultBuffer.Create(result, true);
91 | }
92 | return null;
93 | }
94 |
95 | // Replace the DLL name according to the AutoCAD targeted version
96 | // 2013-2014: "acdb19.dll"
97 | // 2015-2016: "acdb20.dll"
98 | // 2017: "acdb21.dll"
99 | // 2018: "acdb22.dll"
100 | // 2019-2020: "acdb23.dll"
101 | // 2021-2024: "acdb24.dll"
102 | // Replace the EntryPoint according to AutoCAD plateform
103 | // 32 bits: "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z"
104 | // 64 bits: "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z"
105 | [System.Security.SuppressUnmanagedCodeSecurity]
106 | [DllImport("acdb24.dll", CallingConvention = CallingConvention.Cdecl,
107 | EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
108 | private static extern ErrorStatus acdbGetAdsName(out AdsName ename, ObjectId id);
109 |
110 | [System.Security.SuppressUnmanagedCodeSecurity]
111 | [DllImport("accore.dll", CallingConvention = CallingConvention.Cdecl,
112 | EntryPoint = "acdbEntGet")]
113 | private static extern System.IntPtr acdbEntGet(AdsName ename);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/PolylineExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace Gile.AutoCAD.R20.Extension
8 | {
9 | ///
10 | /// Enumeration of offset side options
11 | ///
12 | public enum OffsetSide
13 | {
14 | ///
15 | /// Inside.
16 | ///
17 | In,
18 | ///
19 | /// Outside.
20 | ///
21 | Out,
22 | ///
23 | /// Left side.
24 | ///
25 | Left,
26 | ///
27 | /// Right side.
28 | ///
29 | Right,
30 | ///
31 | /// Both sides.
32 | ///
33 | Both
34 | }
35 |
36 | // credits to Tony 'TheMaster' Tanzillo
37 | // http://www.theswamp.org/index.php?topic=31862.msg494503#msg494503
38 |
39 | ///
40 | /// Provides the Offset() extension method for the Polyline type
41 | ///
42 | public static class PolylineExtension
43 | {
44 | ///
45 | /// Offset the source polyline to specified side(s).
46 | ///
47 | /// Instance to which the method applies.
48 | /// Offset distance.
49 | /// Offset side(s).
50 | /// A polyline sequence resulting from the offset of the source polyline.
51 | /// Thrown if is null.
52 | public static IEnumerable Offset(this Polyline source, double offsetDist, OffsetSide side)
53 | {
54 | Assert.IsNotNull(source, nameof(source));
55 |
56 | offsetDist = Math.Abs(offsetDist);
57 | using (var plines = new DisposableSet())
58 | {
59 | IEnumerable offsetRight = source.GetOffsetCurves(offsetDist).Cast();
60 | plines.AddRange(offsetRight);
61 | IEnumerable offsetLeft = source.GetOffsetCurves(-offsetDist).Cast();
62 | plines.AddRange(offsetLeft);
63 | double areaRight = offsetRight.Select(pline => pline.Area).Sum();
64 | double areaLeft = offsetLeft.Select(pline => pline.Area).Sum();
65 | switch (side)
66 | {
67 | case OffsetSide.In:
68 | return plines.RemoveRange(
69 | areaRight < areaLeft ? offsetRight : offsetLeft);
70 | case OffsetSide.Out:
71 | return plines.RemoveRange(
72 | areaRight < areaLeft ? offsetLeft : offsetRight);
73 | case OffsetSide.Left:
74 | return plines.RemoveRange(offsetLeft);
75 | case OffsetSide.Right:
76 | return plines.RemoveRange(offsetRight);
77 | case OffsetSide.Both:
78 | plines.Clear();
79 | return offsetRight.Concat(offsetLeft);
80 | default:
81 | return null;
82 | }
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // Les informations générales relatives à un assembly dépendent de
6 | // l'ensemble d'attributs suivant. Changez les valeurs de ces attributs pour modifier les informations
7 | // associées à un assembly.
8 | [assembly: AssemblyTitle("Gile.AutoCAD.R20.Extension")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("gileCAD")]
12 | [assembly: AssemblyProduct("Gile.AutoCAD.R20.Extension")]
13 | [assembly: AssemblyCopyright("Copyright © Gilles Chanteau 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
18 | // aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
19 | // COM, affectez la valeur true à l'attribut ComVisible sur ce type.
20 | [assembly: ComVisible(false)]
21 |
22 | // Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
23 | [assembly: Guid("32ebff40-ce54-4b05-aeba-2eeffedb443b")]
24 |
25 | // Les informations de version pour un assembly se composent des quatre valeurs suivantes :
26 | //
27 | // Version principale
28 | // Version secondaire
29 | // Numéro de build
30 | // Révision
31 | //
32 | // Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
33 | // en utilisant '*', comme indiqué ci-dessous :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("2.0.0.0")]
36 | [assembly: AssemblyFileVersion("2.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/ResultBufferExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Gile.AutoCAD.Extension
8 | {
9 | internal class ResultBufferExtension
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/SymbolTableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace Gile.AutoCAD.R20.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the SymbolTable type.
10 | ///
11 | public static class SymbolTableExtension
12 | {
13 | ///
14 | /// Opens the table records in the given open mode.
15 | ///
16 | /// Type of returned object.
17 | /// Instance to which the method applies.
18 | /// Transaction or OpenCloseTransaction to use.
19 | /// Open mode to obtain in.
20 | /// Value indicating whether to obtain erased objects.
21 | /// The sequence of records.
22 | /// Thrown if is null.
23 | /// Thrown if is null.
24 | public static IEnumerable GetObjects(this SymbolTable source, Transaction tr, OpenMode mode = OpenMode.ForRead, bool openErased = false)
25 | where T : SymbolTableRecord
26 | {
27 | Assert.IsNotNull(source, nameof(source));
28 | Assert.IsNotNull(tr, nameof(tr));
29 |
30 | foreach (ObjectId id in openErased ? source.IncludingErased : source)
31 | {
32 | yield return (T)tr.GetObject(id, mode, openErased, false);
33 | }
34 | }
35 |
36 | ///
37 | /// Purges the unreferenced symbol table records.
38 | ///
39 | /// Instance to which the method applies.
40 | /// Transaction or OpenCloseTransaction to use.
41 | /// The number of pruged records.
42 | /// Thrown if is null.
43 | /// Thrown if is null.
44 | public static int Purge(this SymbolTable symbolTable, Transaction tr)
45 | {
46 | Assert.IsNotNull(symbolTable, nameof(symbolTable));
47 | Assert.IsNotNull(tr, nameof(tr));
48 |
49 | Database db = symbolTable.Database;
50 | int cnt = 0;
51 | var unpurgeable = new HashSet();
52 | while (true)
53 | {
54 | var ids = new ObjectIdCollection(symbolTable.Cast().Except(unpurgeable).ToArray());
55 | db.Purge(ids);
56 | if (ids.Count == 0)
57 | {
58 | break;
59 | }
60 | foreach (ObjectId id in ids)
61 | {
62 | try
63 | {
64 | tr.GetObject(id, OpenMode.ForWrite).Erase();
65 | cnt++;
66 | }
67 | catch
68 | {
69 | unpurgeable.Add(id);
70 | }
71 | }
72 | }
73 | return cnt;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R20.Extension/WorkingDatabase.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 |
5 | namespace Gile.AutoCAD.R20.Extension
6 | {
7 | ///
8 | /// Provides a safe way to temporarily set the working database.
9 | /// Credits Tony Tanzillo: https://forums.autodesk.com/t5/net/want-to-have-c-program-to-modify-dwg-and-save-into-dwg-format/m-p/12439905/highlight/true#M79788
10 | ///
11 | public class WorkingDatabase : IDisposable
12 | {
13 | Database previous;
14 |
15 | ///
16 | /// Creates a new instance of WorkingDatabase.
17 | ///
18 | /// Database to be temporarily set as working database.
19 | public WorkingDatabase(Database newWorkingDb)
20 | {
21 | Assert.IsNotNull(newWorkingDb, nameof(newWorkingDb));
22 |
23 | Database current = HostApplicationServices.WorkingDatabase;
24 | if (newWorkingDb != current)
25 | {
26 | previous = current;
27 | HostApplicationServices.WorkingDatabase = newWorkingDb;
28 | }
29 | }
30 |
31 | ///
32 | /// Restores the previous working database.
33 | ///
34 | public void Dispose()
35 | {
36 | if (previous != null)
37 | {
38 | HostApplicationServices.WorkingDatabase = previous;
39 | previous = null;
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/AbstractViewTableRecordExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | namespace Gile.AutoCAD.R25.Extension
5 | {
6 | ///
7 | /// Provides extension for the AbstractViewTableRecord type.
8 | ///
9 | public static class AbstractViewTableRecordExtension
10 | {
11 | ///
12 | /// Gets the transformation matrix from the view Display Coordinate System (DCS) to World Coordinate System (WCS).
13 | ///
14 | /// Instance to which the method applies.
15 | /// The DCS to WCS transformation matrix.
16 | /// Thrown if is null.
17 | public static Matrix3d EyeToWorld(this AbstractViewTableRecord view)
18 | {
19 | System.ArgumentNullException.ThrowIfNull(view);
20 |
21 | return
22 | Matrix3d.Rotation(-view.ViewTwist, view.ViewDirection, view.Target) *
23 | Matrix3d.Displacement(view.Target.GetAsVector()) *
24 | Matrix3d.PlaneToWorld(view.ViewDirection);
25 | }
26 |
27 | ///
28 | /// Gets the transformation matrix from World Coordinate System (WCS) to the view Display Coordinate System (DCS).
29 | ///
30 | /// Instance to which the method applies.
31 | /// The WCS to DCS transformation matrix.
32 | /// Thrown if is null.
33 | public static Matrix3d WorldToEye(this AbstractViewTableRecord view)
34 | {
35 | System.ArgumentNullException.ThrowIfNull(view);
36 |
37 | return
38 | Matrix3d.WorldToPlane(view.ViewDirection) *
39 | Matrix3d.Displacement(view.Target.GetAsVector().Negate()) *
40 | Matrix3d.Rotation(view.ViewTwist, view.ViewDirection, view.Target);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/Active.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices.Core;
2 | using Autodesk.AutoCAD.DatabaseServices;
3 | using Autodesk.AutoCAD.EditorInput;
4 |
5 | using AcAp = Autodesk.AutoCAD.ApplicationServices;
6 |
7 | // Inspired by Scott McFarlane
8 | // https://www.autodesk.com/autodesk-university/class/Being-Remarkable-C-NET-AutoCAD-Developer-2015#handout
9 |
10 | namespace Gile.AutoCAD.R25.Extension
11 | {
12 | ///
13 | /// Provides easy access to several "active" objects in AutoCAD runtime environment.
14 | ///
15 | public static class Active
16 | {
17 | ///
18 | /// Gets the active Document object.
19 | ///
20 | public static AcAp.Document Document => Application.DocumentManager.MdiActiveDocument;
21 |
22 | ///
23 | /// Gets the active Database object.
24 | ///
25 | public static Database Database => Document.Database;
26 |
27 | ///
28 | /// Gets the active Editor object.
29 | ///
30 | public static Editor Editor => Document.Editor;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/AttributeCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Collections.Generic;
4 |
5 | namespace Gile.AutoCAD.R25.Extension
6 | {
7 | ///
8 | /// Provides extension methods for the AttributeCollection type.
9 | ///
10 | public static class AttributeCollectionExtension
11 | {
12 | ///
13 | /// Opens the attribute references in the given open mode.
14 | ///
15 | /// Attribute collection.
16 | /// Transaction or OpenCloseTransaction to use.
17 | /// Open mode to obtain in.
18 | /// Value indicating whether to obtain erased objects.
19 | /// Value indicating if locked layers should be opened.
20 | /// The sequence of attribute references.
21 | /// Thrown if is null.
22 | /// Thrown if is null.
23 | public static IEnumerable GetObjects(
24 | this AttributeCollection source,
25 | Transaction tr,
26 | OpenMode mode = OpenMode.ForRead,
27 | bool openErased = false,
28 | bool forceOpenOnLockedLayers = false)
29 | {
30 | System.ArgumentNullException.ThrowIfNull(source);
31 | System.ArgumentNullException.ThrowIfNull(tr);
32 |
33 | if (source.Count > 0)
34 | {
35 | foreach (ObjectId id in source)
36 | {
37 | if (!id.IsErased || openErased)
38 | {
39 | yield return (AttributeReference)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
40 | }
41 | }
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/BlockTableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | namespace Gile.AutoCAD.R25.Extension
4 | {
5 | ///
6 | /// Provides extension methods for the BlockTable type.
7 | ///
8 | public static class BlockTableExtension
9 | {
10 | ///
11 | /// Gets the objectId of a block definition (BlockTableRecord) from its name.
12 | /// If the block is not found in the block table, a dwg file is searched in the support paths and added to the block table.
13 | ///
14 | /// Block table.
15 | /// Block name.
16 | /// The ObjectId of the block table record or ObjectId.Null if not found.
17 | /// Thrown if is null.
18 | /// Thrown if is null or empty.
19 | public static ObjectId GetBlock(this BlockTable blockTable, string blockName)
20 | {
21 | System.ArgumentNullException.ThrowIfNull(blockTable);
22 | System.ArgumentException.ThrowIfNullOrWhiteSpace(blockName);
23 |
24 | if (blockTable.Has(blockName))
25 | return blockTable[blockName];
26 | try
27 | {
28 | string blockPath = HostApplicationServices.Current.FindFile(blockName + ".dwg", blockTable.Database, FindFileHint.Default);
29 | using var tmpDb = new Database(false, true);
30 | tmpDb.ReadDwgFile(blockPath, FileOpenMode.OpenForReadAndAllShare, true, null);
31 | return blockTable.Database.Insert(blockName, tmpDb, true);
32 | }
33 | catch
34 | {
35 | return ObjectId.Null;
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/BlockTableRecordExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 | using Autodesk.AutoCAD.Runtime;
4 |
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gile.AutoCAD.R25.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the BlockTableRecord type.
12 | ///
13 | public static class BlockTableRecordExtension
14 | {
15 | ///
16 | /// Opens the entities which type matches to the given one, and return them.
17 | ///
18 | /// Type of objects to return.
19 | /// Block table record.
20 | /// Transaction or OpenCloseTransaction to use.
21 | /// Open mode to obtain in.
22 | /// Value indicating whether to obtain erased objects.
23 | /// Value indicating if locked layers should be opened.
24 | /// The sequence of opened objects.
25 | /// Thrown if is null.
26 | /// Thrown if is null.
27 | public static IEnumerable GetObjects(
28 | this BlockTableRecord btr,
29 | Transaction tr,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayers = false) where T : Entity
33 | {
34 | System.ArgumentNullException.ThrowIfNull(btr);
35 | System.ArgumentNullException.ThrowIfNull(tr);
36 |
37 | var source = openErased ? btr.IncludingErased : btr;
38 | if (typeof(T) == typeof(Entity))
39 | {
40 | foreach (ObjectId id in source)
41 | {
42 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
43 | }
44 | }
45 | else
46 | {
47 | var rxClass = RXObject.GetClass(typeof(T));
48 | foreach (ObjectId id in source)
49 | {
50 | if (id.ObjectClass.IsDerivedFrom(rxClass))
51 | {
52 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// Appends the entities to the BlockTableRecord.
60 | ///
61 | /// Instance to which the method applies.
62 | /// Transaction or OpenCloseTransaction to use.
63 | /// Sequence of entities.
64 | /// The collection of added entities ObjectId.
65 | /// Thrown if is null.
66 | /// Thrown if is null.
67 | /// Thrown if is null.
68 | public static ObjectIdCollection Add(this BlockTableRecord owner, Transaction tr, IEnumerable entities)
69 | {
70 | System.ArgumentNullException.ThrowIfNull(owner);
71 | System.ArgumentNullException.ThrowIfNull(tr);
72 | System.ArgumentNullException.ThrowIfNull(entities);
73 |
74 | var ids = new ObjectIdCollection();
75 | using (var ents = new DisposableSet(entities))
76 | {
77 | foreach (Entity ent in ents)
78 | {
79 | ids.Add(owner.AppendEntity(ent));
80 | tr.AddNewlyCreatedDBObject(ent, true);
81 | }
82 | }
83 | return ids;
84 | }
85 |
86 | ///
87 | /// Appends the entities to the BlockTableRecord.
88 | ///
89 | /// Instance to which the method applies.
90 | /// Active transaction
91 | /// Collection of entities.
92 | /// The collection of added entities ObjectId.
93 | /// Thrown if is null.
94 | /// Thrown if is null.
95 | /// Thrown if is null.
96 | public static ObjectIdCollection AddRange(this BlockTableRecord owner, Transaction tr, params Entity[] entities)
97 | {
98 | System.ArgumentNullException.ThrowIfNull(owner);
99 | System.ArgumentNullException.ThrowIfNull(tr);
100 | System.ArgumentNullException.ThrowIfNull(entities);
101 |
102 | return owner.Add(tr, entities);
103 | }
104 |
105 | ///
106 | /// Appends the entity to the BlockTableRecord.
107 | ///
108 | /// Instance to which the method applies.
109 | /// Transaction or OpenCloseTransaction to use.
110 | /// Entity to add.
111 | /// The ObjectId of added entity.
112 | /// Thrown if is null.
113 | /// Thrown if is null.
114 | /// Thrown if is null.
115 | public static ObjectId Add(this BlockTableRecord owner, Transaction tr, Entity entity)
116 | {
117 | System.ArgumentNullException.ThrowIfNull(owner);
118 | System.ArgumentNullException.ThrowIfNull(tr);
119 | System.ArgumentNullException.ThrowIfNull(entity);
120 |
121 | try
122 | {
123 | var id = owner.AppendEntity(entity);
124 | tr.AddNewlyCreatedDBObject(entity, true);
125 | return id;
126 | }
127 | catch
128 | {
129 | entity.Dispose();
130 | throw;
131 | }
132 | }
133 |
134 | ///
135 | /// Inserts a block reference.
136 | ///
137 | /// Instance to which the method applies.
138 | /// Transaction or OpenCloseTransaction to use.
139 | /// Nlock name.
140 | /// Insertion point.
141 | /// X scale factor.
142 | /// Y scale factor.
143 | /// Z scale factor.
144 | /// Rotation
145 | /// Collection of key/value pairs (Tag/Value).
146 | /// The newly created BlockReference.
147 | /// Thrown if is null.
148 | /// Thrown if is null.
149 | /// Thrown if is null or empty.
150 | public static BlockReference? InsertBlockReference(
151 | this BlockTableRecord target,
152 | Transaction tr,
153 | string blkName,
154 | Point3d insertPoint,
155 | double xScale = 1.0,
156 | double yScale = 1.0,
157 | double zScale = 1.0,
158 | double rotation = 0.0,
159 | Dictionary? attribValues = null)
160 | {
161 | System.ArgumentNullException.ThrowIfNull(target);
162 | System.ArgumentNullException.ThrowIfNull(target);
163 | System.ArgumentNullException.ThrowIfNull(tr);
164 | System.ArgumentException.ThrowIfNullOrWhiteSpace(blkName);
165 |
166 | var db = target.Database;
167 | BlockReference? br = null;
168 | var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
169 | var btrId = bt.GetBlock(blkName);
170 | if (btrId != ObjectId.Null)
171 | {
172 | br = new BlockReference(insertPoint, btrId) { ScaleFactors = new Scale3d(xScale, yScale, zScale), Rotation = rotation };
173 | var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
174 | if (btr.Annotative == AnnotativeStates.True)
175 | {
176 | var objectContextManager = db.ObjectContextManager;
177 | var objectContextCollection = objectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES");
178 | Autodesk.AutoCAD.Internal.ObjectContexts.AddContext(br, objectContextCollection.CurrentContext);
179 | }
180 | target.Add(tr, br);
181 | br.AddAttributeReferences(tr, attribValues);
182 | }
183 | return br;
184 | }
185 |
186 | ///
187 | /// Synchronizes the attributes of all block references.
188 | ///
189 | /// Instance which the method applies.
190 | /// Transaction or OpenCloseTransaction to use.
191 | /// Thrown if is null.
192 | /// Thrown if is null.
193 | public static void SynchronizeAttributes(this BlockTableRecord target, Transaction tr)
194 | {
195 | System.ArgumentNullException.ThrowIfNull(target);
196 | System.ArgumentNullException.ThrowIfNull(tr);
197 |
198 | AttributeDefinition[] attDefs = target.GetObjects(tr).ToArray();
199 | foreach (BlockReference br in target.GetBlockReferenceIds(true, false).GetObjects(tr, OpenMode.ForWrite))
200 | {
201 | br.ResetAttributes(tr, attDefs);
202 | }
203 | if (target.IsDynamicBlock)
204 | {
205 | target.UpdateAnonymousBlocks();
206 | foreach (BlockTableRecord btr in target.GetAnonymousBlockIds().GetObjects(tr))
207 | {
208 | attDefs = btr.GetObjects(tr).ToArray();
209 | foreach (BlockReference br in btr.GetBlockReferenceIds(true, false).GetObjects(tr, OpenMode.ForWrite))
210 | {
211 | br.ResetAttributes(tr, attDefs);
212 | }
213 | }
214 | }
215 | }
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DBObjectCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Linq;
4 |
5 | namespace Gile.AutoCAD.R25.Extension
6 | {
7 | ///
8 | /// Provides extension methods for the DBObjectCollection type.
9 | ///
10 | public static class DBObjectCollectionExtension
11 | {
12 | ///
13 | /// Disposes of all objects in the collections.
14 | ///
15 | /// Instance to which the method applies.
16 | /// Thrown if is null.
17 | public static void DisposeAll(this DBObjectCollection source)
18 | {
19 | System.ArgumentNullException.ThrowIfNull(source);
20 |
21 | var list = source.Cast().ToList();
22 | source.Clear();
23 | list.DisposeAll();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DBObjectExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | namespace Gile.AutoCAD.R25.Extension
5 | {
6 | ///
7 | /// Provides extension methods for the DBObject type.
8 | ///
9 | public static class DBObjectExtension
10 | {
11 | ///
12 | /// Tries to get the object extension dictionary.
13 | ///
14 | /// Instance to which the method applies.
15 | /// Transaction or OpenCloseTransaction to use.
16 | /// Output dictionary.
17 | /// Open mode to obtain in.
18 | /// Value indicating whether to obtain erased objects.
19 | /// true, if the operation succeeded; false, otherwise.
20 | /// Thrown if is null.
21 | /// Thrown if is null.
22 | public static bool TryGetExtensionDictionary(
23 | this DBObject dbObject,
24 | Transaction tr,
25 | out DBDictionary? dictionary,
26 | OpenMode mode = OpenMode.ForRead,
27 | bool openErased = false)
28 | {
29 | System.ArgumentNullException.ThrowIfNull(dbObject);
30 | System.ArgumentNullException.ThrowIfNull(tr);
31 |
32 | dictionary = default;
33 | var id = dbObject.ExtensionDictionary;
34 | if (id.IsNull)
35 | return false;
36 | dictionary = (DBDictionary)tr.GetObject(id, mode, openErased);
37 | return true;
38 | }
39 |
40 | ///
41 | /// Gets or creates the extension dictionary.
42 | ///
43 | /// Instance to which the method applies.
44 | /// Transaction or OpenCloseTransaction to use.
45 | /// Open mode to obtain in.
46 | /// The extension dictionary.
47 | /// Thrown if is null.
48 | /// Thrown if is null.
49 | public static DBDictionary GetOrCreateExtensionDictionary(
50 | this DBObject dbObject,
51 | Transaction tr,
52 | OpenMode mode = OpenMode.ForRead)
53 | {
54 | System.ArgumentNullException.ThrowIfNull(dbObject);
55 | System.ArgumentNullException.ThrowIfNull(tr);
56 |
57 | if (dbObject.ExtensionDictionary.IsNull)
58 | {
59 | dbObject.OpenForWrite(tr);
60 | dbObject.CreateExtensionDictionary();
61 | }
62 | return (DBDictionary)tr.GetObject(dbObject.ExtensionDictionary, mode);
63 | }
64 |
65 | ///
66 | /// Tries to get the xrecord data of the extension dictionary of the object.
67 | ///
68 | /// Instance to which the method applies.
69 | /// Transaction or OpenCloseTransaction to use.
70 | /// Xrecord key.
71 | /// Output data.
72 | /// The xrecord data or null if the xrecord does not exists.
73 | /// Thrown if is null.
74 | /// Thrown if is null.
75 | /// Thrown if is null or empty.
76 | public static bool TryGetXDictionaryXrecordData(this DBObject source, Transaction tr, string key, out ResultBuffer? data)
77 | {
78 | System.ArgumentNullException.ThrowIfNull(source);
79 | System.ArgumentNullException.ThrowIfNull(tr);
80 | System.ArgumentException.ThrowIfNullOrWhiteSpace(key);
81 |
82 | data = default;
83 | return
84 | source.TryGetExtensionDictionary(tr, out DBDictionary? xdict) &&
85 | xdict!.TryGetXrecordData(tr, key, out data);
86 | }
87 |
88 | ///
89 | /// Sets the xrecord data of the extension dictionary of the object.
90 | ///
91 | /// Instance to which the method applies.
92 | /// Transaction or OpenCloseTransaction to use.
93 | /// The xrecord key.
94 | /// The new xrecord data.
95 | /// The got or newlycreated Xrecord.
96 | /// Thrown if is null.
97 | /// Thrown if is null.
98 | /// Thrown if is null or empty.
99 | public static Xrecord SetXDictionaryXrecordData(this DBObject target, Transaction tr, string key, params TypedValue[] values)
100 | {
101 | System.ArgumentNullException.ThrowIfNull(target);
102 | System.ArgumentNullException.ThrowIfNull(tr);
103 | System.ArgumentException.ThrowIfNullOrWhiteSpace(key);
104 |
105 | return target.SetXDictionaryXrecordData(tr, key, new ResultBuffer(values));
106 | }
107 |
108 | ///
109 | /// Sets the xrecord data of the extension dictionary of the object.
110 | ///
111 | /// Instance to which the method applies.
112 | /// Transaction or OpenCloseTransaction to use.
113 | /// The xrecord key.
114 | /// The new xrecord data.
115 | /// The got or newlycreated Xrecord.
116 | /// Thrown if is null.
117 | /// Thrown if is null.
118 | /// Thrown if is null or empty.
119 | public static Xrecord SetXDictionaryXrecordData(this DBObject target, Transaction tr, string key, ResultBuffer data)
120 | {
121 | System.ArgumentNullException.ThrowIfNull(target);
122 | System.ArgumentNullException.ThrowIfNull(tr);
123 | System.ArgumentException.ThrowIfNullOrWhiteSpace(key);
124 |
125 | return target.GetOrCreateExtensionDictionary(tr).SetXrecordData(tr, key, data);
126 | }
127 |
128 | ///
129 | /// Sets the object extended data (xdata) for the application.
130 | ///
131 | /// Instance to which the method applies.
132 | /// Transaction or OpenCloseTransaction to use.
133 | /// Extended data (the first TypedValue must be: (1001, <regAppName>)).
134 | /// Thrown if is null.
135 | /// Thrown if is null.
136 | /// Thrown if is null.
137 | /// eBadDxfSequence is thrown if the result buffer is not valid.
138 | public static void SetXDataForApplication(this DBObject target, Transaction tr, ResultBuffer data)
139 | {
140 | System.ArgumentNullException.ThrowIfNull(target);
141 | System.ArgumentNullException.ThrowIfNull(tr);
142 | System.ArgumentNullException.ThrowIfNull(data);
143 |
144 | var db = target.Database;
145 | var typedValue = data.AsArray()[0];
146 | ErrorStatus.BadDxfSequence.ThrowIf(typedValue.TypeCode != 1001);
147 | string appName = (string)typedValue.Value;
148 | var regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
149 | if (!regAppTable.Has(appName))
150 | {
151 | var regApp = new RegAppTableRecord
152 | {
153 | Name = appName
154 | };
155 | tr.GetObject(db.RegAppTableId, OpenMode.ForWrite);
156 | regAppTable.Add(regApp);
157 | tr.AddNewlyCreatedDBObject(regApp, true);
158 | }
159 | target.XData = data;
160 | }
161 |
162 | ///
163 | /// Opens the object for write.
164 | ///
165 | /// Instance to which the method applies.
166 | /// Transaction or OpenCloseTransaction to use.
167 | /// Thrown if is null.
168 | /// Thrown if is null.
169 | public static void OpenForWrite(this DBObject dbObj, Transaction tr)
170 | {
171 | System.ArgumentNullException.ThrowIfNull(dbObj);
172 | System.ArgumentNullException.ThrowIfNull(tr);
173 |
174 | if (!dbObj.IsWriteEnabled)
175 | {
176 | tr.GetObject(dbObj.ObjectId, OpenMode.ForWrite);
177 | }
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DBTextExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | using System;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace Gile.AutoCAD.R25.Extension
8 | {
9 | ///
10 | /// Provides extension methods for the DBText type.
11 | ///
12 | public static partial class DBTextExtension
13 | {
14 | ///
15 | /// Gets the 'text box' of the DBText instance.
16 | ///
17 | /// Instance to which the method applies.
18 | /// Lower left corner of the box ('DBText coordinate system').
19 | /// Upper right corner of the box ('DBText coordinate system')
20 | /// Transformation matrix from 'DBText coordinate system' to WCS.
21 | public static void GetTextBox(this DBText dbText, out Point3d point1, out Point3d point2, out Matrix3d transform)
22 | {
23 | ArgumentNullException.ThrowIfNull(dbText);
24 |
25 | int mirrored = dbText.IsMirroredInX ? 2 : 0;
26 | mirrored |= dbText.IsMirroredInY ? 4 : 0;
27 | var rb = new ResultBuffer(
28 | new TypedValue(1, dbText.TextString),
29 | new TypedValue(40, dbText.Height),
30 | new TypedValue(41, dbText.WidthFactor),
31 | new TypedValue(51, dbText.Oblique),
32 | new TypedValue(7, dbText.TextStyleName),
33 | new TypedValue(71, mirrored),
34 | new TypedValue(72, (int)dbText.HorizontalMode),
35 | new TypedValue(73, (int)dbText.VerticalMode));
36 | var pt1 = new double[3];
37 | var pt2 = new double[3];
38 | acedTextBox(rb.UnmanagedObject, pt1, pt2);
39 | point1 = new Point3d(pt1);
40 | point2 = new Point3d(pt2);
41 | transform =
42 | Matrix3d.Displacement(dbText.Position.GetAsVector()) *
43 | Matrix3d.Rotation(dbText.Rotation, dbText.Normal, Point3d.Origin) *
44 | Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, dbText.Normal));
45 | }
46 |
47 | ///
48 | /// Gets the center of the text bounding box.
49 | ///
50 | /// Instance to which the method applies.
51 | /// The center point of the text.
52 | /// Thrown if is null.
53 | public static Point3d GetTextBoxCenter(this DBText dbText)
54 | {
55 | dbText.GetTextBox(out Point3d point1, out Point3d point2, out Matrix3d xform);
56 | return new Point3d(
57 | (point1.X + point2.X) / 2.0,
58 | (point1.Y + point2.Y) / 2.0,
59 | (point1.Z + point2.Z) / 2.0)
60 | .TransformBy(xform);
61 | }
62 |
63 | ///
64 | /// Gets the points at corners of the text bounding box.
65 | ///
66 | /// Instance to which the method applies.
67 | /// The points (counter-clockwise from lower left).
68 | /// Thrown if is null.
69 | public static Point3d[] GetTextBoxCorners(this DBText dbText)
70 | {
71 | dbText.GetTextBox(out Point3d point1, out Point3d point2, out Matrix3d xform);
72 | return
73 | [
74 | point1.TransformBy(xform),
75 | new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform),
76 | point2.TransformBy(xform),
77 | new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform)
78 | ];
79 | }
80 |
81 | ///
82 | /// Mirrors the text honoring the value of MIRRTEXT system variable.
83 | ///
84 | /// Instance to which the method applies.
85 | /// Transaction or OpenCloseTransaction to use.
86 | /// Axis of the mirroring operation.
87 | /// Value indicating if the source block reference have to be erased.
88 | /// Thrown if is null.
89 | /// Thrown if is null.
90 | /// Thrown if is null.
91 | public static void Mirror(this DBText source, Transaction tr, Line3d axis, bool eraseSource)
92 | {
93 | ArgumentNullException.ThrowIfNull(source);
94 | ArgumentNullException.ThrowIfNull(tr);
95 | ArgumentNullException.ThrowIfNull(axis);
96 |
97 | var db = source.Database;
98 | DBText mirrored;
99 | if (eraseSource)
100 | {
101 | mirrored = source;
102 | mirrored.OpenForWrite(tr);
103 | }
104 | else
105 | {
106 | var ids = new ObjectIdCollection([source.ObjectId]);
107 | var mapping = new IdMapping();
108 | db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
109 | mirrored = (DBText)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
110 | }
111 | mirrored.TransformBy(Matrix3d.Mirroring(axis));
112 | if (!db.Mirrtext)
113 | {
114 | var pts = mirrored.GetTextBoxCorners();
115 | var cen = new LineSegment3d(pts[0], pts[2]).MidPoint;
116 | var rotAxis = Math.Abs(axis.Direction.X) < Math.Abs(axis.Direction.Y) ?
117 | pts[0].GetVectorTo(pts[3]) :
118 | pts[0].GetVectorTo(pts[1]);
119 | mirrored.TransformBy(Matrix3d.Rotation(Math.PI, rotAxis, cen));
120 | }
121 | }
122 |
123 | ///
124 | /// P/Invokes the unmanaged acedTextBox method.
125 | ///
126 | /// ResultBuffer cotaining the DBtext DXF definition.
127 | /// Minimum point of the bounding box.
128 | /// Maximum point of the bounding box.
129 | /// RTNORM, if succeeds; RTERROR, otherwise.
130 | [System.Security.SuppressUnmanagedCodeSecurity]
131 | [LibraryImport("accore.dll", EntryPoint = "acedTextBox")]
132 | [UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
133 | private static partial IntPtr acedTextBox(IntPtr rb, [Out] double[] point1, [Out] double[] point2);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DisposableList.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace Gile.AutoCAD.R25.Extension
8 | {
9 | ///
10 | /// Describes a list of disposable values.
11 | ///
12 | /// Type of the items.
13 | public class DisposableList : List, IDisposableCollection
14 | where T : IDisposable
15 | {
16 | ///
17 | /// Creates a new empty instance.
18 | ///
19 | public DisposableList() { }
20 |
21 | ///
22 | /// Creates a new instance by copying the sequence items.
23 | ///
24 | /// Sequence whose elements are copied into the new set.
25 | public DisposableList(IEnumerable collection)
26 | : base(collection) { }
27 |
28 | ///
29 | /// Creates a new instance by copying the collection items.
30 | ///
31 | /// Collection whose elements are copied into the new set.
32 | public DisposableList(DBObjectCollection collection)
33 | : base((IEnumerable)collection.Cast()) { }
34 |
35 | ///
36 | /// Creates a new empty instance.
37 | ///
38 | /// Initial cpacity
39 | public DisposableList(int capacity)
40 | : base(capacity) { }
41 |
42 | ///
43 | /// Disposes of all items.
44 | ///
45 | public void Dispose()
46 | {
47 | var list = this.ToList();
48 | Clear();
49 | list.DisposeAll();
50 | }
51 |
52 | ///
53 | /// Removes items from the active instance.
54 | ///
55 | /// Items to remove.
56 | /// The sequence of effectively removed items.
57 | public IEnumerable RemoveRange(IEnumerable items)
58 | {
59 | ArgumentNullException.ThrowIfNull(items);
60 | foreach (T item in items)
61 | {
62 | if (Remove(item))
63 | {
64 | yield return item;
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DisposableSet.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Gile.AutoCAD.R25.Extension
6 | {
7 | ///
8 | /// Describes a set of disposable values.
9 | ///
10 | /// Type of the items.
11 | public class DisposableSet : HashSet, IDisposableCollection
12 | where T : IDisposable
13 | {
14 | ///
15 | /// Creates a new empty instance using the default comparer.
16 | ///
17 | public DisposableSet()
18 | { }
19 |
20 | ///
21 | /// Creates a new instance using the default comparer by copying the sequence items.
22 | ///
23 | /// Sequence whose elements are copied into the new set.
24 | public DisposableSet(IEnumerable collection)
25 | : base(collection)
26 | { }
27 |
28 | ///
29 | /// Creates a new empty instance using the specified comparer.
30 | ///
31 | /// IEqualityComparer<T> implementation.
32 | public DisposableSet(IEqualityComparer comparer)
33 | : base(comparer)
34 | { }
35 |
36 | ///
37 | /// Creates a new instance using the specified comparer by copying the sequence items.
38 | ///
39 | /// Sequence whose elements are copied into the new set.
40 | /// IEqualityComparer<T> implementation.
41 | public DisposableSet(IEnumerable collection, IEqualityComparer comparer)
42 | : base(collection, comparer)
43 | { }
44 |
45 | ///
46 | /// Disposes of all items.
47 | ///
48 | public void Dispose()
49 | {
50 | var list = this.ToList();
51 | Clear();
52 | list.DisposeAll();
53 | }
54 |
55 | ///
56 | /// Adds items to the active instance.
57 | ///
58 | /// Items to add.
59 | public void AddRange(IEnumerable items)
60 | {
61 | ArgumentNullException.ThrowIfNull(items);
62 |
63 | UnionWith(items);
64 | }
65 |
66 | ///
67 | /// Removes items from the active instance.
68 | ///
69 | /// Items to remove.
70 | /// The sequence of effectively removed items.
71 | public IEnumerable RemoveRange(IEnumerable items)
72 | {
73 | ArgumentNullException.ThrowIfNull(items);
74 |
75 | ExceptWith(items);
76 | return items;
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/DocumentCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices;
2 |
3 | using System;
4 | using System.Threading.Tasks;
5 |
6 | using AcRx = Autodesk.AutoCAD.Runtime;
7 |
8 | namespace Gile.AutoCAD.R25.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the DocumentCollection type.
12 | ///
13 | public static class DocumentCollectionExtension
14 | {
15 | ///
16 | /// Invokes an action in the document context that can be safely called from the application context.
17 | /// Credit: Tony Tanzillo.
18 | ///
19 | /// Documents collection.
20 | /// Action to invoke.
21 | /// Task.CompletedTask.
22 | /// Thrown if is null;
23 | /// Thrown if is null;
24 | /// eNoDocument thrown if no active document.
25 | /// eInvalidContext thrown if not called from application context.
26 | /// Must be called in a try / catch statement.
27 | public static async Task InvokeAsCommandAsync(this DocumentCollection docs, Action action)
28 | {
29 | ArgumentNullException.ThrowIfNull(docs);
30 |
31 | ArgumentNullException.ThrowIfNull(action);
32 |
33 | Document doc = docs.MdiActiveDocument ?? throw new AcRx.Exception(AcRx.ErrorStatus.NoDocument);
34 |
35 | if (!docs.IsApplicationContext)
36 | throw new AcRx.Exception(AcRx.ErrorStatus.InvalidContext);
37 |
38 | Task task = Task.CompletedTask;
39 | await docs.ExecuteInCommandContextAsync(
40 | (_) =>
41 | {
42 | try
43 | {
44 | action(doc);
45 | return task;
46 | }
47 | catch (Exception ex)
48 | {
49 | return task = Task.FromException(ex);
50 | }
51 | },
52 | null
53 | );
54 | if (task.IsFaulted)
55 | {
56 | throw task.Exception;
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/EditorExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.ApplicationServices.Core;
2 | using Autodesk.AutoCAD.DatabaseServices;
3 | using Autodesk.AutoCAD.EditorInput;
4 | using Autodesk.AutoCAD.Geometry;
5 |
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | namespace Gile.AutoCAD.R25.Extension
10 | {
11 | ///
12 | /// Provides extension methods for the Editor type.
13 | ///
14 | public static class EditorExtension
15 | {
16 | #region Zoom
17 |
18 | ///
19 | /// Zooms to given extents in the current viewport.
20 | ///
21 | /// Instance to which the method applies.
22 | /// Extents of the zoom.
23 | /// Thrown if is null.
24 | public static void Zoom(this Editor ed, Extents3d ext)
25 | {
26 | System.ArgumentNullException.ThrowIfNull(ed);
27 |
28 | using ViewTableRecord view = ed.GetCurrentView();
29 | ext.TransformBy(view.WorldToEye());
30 | view.Width = ext.MaxPoint.X - ext.MinPoint.X;
31 | view.Height = ext.MaxPoint.Y - ext.MinPoint.Y;
32 | view.CenterPoint = new Point2d(
33 | (ext.MaxPoint.X + ext.MinPoint.X) / 2.0,
34 | (ext.MaxPoint.Y + ext.MinPoint.Y) / 2.0);
35 | ed.SetCurrentView(view);
36 | }
37 |
38 | ///
39 | /// Zooms to the extents of the current viewport.
40 | ///
41 | /// Instance to which the method applies.
42 | /// Thrown if is null.
43 | public static void ZoomExtents(this Editor ed)
44 | {
45 | System.ArgumentNullException.ThrowIfNull(ed);
46 |
47 | Database db = ed.Document.Database;
48 | db.UpdateExt(false);
49 | Extents3d ext = (short)Application.GetSystemVariable("cvport") == 1 ?
50 | new Extents3d(db.Pextmin, db.Pextmax) :
51 | new Extents3d(db.Extmin, db.Extmax);
52 | ed.Zoom(ext);
53 | }
54 |
55 | ///
56 | /// Zooms to the given window.
57 | ///
58 | /// Instance to which the method applies.
59 | /// First window corner.
60 | /// Opposite window corner.
61 | /// Thrown if is null.
62 | public static void ZoomWindow(this Editor ed, Point3d p1, Point3d p2)
63 | {
64 | System.ArgumentNullException.ThrowIfNull(ed);
65 |
66 | var extents = new Extents3d();
67 | extents.AddPoint(p1);
68 | extents.AddPoint(p2);
69 | ed.Zoom(extents);
70 | }
71 |
72 | ///
73 | /// Zooms to the specified entity collection.
74 | ///
75 | /// Instance to which the method applies.
76 | /// Collection of the entities ObjectId on which to zoom.
77 | /// Thrown if is null.
78 | public static void ZoomObjects(this Editor ed, IEnumerable ids)
79 | {
80 | System.ArgumentNullException.ThrowIfNull(ed);
81 | System.ArgumentNullException.ThrowIfNull(ids);
82 |
83 | using Transaction tr = ed.Document.TransactionManager.StartOpenCloseTransaction();
84 | Extents3d ext = ids
85 | .GetObjects(tr)
86 | .Select(ent => ent.Bounds)
87 | .Where(b => b.HasValue)
88 | .Select(b => b!.Value)
89 | .Aggregate((e1, e2) => { e1.AddExtents(e2); return e1; });
90 | ed.Zoom(ext);
91 | tr.Commit();
92 | }
93 |
94 | ///
95 | /// Zooms in current viewport to the specified scale.
96 | ///
97 | /// Instance to which the method applies.
98 | /// Scale.
99 | /// Thrown if is null.
100 | public static void ZoomScale(this Editor ed, double scale)
101 | {
102 | System.ArgumentNullException.ThrowIfNull(ed);
103 |
104 | using ViewTableRecord view = ed.GetCurrentView();
105 | view.Width /= scale;
106 | view.Height /= scale;
107 | ed.SetCurrentView(view);
108 | }
109 |
110 | ///
111 | /// Zooms in current viewport to the specified scale and center.
112 | ///
113 | /// Instance to which the method applies.
114 | /// Viewport center.
115 | /// Scale (default = 1).
116 | /// Thrown if is null.
117 | public static void ZoomCenter(this Editor ed, Point3d center, double scale = 1.0)
118 | {
119 | System.ArgumentNullException.ThrowIfNull(ed);
120 |
121 | using ViewTableRecord view = ed.GetCurrentView();
122 | center = center.TransformBy(view.WorldToEye());
123 | view.Height /= scale;
124 | view.Width /= scale;
125 | view.CenterPoint = new Point2d(center.X, center.Y);
126 | ed.SetCurrentView(view);
127 | }
128 |
129 | #endregion
130 |
131 | #region Selection
132 |
133 | ///
134 | /// Gets a selection set using the supplied prompt selection options, the supplied filter and the supplied predicate.
135 | ///
136 | /// Instance to which the method applies.
137 | /// Selection options.
138 | /// Selection filter
139 | /// Selection predicate.
140 | /// The selection result.
141 | /// Thrown if is null.
142 | /// Thrown if is null.
143 | public static PromptSelectionResult GetSelection(this Editor ed, PromptSelectionOptions options, SelectionFilter filter, System.Predicate predicate) =>
144 | GetPredicatedSelection(ed, predicate, options, filter);
145 |
146 | ///
147 | /// Gets a selection set using the supplied prompt selection options and the supplied predicate.
148 | ///
149 | /// Instance to which the method applies.
150 | /// Selection options.
151 | /// Selection predicate.
152 | /// The selection result.
153 | /// Thrown if is null.
154 | /// Thrown if is null.
155 | public static PromptSelectionResult GetSelection(this Editor ed, PromptSelectionOptions options, System.Predicate predicate) =>
156 | GetPredicatedSelection(ed, predicate, options);
157 |
158 | ///
159 | /// Gets a selection set using the supplied filter and the supplied predicate.
160 | ///
161 | /// Instance to which the method applies.
162 | /// Selection filter
163 | /// Selection predicate.
164 | /// The selection result.
165 | /// Thrown if is null.
166 | /// Thrown if is null.
167 | public static PromptSelectionResult GetSelection(this Editor ed, SelectionFilter filter, System.Predicate predicate) =>
168 | GetPredicatedSelection(ed, predicate, null, filter);
169 |
170 | ///
171 | /// Gets a selection set using the supplied predicate.
172 | ///
173 | /// Instance to which the method applies.
174 | /// Selection predicate.
175 | /// The selection result.
176 | /// Thrown if is null.
177 | /// Thrown if is null.
178 | public static PromptSelectionResult GetSelection(this Editor ed, System.Predicate predicate) =>
179 | GetPredicatedSelection(ed, predicate, null, null);
180 |
181 | private static PromptSelectionResult GetPredicatedSelection(
182 | Editor ed,
183 | System.Predicate predicate,
184 | PromptSelectionOptions ?options = null,
185 | SelectionFilter? filter = null)
186 | {
187 | System.ArgumentNullException.ThrowIfNull(ed);
188 | System.ArgumentNullException.ThrowIfNull(predicate);
189 |
190 | void onSelectionAdded(object sender, SelectionAddedEventArgs e)
191 | {
192 | var ids = e.AddedObjects.GetObjectIds();
193 | for (int i = 0; i < ids.Length; i++)
194 | {
195 | if (!predicate(ids[i]))
196 | {
197 | e.Remove(i);
198 | }
199 | }
200 | }
201 |
202 | PromptSelectionResult result;
203 | ed.SelectionAdded += onSelectionAdded;
204 | if (options == null)
205 | {
206 | if (filter == null)
207 | {
208 | result = ed.GetSelection();
209 | }
210 | else
211 | {
212 | result = ed.GetSelection(filter);
213 | }
214 | }
215 | else
216 | {
217 | if (filter == null)
218 | {
219 | result = ed.GetSelection(options);
220 | }
221 | else
222 | {
223 | result = ed.GetSelection(options, filter);
224 | }
225 | }
226 | ed.SelectionAdded -= onSelectionAdded;
227 | return result;
228 | }
229 |
230 | #endregion
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/EntityExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | namespace Gile.AutoCAD.R25.Extension
4 | {
5 | ///
6 | /// Provides extension methods for the Entity type.
7 | ///
8 | public static class EntityExtension
9 | {
10 | ///
11 | /// Evaluates if the owner of is a Layout.
12 | ///
13 | /// Instance to which the method applies.
14 | /// Transaction or OpenCloseTransaction to use.
15 | /// true, if the owner is a Layout; false, otherwise.
16 | /// Thrown if is null.
17 | /// Thrown if is null.
18 | public static bool IsOwnedByLayout(this Entity entity, Transaction tr)
19 | {
20 | System.ArgumentNullException.ThrowIfNull(entity);
21 | System.ArgumentNullException.ThrowIfNull(tr);
22 |
23 | var owner = tr.GetObject(entity.OwnerId, OpenMode.ForRead);
24 | return owner is BlockTableRecord btr && btr.IsLayout;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/Gile.AutoCAD.R25.Extension.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0-windows
4 | Library
5 | false
6 | Gile.AutoCAD.R25.Extension
7 | gileCAD
8 | Gile.AutoCAD.R25.Extension
9 | Copyright © Gilles Chanteau 2017
10 | 2.0.0.0
11 | 2.0.0.0
12 | x64
13 | enable
14 | true
15 | Gile.AutoCAD.R25.Extension
16 |
17 |
18 | bin\Release\Gile.AutoCAD.R25.Extension.xml
19 |
20 |
21 |
22 |
23 |
24 |
25 | F:\ObjectARX 2025\inc\AcCoreMgd.dll
26 | False
27 |
28 |
29 | F:\ObjectARX 2025\inc\AcDbMgd.dll
30 | False
31 |
32 |
33 | F:\ObjectARX 2025\inc\AcMgd.dll
34 | False
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/IDisposableCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Gile.AutoCAD.R25.Extension
5 | {
6 | ///
7 | /// Defines methods to add or removes items from a sequence of disposable objects.
8 | ///
9 | /// Type of the items.
10 | public interface IDisposableCollection : ICollection, IDisposable
11 | where T : IDisposable
12 | {
13 | ///
14 | /// Adds items to the sequence.
15 | ///
16 | /// Items to add.
17 | void AddRange(IEnumerable items);
18 |
19 | ///
20 | /// Removes items from the sequence.
21 | ///
22 | /// Items to remove.
23 | /// The sequence of removed items.
24 | IEnumerable RemoveRange(IEnumerable items);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/IEnumerableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 |
8 | namespace Gile.AutoCAD.R25.Extension
9 | {
10 | ///
11 | /// Provides extension methods for the IEnumerable(T) type.
12 | ///
13 | public static class IEnumerableExtension
14 | {
15 | ///
16 | /// Opens the objects which type matches to the given one, and return them.
17 | ///
18 | /// Type of object to return.
19 | /// Sequence of ObjectIds.
20 | /// Transaction or OpenCloseTransaction to use.
21 | /// Open mode to obtain in.
22 | /// Value indicating whether to obtain erased objects.
23 | /// Value indicating if locked layers should be opened.
24 | /// The sequence of opened objects.
25 | /// Thrown if is null.
26 | /// Thrown if is null.
27 | public static IEnumerable GetObjects(
28 | this IEnumerable source,
29 | Transaction tr,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayers = false) where T : DBObject
33 | {
34 | ArgumentNullException.ThrowIfNull(source);
35 | ArgumentNullException.ThrowIfNull(tr);
36 |
37 | if (source.Any())
38 | {
39 | var rxClass = RXObject.GetClass(typeof(T));
40 | foreach (ObjectId id in source)
41 | {
42 | if (id.ObjectClass.IsDerivedFrom(rxClass) &&
43 | (!id.IsErased || openErased))
44 | {
45 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
46 | }
47 | }
48 | }
49 | }
50 |
51 | ///
52 | /// Upgrades the open mode of all objects in the sequence.
53 | ///
54 | /// Type of objects.
55 | /// Sequence of DBObjects to upgrade.
56 | /// Transaction or OpenCloseTransaction to use.
57 | /// The sequence of opened for write objects (objets on locked layers are discared).
58 | /// Thrown if is null.
59 | /// Thrown if is null.
60 | public static IEnumerable UpgradeOpen(this IEnumerable source, Transaction tr) where T : DBObject
61 | {
62 | ArgumentNullException.ThrowIfNull(source);
63 |
64 | foreach (T item in source)
65 | {
66 | try
67 | {
68 | item.OpenForWrite(tr);
69 | }
70 | catch (Autodesk.AutoCAD.Runtime.Exception ex)
71 | {
72 | if (ex.ErrorStatus != ErrorStatus.OnLockedLayer)
73 | {
74 | throw;
75 | }
76 | continue;
77 | }
78 | yield return item;
79 | }
80 | }
81 |
82 | ///
83 | /// Disposes of all items of the sequence.
84 | ///
85 | /// Type of the items.
86 | /// Sequence of disposable objects.
87 | /// Thrown if is null.
88 | public static void DisposeAll(this IEnumerable source) where T : IDisposable
89 | {
90 | ArgumentNullException.ThrowIfNull(source);
91 |
92 | if (source.Any())
93 | {
94 | System.Exception? last = null;
95 | foreach (T item in source)
96 | {
97 | if (item != null)
98 | {
99 | try
100 | {
101 | item.Dispose();
102 | }
103 | catch (System.Exception ex)
104 | {
105 | last ??= ex;
106 | }
107 | }
108 | }
109 | if (last != null)
110 | {
111 | throw last;
112 | }
113 | }
114 | }
115 |
116 | ///
117 | /// Runs the action for each item of the collection.
118 | ///
119 | /// Type of the items.
120 | /// Sequence to process.
121 | /// Action to run.
122 | /// Thrown if is null.
123 | /// Thrown if is null.
124 | public static void ForEach(this IEnumerable source, Action action)
125 | {
126 | ArgumentNullException.ThrowIfNull(source);
127 | ArgumentNullException.ThrowIfNull(action);
128 |
129 | foreach (T item in source)
130 | {
131 | action(item);
132 | }
133 | }
134 |
135 | ///
136 | /// Runs the indexed action for each item of the collection.
137 | ///
138 | /// Type of the items.
139 | /// Sequence to process.
140 | /// Indexed action to run.
141 | /// Thrown if is null.
142 | /// Thrown if is null.
143 | public static void ForEach(this IEnumerable source, Action action)
144 | {
145 | ArgumentNullException.ThrowIfNull(source);
146 | ArgumentNullException.ThrowIfNull(action);
147 |
148 | int i = 0;
149 | foreach (T item in source)
150 | {
151 | action(item, i++);
152 | }
153 | }
154 |
155 | ///
156 | /// Gets the greatest item of the sequence using with the function returned values.
157 | ///
158 | /// Type the items.
159 | /// Type of the returned value of function.
160 | /// Sequence to which the method applies.
161 | /// Mapping function from TSource to TKey.
162 | /// Comparer used for the TKey type; uses Comparer<TKey>.Default if null or omitted.
163 | /// The greatest item in the sequence.
164 | /// Thrown if is null.
165 | /// Thrown if is null.
166 | public static TSource MaxBy(
167 | this IEnumerable source,
168 | Func selector,
169 | IComparer? comparer = null)
170 | {
171 | ArgumentNullException.ThrowIfNull(source);
172 | ArgumentNullException.ThrowIfNull(selector);
173 |
174 | comparer ??= Comparer.Default;
175 | using var iterator = source.GetEnumerator();
176 | if (!iterator.MoveNext())
177 | {
178 | throw new InvalidOperationException("Empty sequence");
179 | }
180 | var max = iterator.Current;
181 | var maxKey = selector(max);
182 | while (iterator.MoveNext())
183 | {
184 | var current = iterator.Current;
185 | var currentKey = selector(current);
186 | if (comparer.Compare(currentKey, maxKey) > 0)
187 | {
188 | max = current;
189 | maxKey = currentKey;
190 | }
191 | }
192 | return max;
193 | }
194 |
195 | ///
196 | /// Gets the smallest item of the sequence using the with the function returned values.
197 | ///
198 | /// Type the items.
199 | /// Type of the returned value of function.
200 | /// Sequence to which the method applies.
201 | /// Mapping function from TSource to TKey.
202 | /// Comparer used for the TKey type; uses Comparer<TKey>.Default if null or omitted.
203 | /// The smallest item in the sequence.
204 | /// Thrown if is null.
205 | /// Thrown if is null.
206 | public static TSource MinBy(
207 | this IEnumerable source,
208 | Func selector,
209 | IComparer? comparer = null)
210 | {
211 | ArgumentNullException.ThrowIfNull(source);
212 | ArgumentNullException.ThrowIfNull(selector);
213 |
214 | comparer ??= Comparer.Default;
215 | using var iterator = source.GetEnumerator();
216 | if (!iterator.MoveNext())
217 | {
218 | throw new InvalidOperationException("Empty sequence");
219 | }
220 | var min = iterator.Current;
221 | var minKey = selector(min);
222 | while (iterator.MoveNext())
223 | {
224 | var current = iterator.Current;
225 | var currentKey = selector(current);
226 | if (comparer.Compare(currentKey, minKey) < 0)
227 | {
228 | min = current;
229 | minKey = currentKey;
230 | }
231 | }
232 | return min;
233 | }
234 | }
235 | }
236 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/MTextExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Geometry;
3 |
4 | using System;
5 |
6 | namespace Gile.AutoCAD.R25.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the MText Type.
10 | ///
11 | public static class MTextExtension
12 | {
13 | ///
14 | /// Gets the points at corners of the mtext bounding box.
15 | ///
16 | /// Instance to which the method applies.
17 | /// The points (counter-clockwise from lower left).
18 | /// Thrown if is null.
19 | public static Point3d[] GetMTextBoxCorners(this MText mtext)
20 | {
21 | ArgumentNullException.ThrowIfNull(mtext);
22 |
23 | double width = mtext.ActualWidth;
24 | double height = mtext.ActualHeight;
25 | Point3d point1, point2;
26 | switch (mtext.Attachment)
27 | {
28 | case AttachmentPoint.TopLeft:
29 | default:
30 | point1 = new Point3d(0.0, -height, 0.0);
31 | point2 = new Point3d(width, 0.0, 0.0);
32 | break;
33 | case AttachmentPoint.TopCenter:
34 | point1 = new Point3d(-width * 0.5, -height, 0.0);
35 | point2 = new Point3d(width * 0.5, 0.0, 0.0);
36 | break;
37 | case AttachmentPoint.TopRight:
38 | point1 = new Point3d(-width, -height, 0.0);
39 | point2 = new Point3d(0.0, 0.0, 0.0);
40 | break;
41 | case AttachmentPoint.MiddleLeft:
42 | point1 = new Point3d(0.0, -height * 0.5, 0.0);
43 | point2 = new Point3d(width, height * 0.5, 0.0);
44 | break;
45 | case AttachmentPoint.MiddleCenter:
46 | point1 = new Point3d(-width * 0.5, -height * 0.5, 0.0);
47 | point2 = new Point3d(width * 0.5, height * 0.5, 0.0);
48 | break;
49 | case AttachmentPoint.MiddleRight:
50 | point1 = new Point3d(-width, -height * 0.5, 0.0);
51 | point2 = new Point3d(0.0, height * 0.5, 0.0);
52 | break;
53 | case AttachmentPoint.BottomLeft:
54 | point1 = new Point3d(0.0, 0.0, 0.0);
55 | point2 = new Point3d(width, height, 0.0);
56 | break;
57 | case AttachmentPoint.BottomCenter:
58 | point1 = new Point3d(-width * 0.5, 0.0, 0.0);
59 | point2 = new Point3d(width * 0.5, height, 0.0);
60 | break;
61 | case AttachmentPoint.BottomRight:
62 | point1 = new Point3d(-width, 0.0, 0.0);
63 | point2 = new Point3d(0.0, height, 0.0);
64 | break;
65 | }
66 |
67 | var xform =
68 | Matrix3d.Displacement(mtext.Location.GetAsVector()) *
69 | Matrix3d.Rotation(mtext.Rotation, mtext.Normal, Point3d.Origin) *
70 | Matrix3d.PlaneToWorld(new Plane(Point3d.Origin, mtext.Normal));
71 |
72 | return
73 | [
74 | point1.TransformBy(xform),
75 | new Point3d(point2.X, point1.Y, 0.0).TransformBy(xform),
76 | point2.TransformBy(xform),
77 | new Point3d(point1.X, point2.Y, 0.0).TransformBy(xform)
78 | ];
79 | }
80 |
81 | ///
82 | /// Mirrors the mtext honoring the value of MIRRTEXT system variable.
83 | ///
84 | /// Instance to which the method applies.
85 | /// Transaction or OpenCloseTransaction to use.
86 | /// Axis of the mirroring operation.
87 | /// Value indicating if the source block reference have to be erased.
88 | /// Thrown if is null.
89 | /// Thrown if is null.
90 | /// Thrown if is null.
91 | public static void Mirror(this MText source, Transaction tr, Line3d axis, bool eraseSource)
92 | {
93 | ArgumentNullException.ThrowIfNull(source);
94 | ArgumentNullException.ThrowIfNull(tr);
95 | ArgumentNullException.ThrowIfNull(axis);
96 |
97 | var db = source.Database;
98 | MText mirrored;
99 | if (eraseSource)
100 | {
101 | mirrored = source;
102 | if (!mirrored.IsWriteEnabled)
103 | {
104 | tr.GetObject(mirrored.ObjectId, OpenMode.ForWrite);
105 | }
106 | }
107 | else
108 | {
109 | var ids = new ObjectIdCollection([source.ObjectId]);
110 | var mapping = new IdMapping();
111 | db.DeepCloneObjects(ids, db.CurrentSpaceId, mapping, false);
112 | mirrored = (MText)tr.GetObject(mapping[source.ObjectId].Value, OpenMode.ForWrite);
113 | }
114 | mirrored.TransformBy(Matrix3d.Mirroring(axis));
115 |
116 | if (!db.Mirrtext)
117 | {
118 | var pts = mirrored.GetMTextBoxCorners();
119 | var cen = new LineSegment3d(pts[0], pts[2]).MidPoint;
120 | var rotAxis = Math.Abs(axis.Direction.X) < Math.Abs(axis.Direction.Y) ?
121 | pts[0].GetVectorTo(pts[3]) :
122 | pts[0].GetVectorTo(pts[1]);
123 | mirrored.TransformBy(Matrix3d.Rotation(Math.PI, rotAxis, cen));
124 | }
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/ObjectIdCollectionExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System.Collections.Generic;
5 |
6 | namespace Gile.AutoCAD.R25.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the ObjectIdCollection type.
10 | ///
11 | public static class ObjectIdCollectionExtension
12 | {
13 |
14 | ///
15 | /// Opens the objects which type matches to the given one, and return them.
16 | ///
17 | /// Type of objects to return.
18 | /// Instance to which the method applies.
19 | /// Transaction or OpenCloseTransaction to use.
20 | /// Open mode to obtain in.
21 | /// Value indicating whether to obtain erased objects.
22 | /// Value indicating if locked layers should be opened.
23 | /// The sequence of opened objects.
24 | /// Thrown if is null.
25 | /// Thrown if is null.
26 | public static IEnumerable GetObjects(
27 | this ObjectIdCollection source,
28 | Transaction tr,
29 | OpenMode mode = OpenMode.ForRead,
30 | bool openErased = false,
31 | bool forceOpenOnLockedLayers = false)
32 | where T : DBObject
33 | {
34 | System.ArgumentNullException.ThrowIfNull(source);
35 | System.ArgumentNullException.ThrowIfNull(tr);
36 |
37 | if (0 < source.Count)
38 | {
39 | var rxClass = RXObject.GetClass(typeof(T));
40 | foreach (ObjectId id in source)
41 | {
42 | if ((id.ObjectClass == rxClass || id.ObjectClass.IsDerivedFrom(rxClass)) &&
43 | (!id.IsErased || openErased))
44 | {
45 | yield return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayers);
46 | }
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/ObjectIdExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 | using Autodesk.AutoCAD.Runtime;
3 |
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Gile.AutoCAD.R25.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the ObjectId type.
10 | ///
11 | public static partial class ObjectIdExtension
12 | {
13 | ///
14 | /// Tries to open an AutoCAD object of the given type in the given open mode.
15 | ///
16 | /// Type of the output object.
17 | /// ObjectId to open.
18 | /// Transaction or OpenCloseTransaction to use.
19 | /// Output object.
20 | /// Open mode to obtain in.
21 | /// Value indicating whether to obtain erased objects.
22 | /// Value indicating if locked layers should be opened.
23 | /// true, if the operation succeeded; false, otherwise.
24 | /// eNullObjectId is thrown if equals ObjectId.Null.
25 | /// Thrown if is null.
26 | public static bool TryGetObject(
27 | this ObjectId id,
28 | Transaction tr,
29 | out T? obj,
30 | OpenMode mode = OpenMode.ForRead,
31 | bool openErased = false,
32 | bool forceOpenOnLockedLayer = false)
33 | where T : DBObject
34 | {
35 | ErrorStatus.NullObjectId.ThrowIf(id.IsNull);
36 | System.ArgumentNullException.ThrowIfNull(tr);
37 |
38 | obj = default;
39 | if (!id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(T))))
40 | {
41 | return false;
42 | }
43 | obj = (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayer);
44 | return true;
45 | }
46 |
47 | ///
48 | /// Opens an AutoCAD object of the given type in the given open mode.
49 | ///
50 | /// Type of the object to return.
51 | /// ObjectId to open.
52 | /// Transaction or OpenCloseTransaction to use.
53 | /// Open mode to obtain in.
54 | /// Value indicating whether to obtain erased objects.
55 | /// Value indicating if locked layers should be opened.
56 | /// The object opened in given open mode.
57 | /// Thrown if the object type does not match the given type
58 | /// eNullObjectId is thrown if equals ObjectId.Null.
59 | /// Thrown if is null.
60 | public static T GetObject(
61 | this ObjectId id,
62 | Transaction tr,
63 | OpenMode mode = OpenMode.ForRead,
64 | bool openErased = false,
65 | bool forceOpenOnLockedLayer = false)
66 | where T : DBObject
67 | {
68 | ErrorStatus.NullObjectId.ThrowIf(id.IsNull);
69 | System.ArgumentNullException.ThrowIfNull(tr);
70 |
71 | return (T)tr.GetObject(id, mode, openErased, forceOpenOnLockedLayer);
72 | }
73 |
74 | ///
75 | /// Get the DXF definition data (like AutoLISP entget function).
76 | ///
77 | /// Instance to which the method applies.
78 | /// The DXF data.
79 | /// Thrown in case of invalid objectId.
80 | public static ResultBuffer? EntGet(this ObjectId id)
81 | {
82 | var errorStatus = acdbGetAdsName(out AdsName ename, id);
83 | if (errorStatus != ErrorStatus.OK)
84 | {
85 | throw new Exception(errorStatus);
86 | }
87 | var result = acdbEntGet(ename);
88 | if (result != nint.Zero)
89 | {
90 | return ResultBuffer.Create(result, true);
91 | }
92 | return null;
93 | }
94 |
95 | // Replace the DLL name according to the AutoCAD targeted version
96 | // 2013-2014: "acdb19.dll"
97 | // 2015-2016: "acdb20.dll"
98 | // 2017: "acdb21.dll"
99 | // 2018: "acdb22.dll"
100 | // 2019-2020: "acdb23.dll"
101 | // 2021-2024: "acdb24.dll"
102 | // Replace the EntryPoint according to AutoCAD plateform
103 | // 32 bits: "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AAY01JVAcDbObjectId@@@Z"
104 | // 64 bits: "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z"
105 | [System.Security.SuppressUnmanagedCodeSecurity]
106 | [LibraryImport("acdb24.dll", EntryPoint = "?acdbGetAdsName@@YA?AW4ErrorStatus@Acad@@AEAY01_JVAcDbObjectId@@@Z")]
107 | [UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
108 | private static partial ErrorStatus acdbGetAdsName(out AdsName ename, ObjectId id);
109 |
110 | [System.Security.SuppressUnmanagedCodeSecurity]
111 | [LibraryImport("accore.dll", EntryPoint = "acdbEntGet")]
112 | [UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
113 | private static partial nint acdbEntGet(AdsName ename);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/PolylineExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 |
7 | namespace Gile.AutoCAD.R25.Extension
8 | {
9 | ///
10 | /// Enumeration of offset side options
11 | ///
12 | public enum OffsetSide
13 | {
14 | ///
15 | /// Inside.
16 | ///
17 | In,
18 | ///
19 | /// Outside.
20 | ///
21 | Out,
22 | ///
23 | /// Left side.
24 | ///
25 | Left,
26 | ///
27 | /// Right side.
28 | ///
29 | Right,
30 | ///
31 | /// Both sides.
32 | ///
33 | Both
34 | }
35 |
36 | // credits to Tony 'TheMaster' Tanzillo
37 | // http://www.theswamp.org/index.php?topic=31862.msg494503#msg494503
38 |
39 | ///
40 | /// Provides the Offset() extension method for the Polyline type
41 | ///
42 | public static class PolylineExtension
43 | {
44 | ///
45 | /// Offset the source polyline to specified side(s).
46 | ///
47 | /// Instance to which the method applies.
48 | /// Offset distance.
49 | /// Offset side(s).
50 | /// A polyline sequence resulting from the offset of the source polyline.
51 | /// Thrown if is null.
52 | public static IEnumerable? Offset(this Polyline source, double offsetDist, OffsetSide side)
53 | {
54 | ArgumentNullException.ThrowIfNull(source);
55 |
56 | offsetDist = Math.Abs(offsetDist);
57 | using var plines = new DisposableSet();
58 | IEnumerable offsetRight = source.GetOffsetCurves(offsetDist).Cast();
59 | plines.AddRange(offsetRight);
60 | IEnumerable offsetLeft = source.GetOffsetCurves(-offsetDist).Cast();
61 | plines.AddRange(offsetLeft);
62 | double areaRight = offsetRight.Select(pline => pline.Area).Sum();
63 | double areaLeft = offsetLeft.Select(pline => pline.Area).Sum();
64 | switch (side)
65 | {
66 | case OffsetSide.In:
67 | return plines.RemoveRange(
68 | areaRight < areaLeft ? offsetRight : offsetLeft);
69 | case OffsetSide.Out:
70 | return plines.RemoveRange(
71 | areaRight < areaLeft ? offsetLeft : offsetRight);
72 | case OffsetSide.Left:
73 | return plines.RemoveRange(offsetLeft);
74 | case OffsetSide.Right:
75 | return plines.RemoveRange(offsetRight);
76 | case OffsetSide.Both:
77 | plines.Clear();
78 | return offsetRight.Concat(offsetLeft);
79 | default:
80 | return null;
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | [assembly: AssemblyTrademark("")]
5 | [assembly: AssemblyCulture("")]
6 |
7 | // L'affectation de la valeur false à ComVisible rend les types invisibles dans cet assembly
8 | // aux composants COM. Si vous devez accéder à un type dans cet assembly à partir de
9 | // COM, affectez la valeur true à l'attribut ComVisible sur ce type.
10 | [assembly: ComVisible(false)]
11 |
12 | // Le GUID suivant est pour l'ID de la typelib si ce projet est exposé à COM
13 | [assembly: Guid("32ebff40-ce54-4b05-aeba-2eeffedb443b")]
14 | [assembly: DisableRuntimeMarshalling]
15 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/RuntimeExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.Runtime;
2 |
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace Gile.AutoCAD.R25.Extension
6 | {
7 | ///
8 | /// Provides extension related to AutoCAD Runtime.
9 | ///
10 | public static class RuntimeExtension
11 | {
12 | ///
13 | /// Throws Autodesk.AutoCAD.Exception(errorStatus) it condition is true.
14 | /// Credit Tony Tanzillo http://www.theswamp.org/index.php?topic=59013.msg619828#msg619828
15 | ///
16 | /// Error status.
17 | /// Condition.
18 | /// Message.
19 | ///
20 | public static void ThrowIf(
21 | this ErrorStatus errorStatus,
22 | bool condition,
23 | [CallerArgumentExpression(nameof(condition))] string? message = null)
24 | {
25 | if (condition)
26 | throw new Exception(errorStatus, message);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/SymbolTableExtension.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | namespace Gile.AutoCAD.R25.Extension
7 | {
8 | ///
9 | /// Provides extension methods for the SymbolTable type.
10 | ///
11 | public static class SymbolTableExtension
12 | {
13 | ///
14 | /// Opens the table records in the given open mode.
15 | ///
16 | /// Type of returned object.
17 | /// Instance to which the method applies.
18 | /// Transaction or OpenCloseTransaction to use.
19 | /// Open mode to obtain in.
20 | /// Value indicating whether to obtain erased objects.
21 | /// The sequence of records.
22 | /// Thrown if is null.
23 | /// Thrown if is null.
24 | public static IEnumerable GetObjects(this SymbolTable source, Transaction tr, OpenMode mode = OpenMode.ForRead, bool openErased = false)
25 | where T : SymbolTableRecord
26 | {
27 | System.ArgumentNullException.ThrowIfNull(source);
28 | System.ArgumentNullException.ThrowIfNull(tr);
29 |
30 | foreach (ObjectId id in openErased ? source.IncludingErased : source)
31 | {
32 | yield return (T)tr.GetObject(id, mode, openErased, false);
33 | }
34 | }
35 |
36 | ///
37 | /// Purges the unreferenced symbol table records.
38 | ///
39 | /// Instance to which the method applies.
40 | /// Transaction or OpenCloseTransaction to use.
41 | /// The number of pruged records.
42 | /// Thrown if is null.
43 | /// Thrown if is null.
44 | public static int Purge(this SymbolTable symbolTable, Transaction tr)
45 | {
46 | System.ArgumentNullException.ThrowIfNull(symbolTable);
47 | System.ArgumentNullException.ThrowIfNull(tr);
48 |
49 | Database db = symbolTable.Database;
50 | int cnt = 0;
51 | var unpurgeable = new HashSet();
52 | while (true)
53 | {
54 | var ids = new ObjectIdCollection(symbolTable.Cast().Except(unpurgeable).ToArray());
55 | db.Purge(ids);
56 | if (ids.Count == 0)
57 | {
58 | break;
59 | }
60 | foreach (ObjectId id in ids)
61 | {
62 | try
63 | {
64 | tr.GetObject(id, OpenMode.ForWrite).Erase();
65 | cnt++;
66 | }
67 | catch
68 | {
69 | unpurgeable.Add(id);
70 | }
71 | }
72 | }
73 | return cnt;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Gile.AutoCAD.R25.Extension/WorkingDatabase.cs:
--------------------------------------------------------------------------------
1 | using Autodesk.AutoCAD.DatabaseServices;
2 |
3 | using System;
4 |
5 | namespace Gile.AutoCAD.R25.Extension
6 | {
7 | ///
8 | /// Provides a safe way to temporarily set the working database.
9 | /// Credits Tony Tanzillo: https://forums.autodesk.com/t5/net/want-to-have-c-program-to-modify-dwg-and-save-into-dwg-format/m-p/12439905/highlight/true#M79788
10 | ///
11 | public class WorkingDatabase : IDisposable
12 | {
13 | Database? previous;
14 |
15 | ///
16 | /// Creates a new instance of WorkingDatabase.
17 | ///
18 | /// Database to be temporarily set as working database.
19 | public WorkingDatabase(Database newWorkingDb)
20 | {
21 | ArgumentNullException.ThrowIfNull(newWorkingDb);
22 |
23 | Database current = HostApplicationServices.WorkingDatabase;
24 | if (newWorkingDb != current)
25 | {
26 | previous = current;
27 | HostApplicationServices.WorkingDatabase = newWorkingDb;
28 | }
29 | }
30 |
31 | ///
32 | /// Restores the previous working database.
33 | ///
34 | public void Dispose()
35 | {
36 | if (previous != null)
37 | {
38 | HostApplicationServices.WorkingDatabase = previous;
39 | previous = null;
40 | GC.SuppressFinalize(this);
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Gilles Chanteau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Gile.AutoCAD.Extension
2 | ### AutoCAD Helpers Class Library
3 | Thanks to all the [Swampers](http://www.theswamp.org/index.php) who helped me learning AutoCAD .NET programming, with a special mention to Tony 'TheMaster' Tanzillo and Thorsten 'kaefer' Meinecke for the discussions about the GetObject and GetObjects methods which were the start points of this library.
4 |
5 | #### This library should help to write code in a more concise and declarative way.
6 | Example with a method to erase lines in model space which are smaller than a given distance:
7 |
8 | ```c#
9 | public void EraseShortLines(double minLength)
10 | {
11 | var db = Application.DocumentManager.MdiActiveDocument.Database;
12 | using (var tr = db.TransactionManager.StartOpenCloseTransaction())
13 | {
14 | var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
15 | var modelSpace = (BlockTableRecord)tr.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead);
16 | var lineClass = RXObject.GetClass(typeof(Line));
17 | foreach (ObjectId id in modelSpace)
18 | {
19 | if (id.ObjectClass == lineClass)
20 | {
21 | var line = (Line)tr.GetObject(id, OpenMode.ForRead);
22 | if (line.Length < minLength)
23 | {
24 | tr.GetObject(id, OpenMode.ForWrite);
25 | line.Erase();
26 | }
27 | }
28 | }
29 | tr.Commit();
30 | }
31 | }
32 | ```
33 | The same method can be written:
34 |
35 | ```c#
36 | public void EraseShortLines(double minLength)
37 | {
38 | var db = Active.Database;
39 | using (var tr = db.TransactionManager.StartOpenCloseTransaction())
40 | {
41 | db.GetModelSpace(tr)
42 | .GetObjects(tr)
43 | .Where(line => line.Length < minLength)
44 | .UpgradeOpen(tr)
45 | .ForEach(line => line.Erase());
46 | tr.Commit();
47 | }
48 | }
49 | ```
50 |
51 | Reference one of these assemblies in AutoCAD .NET projects setting the Copy Locale property to True.
52 |
53 | Download the [assemblies](https://gilecad.azurewebsites.net/Resources/Gile.AutoCAD.Extension.zip) (Gile.AutoCAD.R20.Extension.dll for AutoCAD 2015 to 2024, Gile.AutoCAD.R25.Extension.dll for AutoCAD 2025+).
54 |
55 | See the [documentation](https://gilecad.azurewebsites.net/Resources/AcadExtensionHelp/index.html).
56 |
--------------------------------------------------------------------------------