Aller au contenu

parcourir une selection


Messages recommandés

Posté(e)

Bonjour a tous et toutes!

 

Je cherche une routine ou une fonction qui permet de parcourir un jeu de sélection à la manière de la fonction ""foreach"" (mais qui marche que pour parcourir une liste)

 

ou avec un ""vlax-for "" mais je n'arrive pas a obtenir le VLA-objet d'un jeu de sélection.

 

Si vous avez une idée, merci!

 

ps: j'essaye de ne pas utiliser de boucle ""while""

 

 

Posté(e)

Salut wookichu,

 

Pour parcourir une sélection tu peux utiliser un repeat à la place du while :

(setq cpt 0)
(repeat (sslength select)
    (setq ent (ssname select cpt)
              vl_ent (vlax-ename->vla-object ent)
    )

    ....


    (setq cpt (1+ cpt))
)

 

Tous pour lisp, Lisp pour tous!

Avec Revit, cela ne vas trop vite...

Posté(e)

Bonjour,

 

Ou tu peux utiliser cette fonction qui retourne le jeu de sélection ss sous forme de liste

 

(defun ss_list  (ss)
 (if ss
   (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))))

 

Tu peux ensuite utiliser un mapcar ou un foreach pour itérer sur chacun des élément.

 

Etienne

www.le-metal.net, sur la métallerie
Posté(e)

Salut,

 

Quelques classiques :

 

avec repeat :

(repeat	(setq n (sslength ss))
 (setq ent (ssname ss (setq n (1- n))))
 (princ (strcat "\n" (cdr (assoc 0 (entget ent)))))
)

 

avec while :

(setq n -1)
(while (setq ent (ssname ss (setq n (1+ n))))
 (princ (strcat "\n" (cdr (assoc 0 (entget ent)))))
)

 

avec foreach et ssnamex (plus concis, mais plus lent)

(foreach ent (vl-remove-if 'listp (mapcar 'cadr (ssnamex ss)))
 (princ (strcat "\n" (cdr (assoc 0 (entget ent)))))
)

 

avec vlax-for et le jeu de sélection actif :

(vlax-for ent (vla-get-ActiveSelectionSet
	(vla-get-ActiveDocument
	  (vlax-get-acad-object)
	)
      )
 (princ (strcat "\n" (vla-get-ObjectName ent)))
)

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

Posté(e)

merci pour ta réponse mais repeat ou while , même combat.

 

je veux justement arrêter d'utiliser des compteurs!

et travailler sur chaque élément de la sélection successivement!

d'où ma demande de fonction ou routine pour retrouver le vla-objet d'un jeu de sélection que j'ai mis au préalable dans une variable..(donc pas le jeu de sélection actif)

 

 

merci encore!

Posté(e)

je veux justement arrêter d'utiliser des compteurs!

et travailler sur chaque élément de la sélection successivement!

 

Je ne vois pas où est le problème, le compteur est nécessaire pour une utilisation avec ssname qui est la seule façon d'accéder aux entités contenues dans le jeu de sélection (ssnamex procède de la même façon en interne).

Tu peux travailler successivement sur chaque élément, dans les exemples que j'ai donné, je fais un princ pour imprimer le type d'entité de chaque élément, tu peux à la place faire n'importe quel processus :

remplace :

(princ (strcat "\n" (cdr (assoc 0 (entget ent)))))

par :

(setq obj (vlax-ename->vla-object ent)
;; puis fais ce que tu veux avec le vla-object...

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

Posté(e)

je vais voir comment j'arrive a me dépatouiller avec la méthode: foreach et ssnamex de (gile)

 

Titifonky avait aussi donné cette solution qui, je le répète est plus lente que les autres.

 

ssnamex retourne une liste complexe qu'il faut traiter avec un mapcar et un vl-remove-if pour n'en garder que les noms d'entités : on parcourt déjà deux fois la liste avant de la parcourir une dernière fois pour traiter les entités.

 

Les méthodes while et repeat pourraient aussi servir à construire une liste qu'on utiliserait ensuite avec foreach, mais là encore, on parcourt une fois de trop la liste à mon avis.

 

Si on veut automatiser efficacement des taches, il faut éviter les processus inutiles...

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

Posté(e)

@(gile)

si je comprend bien tu préconise d'utiliser vlax-for.

 

mais est-on obligé d'utiliser le jeu de sélection actif ou peut-on prendre un autre jeu de sélection ?

Posté(e)

@(gile)

si je comprend bien tu préconise d'utiliser vlax-for.

 

Pas du tout, à mon avis, vlax-for n'est intéressant que quand on utilise le jeu de sélection actif et qu'on veut directement obtenir des vla-objects.

 

Je préconise while ou repeat.

Il semble que tu ne comprennes pas que parcourir le jeu de sélection directement avec while ou repeat permet de faire exactement les mêmes choses que ce que permet de faire foreach avec une liste.

La différence est seulement que pour avoir une liste, il a fallu déjà parcourir au moins une fois le jeu de sélection.

 

(repeat	(setq n (sslength ss))
 (setq obj (vlax-ename->vla-object (ssname ss (setq n (1- n)))
 ;; ici, je fais ce que je veux avec le vla-object
)

 

(setq n -1)
(while (setq ent (ssname ss (setq n (1+ n))))
 (setq obj (vlax-ename->vla-object ent)
 ;; ici, je fais ce que je veux avec le vla-object
)

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

Posté(e)

Bonjour à tous,

 

Sujet très intéressant car je suis en train de faire un lisp pour traiter une à une les entités d'une sélection.

Pour ma part, j'utilise un repeat avec compteur et un

 (setq obj (ssname ss i))

pour accéder aux entités

 

Par contre, je bloque un peu avec -4, AND, NOT pour vérifier qu'une polyligne 2D ou 3D est fermée ou non mais j'ai trouvé la fonction de logand (dixit Gile) pour trouver le nombre de bit du code 70 donc j'ai pu m'en sortir finalement.

 

Tout cela en pur Lisp, le VLA, je ne le maitrise pas totalement encore.

 

Par contre, on ne peut pas par exemple faire une sélection sur un calque défini de toutes les entités de ce même calque sauf les textes et les mtexts ?

 

Pour l'instant, je n'ai pas trouvé l'astuce sauf en parcourant le jeu de sélection ?

 

Bon courage wookichu

 

John

Posté(e)

Par contre, on ne peut pas par exemple faire une sélection sur un calque défini de toutes les entités de ce même calque sauf les textes et les mtexts ?

 

Tu peur utiliser un "groupe logique" avec des balises "NOT" :

 

(ssget "_X" '((8 . "LeCalque") (-4 . "")))

 

ou, comme avec toutes les valeurs de type chaîne, les caractères génériques :

 

(ssget "_X" '((8 . "LeCalque") (0 . "~MTEXT")))

 

 

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

Posté(e)

Je pensais que les

 balises "NOT" :

ou AND ou OR ne s'appliquer qu'aux polylignes pour déterminer si elles sont fermées ou non

 

comme quoi j'ai encore beaucoup apprendre encore en Lisp

 

Merci Gile pour ces infos, ca marche nickel

 

John

Posté(e)

Je pensais que les balises "NOT" ou AND ou OR ne s'appliquer qu'aux polylignes pour déterminer si elles sont fermées ou non

 

Non, les groupes logiques s'appliquent à tous les types de filtres, on peut les combiner à loisir.

 

Les caractères génériques, bien sûr, ne s'appliquent qu'aux chaines.

 

Et les tests relationnels uniquement aux valeurs numériques.

 

Regarde dans l'aide aux développeurs :

Using the AutoLISP Language > Using AutoLISP to Manipulate AutoCAD Objects > Selection Set Handling > Selection Set Filter Lists >

- Wild-Card Patterns in Filter Lists

- Relational Tests

- Logical Grouping of Filter Tests

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

Posté(e)

Salut,

 

Les balises NOT, AND, et OR ont peut les mélanger

et les appliquer sur tout type d'objet.

 

il ne faut pas oublier que les objet d'un dessin sont un peu comme

une base de données, il faut simplement que la sélection soit cohérente.

 

Tous pour lisp, Lisp pour tous!

Avec Revit, cela ne vas trop vite...

Posté(e)

Par contre, une question, comment faire pour compter le nombre de bloc qui sont presents dans un calque en reperant les noms de blocs ?

 

Je m'explique, j'ai un calque qui contient deux types de blocs, un Bloc nommé A et un bloc nommé B mais qui sont dans le même calque, comment faire pour compter les blocs qui sont nommés A et les blocs qui sont nommés B ?

 

Je ne vois vraiment pas comment faire ....

 

Merci par avance de votre aide

John

Posté(e)

Je ne vois vraiment pas comment faire ....

 

Tu n'as pas dû beaucoup chercher... ;)

 

Soit tu filtres tous les blocs A et B sur le calque puis tu parcours ton jeu de sélection avec 2 compteurs.

(setq cntA 0
     cntB 0
     ss   (ssget "_X" '((0 . "INSERT") (8 . "LeCalque") (2 . "A,B")))
)
(repeat	(setq n (sslength ss))
 (if (= "A" (cdr (assoc 2 (entget (ssname ss (setq n (1- n)))))))
   (setq cntA (1+ cntA))
   (setq cntB (1+ cntB))
 )
)

 

Soit tu fais 2 jeux de sélections :

(setq ss1 (ssget "_X" '((0 . "INSERT") (8 . "LeCalque") (2 . "A"))))
(setq ss2 (ssget "_X" '((0 . "INSERT") (8 . "LeCalque") (2 . "B"))))
(setq cntA (sslength ss1))
(setq cntB (sslength ss2))

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

Posté(e)

Non, je me suis mal exprimé

 

Tu n'as pas dû beaucoup chercher.

 

Je sais le faire de cette façon mais ca marche que si tu connais le nom de ton bloc présent dans ton dessin mais si tu ne le connais pas.

 

J'ai fait un début de code avec

 

(if (/= nil (setq ss2 (ssget "_X" (list (cons 8 lay) (cons 0 "INSERT")))))
(progn
(setq n_blk (cdr (assoc 2 (entget (ssname ss2 0)))))
(setq d 1)
(while (setq ent1 (ssname ss2 d)) 

 

Mais le problème est toujours le même, la difficulté réside dans le fait que je ne connais pas le nom des blocs présents dans le calque et je ne sais pas si il y a 2 types différents,3 ou 4 .......

 

Je pense qu'il faut faire une sélection du type

 

(while (setq blo (tblnext "BLOCK" (not blo)))
(setq nom_bloc (cdr (assoc 2 blo))) 

avec la table des blocs mais ensuite .......

 

John

Posté(e)

Salut,

 

Tu peux utiliser une liste d'association contenant des paires pointées du type :

(NomDuBloc . NombreDeReferences)

 

(if (setq ss (ssget "_X" '((0 . "INSERT") (8 . "Calque7"))))
 (repeat (setq n (sslength ss))
   (setq name (cdr (assoc 2 (entget (ssname ss (setq n (1- n))))))
  lst  (if (setq pair (assoc name lst))
	 (subst (cons name (1+ (cdr pair))) pair lst)
	 (cons (cons name 1) lst)
       )
   )
 )
)

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

Posté(e)

Elle est vraiment pas mal ta méthode

 

Voici ton code modifié pour compter les entités d'un calque utile dans certains cas

 

(if (setq ss1 (ssget "_X" (list (cons 8 lay))))
(repeat (setq n (sslength ss1))
(setq name (cdr (assoc 0 (entget (ssname ss1 (setq n (1- n))))))
lst  (if (setq pair (assoc name lst))
(subst (cons name (1+ (cdr pair))) pair lst)
(cons (cons name 1) lst)
)
)
)
) 

 

Il ne me reste plus que filtrer par calque les polylignes 3D fermées ou non

je vais essayé et je reviens vers toi en cas de prob.

 

Merci encore Gile

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é