Author Topic: Selection set - get single block loop thru  (Read 7484 times)

0 Members and 1 Guest are viewing this topic.

jcoon

  • Newt
  • Posts: 157
Selection set - get single block loop thru
« on: April 13, 2014, 12:29:37 PM »
Group,

I'm having difficultly with a selection set to loop thru block reference. I'm able to use the SS with GetSelection to select onscreen and filter blocks by name, I also used SelectAll to loop thru all the blocks to retrieve the named block. These are all filtered with  TypedValue like (2, "Enter block name"). What I'd like to do is use the  PromptSelectionOptions  to prompt to select only one block in the drawing and retrieve the block name and layer of the selected block, then use the block name and layer from the prompt as the filter for TypedValue to be used with the selectall to return all blocks in the drawing that match the filter.

thanks for any links or sample you can provide
John

sample:
<CommandMethod("filterblocks")> _
    Public Sub filterblocks()
        '' Get the current document editor
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        '' Create a TypedValue array to define the filter criteria

        Dim filterlist() As TypedValue = New TypedValue((2) - 1) {}
        filterlist(0) = New TypedValue(0, "INSERT")
        filterlist(1) = New TypedValue(2, "RWLBM")
        Dim filter As SelectionFilter = New SelectionFilter(filterlist)

        '' Assign the filter criteria to a SelectionFilter object
        Dim acSelectionfilter As SelectionFilter = New SelectionFilter(filterlist)
        '' Request for objects to be selected in the drawing area
        Dim acSSPrompt As PromptSelectionResult
        acSSPrompt = ed.SelectAll(acSelectionfilter)

        '' If the prompt status is OK, objects were selected
        If acSSPrompt.Status = PromptStatus.OK Then
            Dim acSSet As SelectionSet = acSSPrompt.Value
            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Number of objects selected: " & acSSet.Count.ToString())
        Else
            Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Number of objects selected: 0")
        End If
    End Sub

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Selection set - get single block loop thru
« Reply #1 on: April 13, 2014, 01:33:56 PM »
Hi,

Here's an example (written in C#, but easy to convert).
No need to check if the selection set is empty, it must contains almost the first selected block.

Code - C#: [Select]
  1.         [CommandMethod("filterblocks")]
  2.         public void FilterBlocks()
  3.         {
  4.             Document doc = AcAp.DocumentManager.MdiActiveDocument;
  5.             Database db = doc.Database;
  6.             Editor ed = doc.Editor;
  7.  
  8.             PromptEntityOptions opts = new PromptEntityOptions("\nSelect the target block: ");
  9.             opts.SetRejectMessage("Only a block.");
  10.             opts.AddAllowedClass(typeof(BlockReference), true);
  11.             PromptEntityResult per = ed.GetEntity(opts);
  12.             if (per.Status != PromptStatus.OK)
  13.                 return;
  14.  
  15.             using (Transaction tr = db.TransactionManager.StartTransaction())
  16.             {
  17.                 BlockReference br = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
  18.                 TypedValue[] filterList = new TypedValue[3]
  19.                 {
  20.                     new TypedValue(0, "INSERT"),
  21.                     new TypedValue(2, br.Name),
  22.                     new TypedValue(8, br.Layer)
  23.                 };
  24.                 PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filterList));
  25.                 ed.SetImpliedSelection(psr.Value);
  26.                 ed.WriteMessage("\nNumber of selected objects: {0}", psr.Value.Count);
  27.                 tr.Commit();
  28.             }
  29.         }
Speaking English as a French Frog

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #2 on: April 14, 2014, 11:57:12 AM »
gile,

Thanks,  I'll give it a try after work.

Thank you for the help

John

n.yuan

  • Bull Frog
  • Posts: 348
Re: Selection set - get single block loop thru
« Reply #3 on: April 14, 2014, 01:25:12 PM »
If the target blockreference (to be selected) is derived from a dynamic block definition, then the "BlockName" filter may not work (e.g. if all block references are based on anonymous block definitions, generated according to the dynamic block definition).

So, you may only want to use Block Name as filter only the target block references are not dynamic block.

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #4 on: April 15, 2014, 08:52:26 AM »
n.yuan,

The selected block should not be dynamic but it might be smart to add it.

Gile,
Thanks, I got the sample to work, just adding a few checks for layers.

Thank you both for the help

John

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Selection set - get single block loop thru
« Reply #5 on: April 15, 2014, 10:53:46 AM »
This should work with dynamic blocks;

Code - C#: [Select]
  1.         [CommandMethod("filterblocks")]
  2.         public void FilterBlocks()
  3.         {
  4.             Document doc = AcAp.DocumentManager.MdiActiveDocument;
  5.             Database db = doc.Database;
  6.             Editor ed = doc.Editor;
  7.  
  8.             PromptEntityOptions opts = new PromptEntityOptions("\nSelect a block: ");
  9.             opts.SetRejectMessage("Only a block.");
  10.             opts.AddAllowedClass(typeof(BlockReference), true);
  11.             PromptEntityResult per = ed.GetEntity(opts);
  12.             if (per.Status != PromptStatus.OK)
  13.                 return;
  14.  
  15.             using (Transaction tr = db.TransactionManager.StartTransaction())
  16.             {
  17.                 BlockReference br = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
  18.                 blockName = GetEffectiveName(br);
  19.                 TypedValue[] filterList = new TypedValue[3]
  20.                 {
  21.                     new TypedValue(0, "INSERT"),
  22.                     new TypedValue(2, "`*U*," + blockName),
  23.                     new TypedValue(8, br.Layer)
  24.                 };
  25.                 ed.SelectionAdded += onSelectionAdded;
  26.                 PromptSelectionResult psr = ed.SelectAll(new SelectionFilter(filterList));
  27.                 ed.SelectionAdded -= onSelectionAdded;
  28.                 ed.SetImpliedSelection(psr.Value);
  29.                 ed.WriteMessage("\nNumber of selected objects: {0}", psr.Value.Count);
  30.                 tr.Commit();
  31.             }
  32.         }
  33.  
  34.         private string blockName;
  35.  
  36.         private string GetEffectiveName(BlockReference br)
  37.         {
  38.             return br.IsDynamicBlock ?
  39.                 ((BlockTableRecord)br.DynamicBlockTableRecord.GetObject(OpenMode.ForRead)).Name :
  40.                 br.Name;
  41.         }
  42.  
  43.         void onSelectionAdded(object sender, SelectionAddedEventArgs e)
  44.         {
  45.             for (int i = 0; i < e.AddedObjects.Count; i++)
  46.             {
  47.                 BlockReference br = (BlockReference)e.AddedObjects[i].ObjectId.GetObject(OpenMode.ForRead);
  48.                 if (GetEffectiveName(br) != blockName)
  49.                     e.Remove(i);
  50.             }
  51.         }
Speaking English as a French Frog

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #6 on: April 18, 2014, 01:03:24 PM »
gile,

I'll convert and test tonight.  I never used SetImpliedSelection before, thought it was something that I'd like to add to a few of my routines. thank you.  You learn something everyday reading these posts

John

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #7 on: June 04, 2014, 04:21:01 PM »
All,
looking to revisit selection set to write block reference coordinates to a text file, x,y,z, csv.  print to dialog for testing is perfect.
I don't understand how to get the x,y,z positions for the block in the selection set. It appears the ss does not contain the insertion point of the blocks, I can get the layer and block name but I don't know where or how the get the insertion points. what do I need to access to pull those values out.


Do I get the insertion points from the objectid?


sample I was using
Code: [Select]

<CommandMethod("filterblocks10")> _
    Public Sub FilterBlocks10()
        Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor()
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim acaddoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim opts As PromptEntityOptions = New PromptEntityOptions("" & vbLf & "Select One Target Block, For Selection Set:")
        opts.SetRejectMessage("No Target Block Selected.")
        opts.AddAllowedClass(GetType(Autodesk.AutoCAD.DatabaseServices.BlockReference), True)
        Dim per As PromptEntityResult = ed.GetEntity(opts)

        If (per.Status <> PromptStatus.OK) Then
            Return
        End If

        Dim oSset As SelectionSet = Nothing
        Dim mytrans As Transaction = db.TransactionManager.StartTransaction
        Dim br As Autodesk.AutoCAD.DatabaseServices.BlockReference = CType(mytrans.GetObject(per.ObjectId, OpenMode.ForRead), Autodesk.AutoCAD.DatabaseServices.BlockReference)
        Dim acBlockTable As BlockTable
        acBlockTable = mytrans.GetObject(db.BlockTableId, OpenMode.ForRead)
        Dim acBlockTableRec As BlockTableRecord
        acBlockTableRec = mytrans.GetObject(acBlockTable(BlockTableRecord.ModelSpace), OpenMode.ForWrite)

        Dim filterlist() As TypedValue = New TypedValue((3) - 1) {}
        filterlist(0) = New TypedValue(0, "INSERT")
        filterlist(1) = New TypedValue(2, br.Name)
        filterlist(2) = New TypedValue(8, br.Layer)

        Dim filter As SelectionFilter = New SelectionFilter(filterlist)
        Dim psr As PromptSelectionResult = ed.SelectAll(New SelectionFilter(filterlist))
        ed.SetImpliedSelection(psr.Value)
        ed.WriteMessage("" & vbLf & "Number of selected objects: {0}", psr.Value.Count)

        'show dialog with filter results, insert, block name and layer name. need block position.x,block position.y,block position.z
        Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Number of objects selected: " & psr.Value.Count.ToString())
        Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Block Name is: " & br.Name.ToString())
        Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Block Is on Layer: " & br.Layer.ToString())
        'Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("x insertion point : " & br.pointion.x.ToString())
        'Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("y insertion point : " & br.pointion.y.ToString())
        'Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("z insertion point : " & br.pointion.z.ToString())

        mytrans.Commit()
    End Sub

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Selection set - get single block loop thru
« Reply #8 on: June 04, 2014, 08:31:59 PM »
I'm curious how you figure you're getting the block name and layer from the selection set.

My first comment is go download the ObjectARX SDK so you can get the documentation.

Moving on to details, the code block you've posted is giving you info on the block you opened during your entity selection at the start.  If you want to access the entities pointed to by your selection set then you're going to need to open them.  Something like:

Code - C#: [Select]
  1. foreach (ObjectId id in psr.GetObjectIds())
  2. {
  3.    BlockReference br = (BlockReference)tr.GetObject(id,Openmode.ForRead);
  4.    ~~write data to file~~
  5. }

To specifically answer your question, no you do not get insertion point from the objectid.  You get the id from the selection set and you get the block from the id and you get the insertion from the block

ss --> ObjectId[] --> BlockReference --> Position

To reiterate... DOWNLOAD THE SDK! It answers all of these things for you and will give you some better confidence in your code


Edit: Had opened block for write

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Selection set - get single block loop thru
« Reply #9 on: June 05, 2014, 01:09:24 AM »
Just had a thought about this...

This would be a great case for the GetObjects<T>() method that was floating around the swamp somewhere

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #10 on: June 05, 2014, 11:26:37 AM »
Will,

I've downloaded SDK as you suggested, I'll see if I can get this worked out with that. What selection should I look at first for the description of the blockreference postion and the id ?

Sorry about the selection Set, It appears that I pasted the sample before my selection set. I was using SS = myPSR.Value

Thank you for the help

john

jcoon

  • Newt
  • Posts: 157
Re: Selection set - get single block loop thru
« Reply #11 on: June 09, 2014, 07:42:37 AM »
Will,

I ordered a book AutoCAD vb.net training that should help. Thanks for help with this.
John