wookichu Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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""
bseb67 Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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...
Titifonky Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
wookichu Posté(e) le 3 février 2011 Auteur Posté(e) le 3 février 2011 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!
wookichu Posté(e) le 3 février 2011 Auteur Posté(e) le 3 février 2011 Eh bien un grand merci!! :D je vais voir comment j'arrive a me dépatouiller avec la méthode: foreach et ssnamex de (gile)
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
wookichu Posté(e) le 3 février 2011 Auteur Posté(e) le 3 février 2011 @(gile) la réponse n°4 était destinée à bseb67 :) merci pour ton aide!
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
wookichu Posté(e) le 3 février 2011 Auteur Posté(e) le 3 février 2011 @(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 ?
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 @(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
chris_mtp Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
chris_mtp Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
(gile) Posté(e) le 3 février 2011 Posté(e) le 3 février 2011 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
bseb67 Posté(e) le 4 février 2011 Posté(e) le 4 février 2011 Salut, Les balises NOT, AND, et OR ont peut les mélangeret les appliquer sur tout type d'objet. il ne faut pas oublier que les objet d'un dessin sont un peu commeune 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...
chris_mtp Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 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 aideJohn
(gile) Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 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
chris_mtp Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 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
(gile) Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 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
chris_mtp Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 Merci GileCa marche nickel, je vais décortiquer ta méthode.John
chris_mtp Posté(e) le 5 février 2011 Posté(e) le 5 février 2011 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
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant