Let us look at a cool AutoCAD .NET coding gadget in this post. It uses the cool .NET Extension Method and the LINQ technology to find some AutoCAD entities with a pretty complex filtering criteria, e.g. finding all circles with red or yellow color, with DASHED or DOT line type, on a unfrozen layer TEST, and having radiuses between 2.0 and 6.0 unit.
In the old days without the LINQ technology, this is a not so straightforward and actually an error prone task. We generally had to use many out-of-dated ADS stuffs such as result buffer, DXF code, selection set, and different sets of relational and logical operators which are not familiar to C# or C++ programmers at all, though they have been wrapped a bit and renamed in the AutoCAD .NET as such, TypedValue, DxfCode, SelectionFilter, etc.
Furthermore, filtering color, layer and line type may be still possible to use the out of fashion result buffer and DXF code APIs, but for the circle radius comparison, a loop will be still necessary. Therefore, it just brings in unnecessary technical difficulties and makes the performance further worse if we choose to do so in the old way.
With the wonderful .NET LINQ technology handy, we do not have to care about these unfriendly legacy stuffs anymore. We can make the same work done more nicely, naturally and efficiently with less code in a single loop using the LINQ technology. We demonstrated how to do so before, but there was something worth of a bit improvement there. Using the .NET Extension Method to wrap the AutoCAD Entity open for read operations and those related variables into a separate static class seemed to make things better.
Here is the extension method to the AutoCAD Transaction class. Please put the code into a separate class file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Windows;
namespace AcadNetAddinWizard_Namespace
{
public static class ExtensionMethods
{
private static Entity cachedEntity = null;
private static ObjectId cachedEntId = ObjectId.Null;
public static Entity GetEnt(this Transaction tr, ObjectId id)
{
if (cachedEntId != id || cachedEntity == null)
cachedEntity = tr.GetObject(id, OpenMode.ForRead) as Entity;
return cachedEntity;
}
}
}
Here is the improved Entity filtering code and test command.
private delegate bool InRange(double d);
[CommandMethod("TestLinqInAutoCAD2")]
public static void TestLinqInAutoCAD2_Method()
{
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
try
{
ObjectId[] ids;
InRange inRange2to6 = r => { return r >= 2.0 && r <= 6.0; };
using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
var v = from ObjectId id in btr
where GetEnt(tr, id) is Circle &&
(new int[] { 1, 3 }.Contains(tr.GetEnt(id).ColorIndex)) && //Color Red or Yellow
tr.GetEnt(id).Layer == "TEST" && //Layer 'TEST'
!(tr.GetObject(tr.GetEnt(id).LayerId, OpenMode.ForRead) as LayerTableRecord).IsFrozen && //Layer not frozen
(new string[] { "DASHED", "DOT" }.Contains(tr.GetEnt(id).Linetype)) && //Linetype Dashed or Dotted
inRange2to6((tr.GetEnt(id) as Circle).Radius) //Circle radius in the range [2.0, 6.0]
select id;
ids = v.ToArray();
tr.Commit();
}
ed.WriteMessage(string.Format("\nThere are {0} circles meeting the filtering criteria.", ids.Length));
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
As can be seen, this time we do not have to specify the transaction variable every time in the GetEnt() method and this makes the code more readable and succinct. Besides the Extension Method technology, as also can be seen, a few other wonderful modern .NET technologies have been demonstrated such as LINQ, Lambda Expression and Delegate. Better, all these are not just for new thing show-off. Instead, each cool tech applied here has its own very reason!
In case there are some circles meeting the filtering criteria in the current drawing, the command may print out something onto the AutoCAD command line window as follows:
Command: TestLinqInAutoCAD2
There are 58 circles meeting the filtering criteria.
Enjoy it! More coding gadgets will be created and demonstrated in the future. Please stay tuned.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides various project wizards, item wizards, coders and widgets to help program AutoCAD .NET addins.
Posted by: |