.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Preselect Selectionset Programmatically And Let User Modify It

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
DECH0002
3206 Views, 8 Replies

Preselect Selectionset Programmatically And Let User Modify It

Hi there!

 

I'm trying to find a solution for the following task:

 

I have to programmatically select some entities based on a predefined algorithm (It doesent matter which one, but to be clear e.g. Every 2nd block of a given name in x-direction between two points). Then I have to highlight them and let the user add other entities to, or remove preselected entities from this selection set by selecting them on screen.

 

I tried to prototype it in LISP like this, but failed, because I can't control what the user selects with this method:

(setq PreSs (ComputePreSelection))

(command "_.SELECT")

(if PreSs (command PreSs))

(while (> (getvar "CMDACTIVE") 0) (command pause))

(setq SelSet (ssget "_P")

 

I also failed using this code, because I can't deselect the preselected entities while looping in the filtering ssget call:

(setq PreSs (ComputePreSelection))

(command "_.SELECT")

(if PreSs (command PreSs))

(command (ssget '(( 0 . "INSERT") (8 . "S_ON*"))))

(setq SelSet (ssget "_P")

 

 

Is there a possibility using .NET to pass a predefined selection set to a selection method and let it modify while taking a filter into account?

 

TIA - Martin

8 REPLIES 8
Message 2 of 9
moogalm
in reply to: DECH0002

Hi Martin ,

 

One way of doing in .NET is use SetImpliedSelection API ,which preselects the entities which are passed to the API , it accepts ObjectID array.

So you can programatically popuplate the array.

 

Code Sample :

 

public static void FilterSelectionSet()
{
    // Get the current document editor
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
    Document doc = Application.DocumentManager.MdiActiveDocument;

    /*To Illustrate I'm getting an Object Id of single blockreference*/
    ObjectIdCollection idColl = new ObjectIdCollection();
    Handle blockHandle = new Handle(0x350);
    ObjectId id1 = ObjectId.Null;
    if (doc.Database.TryGetObjectId(blockHandle, out id1))
    {
        idColl.Add(id1);
    }
    ObjectId[] idArray = new ObjectId[idColl.Count];
    idColl.CopyTo(idArray, 0);
    /*This imply the selection of block reference and user can deselect later*/
    ed.SetImpliedSelection(idArray);

}

 

 

Message 3 of 9
BlackBox_
in reply to: DECH0002


@DECH0002 wrote:

 

I have to programmatically select some entities based on a predefined algorithm (It doesent matter which one, but to be clear e.g. Every 2nd block of a given name in x-direction between two points). Then I have to highlight them and let the user add other entities to, or remove preselected entities from this selection set by selecting them on screen.

 

I tried to prototype it in LISP like this, but failed, because I can't control what the user selects with this method:

(setq PreSs (ComputePreSelection))

(command "_.SELECT")

(if PreSs (command PreSs))

(while (> (getvar "CMDACTIVE") 0) (command pause))

(setq SelSet (ssget "_P")

 

I also failed using this code, because I can't deselect the preselected entities while looping in the filtering ssget call:

(setq PreSs (ComputePreSelection))

(command "_.SELECT")

(if PreSs (command PreSs))

(command (ssget '(( 0 . "INSERT") (8 . "S_ON*"))))

(setq SelSet (ssget "_P")

 

...


FWIW - To 'select' entities in LISP, simply pass your selection set to the SSSETFIRST LispFunction.

 

Cheers



"How we think determines what we do, and what we do determines what we get."

Message 4 of 9
DECH0002
in reply to: BlackBox_

Thanks for your answers, I'll give it a try this week or so.

Message 5 of 9
DECH0002
in reply to: moogalm

Hi Madhukar

 

Unfortunately, the proposed solution does not, what I expect, no matter if I use the LISP or the .NET variant.

 

What happens depends on the setting of PICKFIRST. If PICKFIRST is 1, then the subsequent call to Editor.GetSelection immediately returns the selection set I passed to SetImpliedSelection. If PICKFIRST is 0, the entities I pass to SetImpliedSelection are highlighted with GRIPS and I can select objects mannually. However, deselecting entities from the implied selection set is not possible. But this is, what I described in my topic title with "Preselect Selectionset Programmatically And Let User Modify It". EDIT: Probably there is an option of GetSelection, I missed???

 

Let me tell in detail, what I have to achieve:

 

I'm developing an application for railway switch and track planning. Switches and tracks have a hughe amount of sleepers. Now, we have the need to select multiple sleepers along a rail. Because sleepers are displayed in dashed lines sometimes, the fence selection method fails too often because of its lack to select objects when the rubber band crosses a dashed line at one of its gaps.

 

In addition, we have the need to select only every 2nd, 3rd (a.s.o.) sleeper fore some actions. So we implemented a selection method which lets the user select a rail (which is a polyline in fact), a start point, and an end point. The method will now select those sleepers which are crossing the rail and are matching the interval condition. Until here, everything works fine. We have an array of ObjectId's or selection set of preselected entities (sleepers).

 

Now, the user should be eligible to add, or remove individual sleepers to, or from the selection set. That said, he must be able to modify the programmatically preselected selection. And, to make things more complex, he must be eligible only to add new sleepers (which are blocks, in fact), nothing else.

 

I hope my explanations are understandable. Thank you for your further investigation.

 

Regards,

Martin

 

EDIT: I do not necessarely need a .NET API solution. LISP can do as well.

Message 6 of 9
moogalm
in reply to: DECH0002

Hi

 

Thanks for your detailed explanation ,this helped a lot .

I'm assuming you are working on .NET 4.5 and AutoCAD 2015 SP2.

Sorry I have more expertise on .NET than LISP.

 

I have attached code snippet and test with pickfirst =0 &=1 I see no difference, in the preselection.

In the attached video link I have demonstrated  deselecting entities and selecting  entities too.

I have attached my test DWG too.

 

 

 

public static SelectionSet ss;
        // Modal Command with pickfirst selection
        [CommandMethod("MyGroup", "MyPickFirst", "MyPickFirstLocal", CommandFlags.Modal | CommandFlags.UsePickSet)]
         async public void MyPickFirst() // This method can have any name
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            ed.PromptedForSelection+=ed_PromptedForSelection;
            try
            {
                await ed.CommandAsync("_.Select");

                ObjectIdCollection idColl = new ObjectIdCollection();

                // Preselect 350, 3AE 
                Handle h1 = new Handle(0X350);
                ObjectId id1 = ObjectId.Null;
                if (doc.Database.TryGetObjectId(h1, out id1))
                {
                    idColl.Add(id1);
                }

                Handle h2 = new Handle(0X3AE);
                ObjectId id2 = ObjectId.Null;
                if (doc.Database.TryGetObjectId(h2, out id2))
                {
                    idColl.Add(id2);
                }

                /*You can populate array*/
                ObjectId[] ids = new ObjectId[idColl.Count];
                idColl.CopyTo(ids, 0);

                ss = SelectionSet.FromObjectIds(ids);
                await ed.CommandAsync(ss, Editor.PauseToken);

                // Let the user select / unselect more entities.
                // To unselect use shift+click
                           
               



            }
            catch (Autodesk.AutoCAD.Runtime.Exception)
            {
                ed.WriteMessage("Exception thrown.");
            }
         
        }

        private void ed_PromptedForSelection(object sender, PromptSelectionResultEventArgs e)
        {
          Editor ed = sender as Editor;
          PromptSelectionResult result =  e.Result;
          if (result.Status != PromptStatus.OK)
          {
            
              ed.PromptedForSelection -= ed_PromptedForSelection;
              return; 
          }
          ss = result.Value;
          Application.ShowAlertDialog("Number of objects selected: " +
                                         ss.Count.ToString());
          foreach (ObjectId id in ss.GetObjectIds())
          {
              ed.WriteMessage("selected Objects are {0} \n", id.Handle.ToString());
             
          }
  
        }

 

 

 

 

Message 7 of 9
DECH0002
in reply to: moogalm

Hello Madhukar

 

Thank you for your great work. Since I'm still working with AutoCAD 2014/.NET4, it's not directly useable for me, since CommandAsync was introduced with Release 2015. However, I appreciate your solution, since it shows us how to achieve this in future releases, and it pointed me to the solution for the current release.

 

Just wanted to add a hint for future readers: The request to filter the user selected entities can be achieved by adding a SelectionAdded event handler to the Editor instance.

 

For now, I'll solve this request in a mixed LISP/.NET implementation like folows:

 

(setq ps (eacl_acquireSleepers)) ; Preselect some sleepers according the algorithm described in a previous post.
(eacl_sethandler) ; attach a SelectionAdded event handler in a .NET-implemented lisp function.
(command "_.SELECT" ps) ; Add the preselected sleepers to the selection set, so they are highlighted.
(while (> (getvar "CMDACTIVE") 0) ; Let the user add or remove entities as long as the user does not presses enter.
 (command pause)
)
(setq ss (ssget "_P")) ; Get the selected sleepers.
(eacl_removehandler) ; detach the SelectionAdded event handler in a .NET-implemented lisp function.

 The .NET part will look like this:

 

        [LispFunction("eacl_sethandler")]
        public void SetHandler(ResultBuffer args) // This method can have any name
        {
            // Put your command code here

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

            Editor ed = doc.Editor;

            ed.SelectionAdded += EditorOnSelectionAdded;
        }
[LispFunction("eacl_removehandler")] public void RemoveHandler(ResultBuffer args) // This method can have any name { // Put your command code here Document doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; ed.SelectionAdded -= EditorOnSelectionAdded; } private void EditorOnSelectionAdded(object sender, SelectionAddedEventArgs selectionAddedEventArgs) { var ed = (Editor) sender; using (Transaction tr = ed.Document.TransactionManager.StartOpenCloseTransaction()) { for (int i = 0; i < selectionAddedEventArgs.AddedObjects.Count; i++) { SelectedObject addedObject = selectionAddedEventArgs.AddedObjects[i]; var curEnt = tr.GetObject(addedObject.ObjectId, OpenMode.ForRead) as Entity; if (curEnt != null) { if (!(curEnt.Layer.Equals("MySpecificLayer") && curEnt.GetType() == typeof (BlockReference))) { selectionAddedEventArgs.Remove(i); } } else { ed.WriteMessage("\nPanic!"); } } } }

 Disclaimer: This code was not tested at all and might contain errors. And of course, I'll make that more generic and robust than shown above but as a starting point for others, it should satisfy.

Message 8 of 9
phliberato
in reply to: moogalm

Good Solution! 
But now I have another problem, I need to use the selection with Keywords and I need to change the prompt message. Is it possible?

 

Thanks.

Message 9 of 9
BlackBox_
in reply to: DECH0002

FWIW -

Consider REDRAW LispFunction in lieu of SELECT Command calls.

Cheers


"How we think determines what we do, and what we do determines what we get."

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost