Aller au contenu

Sélection & Collection d'objets


PhilBat

Messages recommandés

Bonjour à tous

à partir d'une sélection d'objets (selectall)

je voudrai créer une autre sélection répondant à quelques critères (calque)

qui au final me permet de créer un bloc sur le disque dur. :unsure:

Voici un exemple de code :

       Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
       Dim ed As Editor = acDoc.Editor
       Dim Db As Database = acDoc.Database
       Dim idArray() As ObjectId
       'Dim blkRef As BlockReference
       Dim TemSsetObj As SelectionSet
       Dim acObjId As ObjectId

       Using Tr As Transaction = Db.TransactionManager.StartTransaction

           Dim res As PromptSelectionResult = ed.SelectAll()
           Dim acObjIdColl As ObjectIdCollection = New ObjectIdCollection()

           If (res.Status <> PromptStatus.OK) Then
               ed.WriteMessage(vbLf & "Failed to select all entity [Lg..-prmfolio]")
               GoTo Fin
           End If
           Dim acSSet As SelectionSet = res.Value

           For I = 0 To UBound(Calque)
               If Not TemForcSuf Then txtSuffixe.Text = Calque(I)

               For Each acObjId In acSSet.GetObjectIds()
                   Dim acEnt As Entity = Tr.GetObject(acObjId, OpenMode.ForRead)
                   If Not IsDBNull(acEnt) Then
                       If Microsoft.VisualBasic.Right("00" & acEnt.Layer, 3) = Calque(I) Or (acEnt.Layer = "FDP" And Calque(I) <> "PDG") Then
                           acObjIdColl.Add(acObjId)
                       End If
                   End If
               Next

               ThisDrawing.Wblock(PathAff & "\" & Trim(txtPrefixe.Text) & Trim(txtRacine.Text) & "_" & Trim(txtSuffixe.Text) & ".dwg", ????????)
               acObjIdColl.Clear()
               If TemForcSuf Then txtSuffixe.Text = IncNum(txtSuffixe.Text, 1)
           Next

           Tr.Commit()
Fin:
       End Using
       Me.Close()
   End Sub

 

nota: la variable 'Calque' est la liste des calques triés numériquement (calque '1' puis '2' ...etc)

Suivant le lien

http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer%27s%20Guide/index.html

il faut utilisé une collection pour travailler avec plusieurs sélections.

Mais au final j'ai besoin d'une sélection pour créer mon bloc et pas d'une collection.

Comment faire ? :(

Merci

Phil.

Lien vers le commentaire
Partager sur d’autres sites

Tu dois passer un filtre de sélection à SelectAll :

 

var tv = new[]
{
   new TypedValue((int) DxfCode.Operator, "<OR"),
   new TypedValue((int) DxfCode.LayerName, "Calque1"),
   new TypedValue((int) DxfCode.LayerName, "Calque2"),
   [..]
   new TypedValue((int) DxfCode.Operator, "OR>")
;
var sf = new SelectionFilter(tv);
ed.SelectAll(sf);

 

C'est en C# désolé, j'ai la flemme de traduire ça en VB.

Maxence DELANNOY

Développement de compléments aux logiciels Autodesk : AutoCAD, Revit, Inventor, Vault, Navisworks... et autres logiciels de CAO

WIIP - http://wiip.fr

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Comme dis Maxence, en utilisant des filtres de sélection tu auras directement des sélections.

 

Tu peux aussi créer un jeu de sélection à partir d'un tableau d'ObjectId en utilisant la méthode statique/Shared SelectionSet.FromObjectIds().

 

Mais, encore une fois essaye d'arrêter de mélanger .NET et VBA...

Il n'est pas difficile de de faire un Wblock à partir d'un ObjectIdCollection en .NET

 

        private void WBlock(ObjectIdCollection ids, string filename)
       {
           Database db = HostApplicationServices.WorkingDatabase;
           using (Database target = new Database())
           {
               db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Replace);
               target.SaveAs(filename, DwgVersion.Current);
           }
       }

 

PS: tu pourrais aussi facilement éviter cet horrible GoTo...

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Oui pour les filtres

mais il est facile de les créer quand on sait d'avance les calques concernés

ce qui n'est pas mon cas : d'un dwg à l'autre je n'ai pas la même chose (le nombre de calque peut varier). Il faut que je les traite dans l'ordre croissant.

Je doute que le code suivant me donne un listing qui respecte cela :

      Using Tr As Transaction = Db.TransactionManager.StartTransaction
           Dim acLyrTbl As LayerTable
           acLyrTbl = Tr.GetObject(Db.LayerTableId, OpenMode.ForRead)
           For Each acObjId As ObjectId In acLyrTbl
               Dim acLyrTblRec As LayerTableRecord
               acLyrTblRec = Tr.GetObject(acObjId, OpenMode.ForRead)
               If acLyrTblRec.Name = "1" Then
                   ..........
               End If
           Next
      End Using

Il faut que le programme s'adapte.

 

Pardon pour le goto, il faut absolument le retirer des commandes de vs2010... :blink:

nota: le nom des calques peut varier de "1","2","3" à l'infini.

Lien vers le commentaire
Partager sur d’autres sites

Pour faire ce que tu veux, si je comprends bien faire un Wblock par calque, le plus "simple" est d'utiliser Linq qui permet de faire des requêtes sur tout type de collection et donc de grouper les ObjectId des entités par calque.

 

Un exemple:

 

        public void Test()
       {
           Document doc = AcAp.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;
           PromptSelectionResult psr = ed.SelectAll();
           if (psr.Status != PromptStatus.OK) return;
           using (Transaction tr = db.TransactionManager.StartTransaction())
           {
               var grps = from id in psr.Value.GetObjectIds()
                          group id by ((Entity)id.GetObject(OpenMode.ForRead)).Layer;

               foreach (IGrouping<string, ObjectId> grp in grps)
               {
                   if (!TemForcSuf)  txtSuffixe.Text = grp.Key;

                   ObjectIdCollection ids = new ObjectIdCollection(grp.ToArray());
                   string filename = string.Format("{0}\\{1}{2}_{3}.dwg",
                       PathAff, txtPrefixe.Text.Trim(), txtRacine.Text.Trim(), txtSuffixe.Text.Trim());

                   using (Database target = new Database())
                   {
                       db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Replace);
                       target.SaveAs(filename, DwgVersion.Current);
                   }
               }
               tr.Commit();
           }
       }

 

Le même code en VB:

 

        Public Sub Test()
           Dim doc As Document = Application.DocumentManager.MdiActiveDocument
           Dim db As Database = doc.Database
           Dim ed As Editor = doc.Editor

           Dim psr As PromptSelectionResult = ed.SelectAll
           If psr.Status <> PromptStatus.OK Then Return

           Using tr As Transaction = db.TransactionManager.StartTransaction()

               Dim grps = From id In psr.Value.GetObjectIds()
                          Group id By DirectCast(id.GetObject(OpenMode.ForRead), Entity).Layer
                          Into Group

               For Each grp In grps
                   If Not TemForcSuf Then txtSuffixe.Text = grp.Layer
                   Dim ids As ObjectIdCollection = New ObjectIdCollection(grp.Group.ToArray())
                   Dim filename As String = String.Format("{0}\\{1}{2}_{3}.dwg", _
                                                          PathAff, txtPrefixe.Text.Trim(), txtRacine.Text.Trim(), txtSuffixe.Text.Trim())
                   Using target As New Database
                       db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Ignore)
                       target.SaveAs(filename, DwgVersion.Current)
                   End Using
               Next
               tr.Commit()
           End Using
       End Sub

 

On peut aussi écrire les requêtes Linq sous forme de "chaînage" de méthodes. L'interface générique IEnumerable fournit de nombreuses méthodes d'extensions (plus que ce permettent les requêtes SQL classiques.

Ces méthodes requièrent souvent une (ou plusieurs) méthode comme argument (qu'on peut passer sous forme d'expression lambda).

 

La requête ci dessus :

Dim grps = psr.Value.GetObjectIds() _
          .GroupBy(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), Entity).Layer)

Dans ce cas, dans l'expression For Each, on accède à la clé de chaque IGrouping par grp.Key et au groupe d'ObjectId directement par grp :

For Each grp In grps
   If Not TemForcSuf Then txtSuffixe.Text = grp.Key
   Dim ids As ObjectIdCollection = New ObjectIdCollection(grp.ToArray())

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Pour le fun, l'équivalent F# :

 

let Test() =
   let doc = AcAp.DocumentManager.MdiActiveDocument
   let db = doc.Database
   let ed = doc.Editor
   let psr = ed.SelectAll()
   if psr.Status = PromptStatus.OK then
       use tr = db.TransactionManager.StartTransaction()
       psr.Value.GetObjectIds()
       |> Seq.groupBy(fun id -> (id.GetObject(OpenMode.ForRead) :?> Entity).Layer)
       |> Seq.iter(fun grp -> 
           let ids = new ObjectIdCollection(snd grp |> Seq.toArray)
           let filename = String.Format(@"C:\Temp\{0}.dwg", fst grp)
           use target = new Database()
           db.Wblock(target, ids, Point3d.Origin, DuplicateRecordCloning.Ignore)
           target.SaveAs(filename, DwgVersion.Current))
       tr.Commit()

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

À ma connaissance il n'y en a qu'un en anglais : VB.NET Programming for AutoCAD Customization de Jerry Winters.

Je ne l'ai pas lu, donc je ne peux pas en dire plus peut être que Patrick, s'il passe par là, pourra en dire plus (il me semble qu'il l'a lu).

 

Dans tout les cas, encore une fois, avant de s'attaquer à la programmation d'AutoCAD en .NET, il est, à mon avis, indispensable de se familiariser avec .NET en général (Visual Studio, la POO, les bibliothèques de classe du Framework). Et pour ça, il y a pléthore de sites , tutoriels, livres en français comme en anglais.

Par exemple, l'utilisation de Linq telle que montrée ci-dessus, n'est pas du tout spécifique à AutoCAD (Linq sert avant tout pour l'accès aux bases de données).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité