Author Topic: .NET SELECTION Routines  (Read 11874 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
.NET SELECTION Routines
« on: January 27, 2010, 03:32:31 AM »
LIBRARY THREAD for  AutoCAD SELECTIONS
 Members are encouraged to post any functions, methods, snips regarding
AutoCAD SELECTIONSS in .NET : C# ,  VB , F# , Python , etc

Feel free to include comments, descriptive notes, limitations,  and images to document your post.

Please post questions in a regular thread.
kdub in one timeline.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<-

MickD

  • King Gator
  • Posts: 3520
  • (x-in)->[process]->(y-out)
[Boo] Select all objects by type
« Reply #1 on: January 27, 2010, 02:31:09 PM »
just to get the ball rolling, here's an example of iterating over the modelspace block table record to retrieve all Solid3d and Line objects, change as per your required type.
I'll post an example using selection sets and filters as well shortly.

[added kwb] This is a Boo example
Boo is an object oriented statically typed programming language for the Common Language Infrastructure with a python inspired syntax.

Code: [Select]
public def SelectAll3dSolidsAndLines(prompt as string) as ObjectIdCollection:
db = HostApplicationServices.WorkingDatabase
ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
ids = ObjectIdCollection()
using tr = db.TransactionManager.StartTransaction():
//roll over the block table and get useable entity types:
bt = (tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable)
if bt is null:
ed.WriteMessage('{0}Catastrophic error: Failed to open the BlockTable!', Environment.NewLine)
return

modelspace = (tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord)
if modelspace is null:
ed.WriteMessage('{0}Catastrophic error: Failed to open the modelspace btr!', Environment.NewLine)
return
for msid as ObjectId in modelspace:
l = (tr.GetObject(msid, OpenMode.ForRead) as Line)
if l is not null:
ids.Add(msid)

s = (tr.GetObject(msid, OpenMode.ForRead) as Solid3d)
if s is not null:
ids.Add(msid)
tr.Commit()
return ids
« Last Edit: January 27, 2010, 06:55:44 PM by Kerry Brown »
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

"The E in Javascript stands for 'easy'." Florin Pop tweet

DaveWish

  • Guest
Re: .NET SELECTION Routines
« Reply #2 on: January 29, 2010, 12:49:24 PM »
That's beautiful code. Thanks

MickD

  • King Gator
  • Posts: 3520
  • (x-in)->[process]->(y-out)
[Boo] Selection set with filter
« Reply #3 on: January 29, 2010, 07:57:59 PM »
I can't take all the credit, I pinched most of it from one of GlennR's posts  (thanks Glenn) and changed it to Boo ;)

Boo is a nice language, it's easy to read and use just like Python, probably even a little better in some respects.

Here's a selection set example as well although I was having some issues with Boo and enums. I have a work around though and have made a post at the Boo mailing lists to see what the problem is so hopefully it will be a short term fix. Basically I just use the actual enum assigned value for the comparison and this works fine.

Here'tis
Code: [Select]
// Autocad enums, we need to fudge these as Boo doesn't handle enums to well just yet :(
// these values are taken from the C++ ARX documentation on PromptStatus enums
// eNone 5000 No result
// eNormal 5100 Request succeeded
// eError -5001 Nonspecific error
// eCancel -5002 User canceled the request with a CTRL-C
// eRejected -5003 AutoCAD rejected the request as invalid
// eFailed -5004 Link failure, possibly with the LISP interpreter
// eKeyword -5005 Keyword returned from a "get" routine
// eDirect -5999 Passed to endGetPoint() if the getpoint was nested within
//                      another geometric value prompt (such as for angle), and the response
//                      entered was such a value rather than a point

public static def Select3dSolids(prompt as string) as (ObjectId):
ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
// set up some prompt options:
pso = PromptSelectionOptions()
pso.MessageForAdding = prompt
pso.AllowDuplicates = false
// create an sset filter to only grab 3d solids, an array of typed values
ssFilter = SelectionFilter((TypedValue(0, "3DSOLID"),)) // notice the ','!
// get the sset:
res as PromptSelectionResult = ed.GetSelection(pso, ssFilter)
if res.Status != 5100 or res.Status == -5002: // OK and Cancel enums.
return null
return res.Value.GetObjectIds()
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

"The E in Javascript stands for 'easy'." Florin Pop tweet

fixo

  • Guest
Re: .NET SELECTION Routines
« Reply #4 on: August 27, 2010, 04:23:07 PM »
    ==  Continuous copy  ==

Code: [Select]
//inspired by Donnia Tabor-Hanson's (CadMama) continuous copy lisp 'cc.lsp'
[CommandMethod("CC")]
        public static void ContinuousCopy()

        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

            Database db = HostApplicationServices.WorkingDatabase;

            Editor ed = doc.Editor;

            Transaction tr = db.TransactionManager.StartTransaction();

            BlockTableRecord btr =

                   (BlockTableRecord)tr.GetObject(

                   db.CurrentSpaceId,

                   OpenMode.ForWrite,

                   false);

            using (tr)
            {
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect Object >>");

                peo.SetRejectMessage("\nNothing selected >>");

                PromptEntityResult res;

                res = ed.GetEntity(peo);

                if (res.Status != PromptStatus.OK)

                    return;

                Entity ent = (Entity)tr.GetObject(res.ObjectId, OpenMode.ForRead);

                if (ent == null)

                    return;

                Point3d pt = res.PickedPoint;

                PromptAngleOptions pao =

                            new PromptAngleOptions("\nSelect angle: ");

                PromptDoubleResult ares;

                ares = ed.GetAngle(pao);

                if (ares.Status != PromptStatus.OK)

                    return;

                double ang = ares.Value;

                PromptDistanceOptions pdo =

    new PromptDistanceOptions("\nEnter a distance >>");

                pdo.AllowNone = true;

                pdo.UseDefaultValue = true;

                pdo.DefaultValue = 12.0;

                pdo.Only2d = true;

                PromptDoubleResult dres;

                dres = ed.GetDistance(pdo);

                if (dres.Status != PromptStatus.OK)

                    return;

                double dist = dres.Value;

                double step = dist;

                PromptKeywordOptions pko = new PromptKeywordOptions("\nCopy or Break out? [Copy/Break]:", "Copy Break");

                pko.AllowNone = true;

                pko.Keywords.Default = "Copy";

                PromptResult kres = ed.GetKeywords(pko);

                ed.WriteMessage("\n" + kres.StringResult);

                while (kres.StringResult == "Copy")
                {
                    Entity cent =(Entity) ent.Clone() as Entity;

                    Point3d topt = PolarPoint(pt, ang, dist);

                    Matrix3d mtx = Matrix3d.Displacement(pt.GetVectorTo(topt));

                    cent.TransformBy(mtx);

                    btr.AppendEntity(cent);

                    tr.AddNewlyCreatedDBObject(cent, true);

                    db.TransactionManager.QueueForGraphicsFlush();

                    dist = dist+step;

                    kres = ed.GetKeywords(pko);

                    if (kres.StringResult != "Copy") break;
                }

                tr.Commit();
            }
        }

        // by Tony Tanzillo
        public static Point3d PolarPoint(Point3d basepoint, double angle, double distance)
        {
            return new Point3d(

            basepoint.X + (distance * Math.Cos(angle)),

            basepoint.Y + (distance * Math.Sin(angle)),

            basepoint.Z);
        }

gile

  • Water Moccasin
  • Posts: 2411
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #5 on: November 20, 2011, 05:16:46 AM »
Hi,

Here's a little example of using the Editor.SelectionAdded event to filter a selection.

This example defines an Editor extension method to select only Curve entities, an additional selection filter can be used.

Code: [Select]
        public static PromptSelectionResult GetCurveSelection(this Editor ed, params TypedValue[] filter)
        {
            ed.SelectionAdded += new SelectionAddedEventHandler(OnCurveSelectionAdded);
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            ed.SelectionAdded -= new SelectionAddedEventHandler(OnCurveSelectionAdded);
            return psr;
        }

        static void OnCurveSelectionAdded(object sender, SelectionAddedEventArgs e)
        {
            ObjectId[] ids = e.AddedObjects.GetObjectIds();
            for (int i = 0; i < ids.Length; i++)
            {
                if (!ids[i].ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve))))
                    e.Remove(i);
            }
        }
Speaking English as a French Frog

gile

  • Water Moccasin
  • Posts: 2411
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #6 on: June 30, 2013, 05:09:07 AM »
Hi,

This is just a example (related to this thread)  to show how it is possible to change the filtering criteria during the selection using Editor.SelectionAdded event.

In this example, the selection starts filtering lines and allows the user to change the filtered entities to circles or polylines by specifying keywords.

C#
Code - C#: [Select]
  1. using System.Collections.Generic;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace SelectionSample
  8. {
  9.     public class CommandMethods
  10.     {
  11.         private string keyWord;
  12.  
  13.         [CommandMethod("Test")]
  14.         public void Test()
  15.         {
  16.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  17.  
  18.             this.keyWord = "LIne";
  19.  
  20.             PromptSelectionOptions opt = new PromptSelectionOptions();
  21.             opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline");
  22.             opt.MessageForAdding = "\nSelect objects or " + opt.Keywords.GetDisplayString(true);
  23.             opt.KeywordInput += onKeywordInput;
  24.  
  25.             ed.SelectionAdded += onSelectionAdded;
  26.             PromptSelectionResult psr = ed.GetSelection(opt);
  27.             ed.SelectionAdded -= onSelectionAdded;
  28.             if (psr.Status == PromptStatus.OK)
  29.                 ed.SetImpliedSelection(psr.Value);
  30.         }
  31.  
  32.         private void onKeywordInput(object sender, SelectionTextInputEventArgs e)
  33.         {
  34.             this.keyWord = e.Input;
  35.         }
  36.  
  37.         private void onSelectionAdded(object sender, SelectionAddedEventArgs e)
  38.         {
  39.             RXClass rxc;
  40.             switch (this.keyWord)
  41.             {
  42.                 case "POlyline": rxc = RXClass.GetClass(typeof(Polyline)); break;
  43.                 case "CIrcle": rxc = RXClass.GetClass(typeof(Circle)); break;
  44.                 default: rxc = RXClass.GetClass(typeof(Line)); break;
  45.             }
  46.             ObjectId[] ids = e.AddedObjects.GetObjectIds();
  47.             for (int i = 0; i < ids.Length; i++)
  48.             {
  49.                 if (ids[i].ObjectClass != rxc)
  50.                     e.Remove(i);
  51.             }
  52.         }
  53.     }
  54. }

VB
Code - vb.net: [Select]
  1. Imports System.Collections.Generic
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5. Imports Autodesk.AutoCAD.Runtime
  6.  
  7. Namespace SelectionSample
  8.  
  9.     Public Class CommandMethods
  10.  
  11.         Private keyWord As String
  12.  
  13.         <CommandMethod("Test")> _
  14.         Public Sub Test()
  15.             Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
  16.  
  17.             Me.keyWord = "LIne"
  18.  
  19.             Dim opt As New PromptSelectionOptions()
  20.             opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline")
  21.             opt.MessageForAdding = vbLf & "Select objects or " & opt.Keywords.GetDisplayString(True)
  22.             AddHandler opt.KeywordInput, AddressOf onKeywordInput
  23.  
  24.             AddHandler ed.SelectionAdded, AddressOf onSelectionAdded
  25.             Dim psr As PromptSelectionResult = ed.GetSelection(opt)
  26.             RemoveHandler ed.SelectionAdded, AddressOf onSelectionAdded
  27.             If psr.Status = PromptStatus.OK Then
  28.                 ed.SetImpliedSelection(psr.Value)
  29.             End If
  30.         End Sub
  31.  
  32.         Private Sub onKeywordInput(sender As Object, e As SelectionTextInputEventArgs)
  33.             Me.keyWord = e.Input
  34.         End Sub
  35.  
  36.         Private Sub onSelectionAdded(sender As Object, e As SelectionAddedEventArgs)
  37.             Dim rxc As RXClass
  38.             Select Case Me.keyWord
  39.                 Case "POlyline"
  40.                     rxc = RXClass.GetClass(GetType(Polyline))
  41.                     Exit Select
  42.                 Case "CIrcle"
  43.                     rxc = RXClass.GetClass(GetType(Circle))
  44.                     Exit Select
  45.                 Case Else
  46.                     rxc = RXClass.GetClass(GetType(Line))
  47.                     Exit Select
  48.             End Select
  49.             Dim ids As ObjectId() = e.AddedObjects.GetObjectIds()
  50.             For i As Integer = 0 To ids.Length - 1
  51.                 If ids(i).ObjectClass <> rxc Then
  52.                     e.Remove(i)
  53.                 End If
  54.             Next
  55.         End Sub
  56.  
  57.     End Class
  58.  
  59. End Namespace

F#
Code - F#: [Select]
  1. module SelectionSample
  2.  
  3. open System.Collections.Generic
  4. open Autodesk.AutoCAD.ApplicationServices
  5. open Autodesk.AutoCAD.DatabaseServices
  6. open Autodesk.AutoCAD.EditorInput
  7. open Autodesk.AutoCAD.Runtime
  8.  
  9. [<CommandMethod("Test")>]
  10. let test () =
  11.     let ed = Application.DocumentManager.MdiActiveDocument.Editor
  12.  
  13.     let keyWord = ref "LIne"
  14.  
  15.     let opt = new PromptSelectionOptions()
  16.     opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline")
  17.     opt.MessageForAdding <- "\nSelect objects or " + opt.Keywords.GetDisplayString(true)
  18.     opt.KeywordInput.Add(fun (e: SelectionTextInputEventArgs) -> keyWord := e.Input)
  19.  
  20.     let onSelectionAdded =
  21.         new SelectionAddedEventHandler(fun _ e ->
  22.             let rxc =
  23.                 RXClass.GetClass(
  24.                     match !keyWord with
  25.                     | "CIrcle"   -> typeof<Circle>
  26.                     | "POlyline" -> typeof<Polyline>
  27.                     | _          -> typeof<Line>)
  28.             e.AddedObjects.GetObjectIds()
  29.             |> Array.iteri(fun i id -> if id.ObjectClass <> rxc then e.Remove(i)))
  30.  
  31.     ed.SelectionAdded.AddHandler(onSelectionAdded)
  32.     let psr = ed.GetSelection(opt)
  33.     ed.SelectionAdded.RemoveHandler(onSelectionAdded)
  34.     if psr.Status = PromptStatus.OK then
  35.         ed.SetImpliedSelection(psr.Value)
Speaking English as a French Frog

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: .NET SELECTION Routines
« Reply #7 on: June 30, 2013, 07:46:17 PM »
Very nice gile! I had desired this behavior but thought along the lines of Mr. Webb...
Do you think it would be worth adding another collection to track all raw selection so that when filter parameters are changed the user doesn't have to reselect objects which were excluded by previous filter parameters?