Guillaume.A Posté(e) le 16 février 2021 Posté(e) le 16 février 2021 Bonjour à tous ! J'ai créé un lisp au sein de mon bureau nous permettant de récupérer une valeur d'un paramètre d'un bloc dynamique (en l'occurrence, il s'agit de blocs de rupteur thermique, et je récupère la longueur), afin de d'obtenir la longueur totale de rupteur sur le plan. Le bloc de rupteur qu'on utilisé s'appelle "01_BA_Rupteur". Je voulais savoir s'il était possible d'intégrer au lisp une condition, ou une gestion d'erreur (je ne sais pas par quoi passer) permettant de ne pas prendre en compte la sélection SI il ne s'agit pas d'un bloc nommé "01_BA_Rupteur". J'aurai pu passer par l'extraction de données, mais je trouvais ça un peu lourd personnellement, quoi que très efficace quand même Ci-dessous, le code : (defun c:lineaire_rupteur (/ lg lgs obj prop valnum pt rupt) (vl-load-com) (setq lg 0) (while (setq rupt (entsel)) (setq obj (vlax-ename->vla-object (car rupt))) (setq prop (vlax-invoke obj 'getdynamicblockproperties)) (setq valnum (vlax-variant-value (vlax-get-property (nth 0 prop) 'value))) (setq lg (+ lg valnum)) ) (setq lgs (strcat (rtos (/ lg 100.00) 2 1) " ml")) (setq pt (getpoint "\nPoint d'insertion texte : ")) (command "texte" pt "15" "0" lgs) ) Merci d'avance pour votre aide :) , Guillaume
VDH-Bruno Posté(e) le 16 février 2021 Posté(e) le 16 février 2021 Bonjour, Je n'ai pas d'AutoCAD sous la main pour te faire un exemple "sur mesure" mais tu devrais trouver des éléments de réponse dans ce message posté récemment sur le forum Autodeskhttps://forums.autodesk.com/t5/autocad-tous-produits-francais/impossible-de-selectionner-un-bloc-dynamique-via-lisp/td-p/10083959Regarde plus précisément la réponse posté par (gile) avec une condition et l'utilisation de la propriété getpropertyvalue(= (getpropertyvalue (car rupt) "BlockTableRecord/Name") "01_BA_Rupteur") CordialementBruno 1 Apprendre => Prendre => Rendre
Guillaume.A Posté(e) le 16 février 2021 Auteur Posté(e) le 16 février 2021 Merci beaucoup pour ton aide, j'ai pu faire ce que je voulais. J'ai pu intégrer une condition dans mon lisp :) (defun c:lineaire_rupteur (/ lg lgs obj prop valnum pt rupt ent) (vl-load-com) (setq lg 0) (while (setq rupt (entsel)) (setq ent (car rupt)) (if (= (getpropertyvalue ent "BlockTableRecord/Name") "01_BA_Rupteur") (progn (setq obj (vlax-ename->vla-object ent)) (setq prop (vlax-invoke obj 'getdynamicblockproperties)) (setq valnum (vlax-variant-value (vlax-get-property (nth 0 prop) 'value))) (setq lg (+ lg valnum)) ) (princ "\nMauvaise sélection") ) ) (setq lgs (strcat (rtos (/ lg 100.00) 2 1) " ml")) (setq pt (getpoint "\nPoint d'insertion texte : ")) (command "texte" pt "15" "0" lgs) )
VDH-Bruno Posté(e) le 16 février 2021 Posté(e) le 16 février 2021 Merci beaucoup pour ton aide, j'ai pu faire ce que je voulais. J'ai pu intégrer une condition dans mon lisp :)Heureux d'avoir pu aidé, et bienvenu à toi sur CADxp Apprendre => Prendre => Rendre
Guillaume.A Posté(e) le 26 avril 2021 Auteur Posté(e) le 26 avril 2021 Bonjour, Je déterre ce sujet que j'avais lancé car je me suis retrouvé récemment face à un problème que je ne sais pas gérer. Avec la routine que j'ai créé (voir fin de message), je dois sélectionner chaque bloc de rupteur les uns après les autres pour en extraire la donnée qui m'intéresse au fur et à mesure. Seulement, si je sélectionne une côte par exemple, AutoCAD me renvoie l'erreur "erreur: Demande ADS erronée" et ça m'annule la fonction. Je voulais donc savoir s'il est possible de gérer ce genre d'erreur et faire en sorte que ça n'annule pas la fonction (et ainsi que je sois pas obligé de tout recommencer, ce qui peut être lourd quand vous avez 40 blocs de rupteurs sur le plan). La routine : (defun c:lineaire_rupteur (/ lg lgs obj prop valnum pt rupt ent) (setvar "selectionpreview" 2) (vl-load-com) (setq lg 0) (while (setq rupt (entsel)) (setq ent (car rupt)) (if (= (getpropertyvalue ent "BlockTableRecord/Name") "01_BA_Rupteur") (progn (setq obj (vlax-ename->vla-object ent)) (setq prop (vlax-invoke obj 'getdynamicblockproperties)) (setq valnum (vlax-variant-value (vlax-get-property (nth 0 prop) 'value))) (setq lg (+ lg valnum)) ) (princ "\nMauvaise sélection") ) ) (setq lgs (strcat (rtos (/ lg 100.00) 2 1) " ml")) (setq pt (getpoint "\nPoint d'insertion texte : ")) (command "texte" pt "15" "0" lgs) (setvar "selectionpreview" 0) ) Merci d'avance pour votre retour ! Guillaume
(gile) Posté(e) le 26 avril 2021 Posté(e) le 26 avril 2021 Salut, Vérifie que l'objet sélection est bien une référence de bloc avant de cherche à obtenir le nom de la définition du bloc. (if (and (= (cdr (assoc 0 (entget ent))) "INSERT") (= (getpropertyvalue ent "BlockTableRecord/Name") "01_BA_Rupteur") ) ... ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Luna Posté(e) le 26 avril 2021 Posté(e) le 26 avril 2021 Coucou, Vouih en effet toujours filtrer selon le code DXF 0 = "INSERT" lorsqu'on gère des blocs, cela permet d'esquiver un grand nombre de soucis ! Juste en précision du message de @(gile) ci-dessus, il faut se méfier des entités RESEAUX, car malheureusement ils sont eux aussi considérés comme des "INSERT" mais ils ne possèdent pas la propriété "BlockTableRecord/Name" (ils sont anonymisés). Donc si ton .dwg possède (ou risque de posséder) des entités RESEAU, je te suggère d'ajouter une condition sur une propriété commune entre les blocs et les réseaux : ;; En passant par la propriété "ClassName" équivalente à "AcDbAssociativeRectangularArray", etc pour des réseaux et "" pour des blocs dynamiques/standards (if (and (= (cdr (assoc 0 (entget ent))) "INSERT") (= (getpropertyvalue ent "ClassName") "") (= (getpropertyvalue ent "BlockTableRecord/Name") "01_BA_Rupteur") ) ... ) ;; En passant par une fonction de gestion d'erreur (if (and (= (cdr (assoc 0 (entget ent))) "INSERT") (not (vl-catch-all-error-p (setq name (vl-catch-all-apply 'getpropertyvalue (list ent "BlockTableRecord/Name"))))) (= name "01_BA_Rupteur") ) ... ) ;; En passant par les fonctions Visual LISP (if (and (= (cdr (assoc 0 (entget ent))) "INSERT") (vlax-property-available-p (vlax-ename->vla-object ent) 'EffectiveName) (= (vlax-get-EffectiveName (vlax-ename->vla-object ent)) "01_BA_Rupteur") ) ... ) Autrement, pas besoin de filtrer ces entités casse-tête ! :3 Sinon, si tu as besoin de faire cette démarche sur plusieurs blocs portant le même nom, ne serait-il pas plus simple de faire une boucle (while) sur un jeu de sélection au lieu de devoir sélectionner les blocs un par un manuellement ? Bisous, Luna
Guillaume.A Posté(e) le 26 avril 2021 Auteur Posté(e) le 26 avril 2021 Super, merci à vous deux ! C'est vrai que j'avais pas pensé à filtrer avant de choper le nom de définition du bloc ... un peu bête ^^ 22 minutes ago, Luna said: Sinon, si tu as besoin de faire cette démarche sur plusieurs blocs portant le même nom, ne serait-il pas plus simple de faire une boucle (while) sur un jeu de sélection au lieu de devoir sélectionner les blocs un par un manuellement ? J'aurais bien aimé, mais j'ai jamais compris comment fonctionnait les jeux de sélection sous lisp (ssget etc...) du coup, j'ai lâché l'affaire. De plus, au bureau on s'est pas embêté à créer un bloc par type de rupteur, et il peut arriver que sur un niveau d'un bâtiment, on ait à la fois des rupteurs en façade et des rupteurs en acrotère. Ces rupteurs étant différent, on a un linéaire de rupteur par type de rupteur (et si à ça, on rajoute le fait qu'un chantier peut être constitué de plusieurs bâtiments, on a en plus des linéaires par bâtiment ET par type). J'écris mais en même temps je me dis que je pourrais passer par des calques, et ainsi filtrer par calque et par nom de bloc mon jeu de sélection, mais faut d'abord que j'essaye de nouveau de saisir comment fonctionne les jeux de sélection ^^ Bref, je vais creuser ça de mon côté, mais en attendant j'ai pu résoudre mon soucis d'erreur ADS 🙂 Merci !
didier Posté(e) le 26 avril 2021 Posté(e) le 26 avril 2021 Bonjour @Guillaume.A Je me permets de te diriger vers la page SSGET de mon site, il me semble avoir fait un bon tout de la fonction et de ses options. À ta disposition pour clarification le cas échéant. Amicalement Éternel débutant... Mon site perso : Programmer dans AutoCAD
Luna Posté(e) le 26 avril 2021 Posté(e) le 26 avril 2021 En effet la gestion par calques et la version la plus simple et efficace pour la séparation des objets ! Après rien n'exclu le fait de créer des blocs identiques mais avec une dénomination différente (pour séparer vos rupteurs en façade et en acrotères) ou bien de passer par des visibilités au sein du bloc (mais moins pratique pour un SELECTSIMILAR par exemple) :3 Ainsi il ne restera plus qu'à faire une séparation des bâtiments via les calques (chat divise par deux le nombre de calques). Pour ce qui est des jeux de sélection, tu as déjà de nombreuses formations sur le net ("Introduction à AutoLISP" de (gile), "Da-Code" de didier, AfraLISP, ...) mais cela n'a rien de bien sorcier :3 Il faut voir cela comme une liste nommée que l'on parcours à l'aide de fonctions d'itération comme (while) ou (repeat) : ;; Version avec (while) (if (setq i 0 jsel (ssget)) ; Initialisation du compteur i à 0 (premier entité dans le jeu de sélection (while (< i (sslength jsel)) ; Démarrage de la boucle (setq name (ssname jsel i)) ; Récupération du nom de l'entité à l'indice i du jeu de sélection ... (setq i (1+ i)) ; Incrémentation du compteur i de 1 par rapport à sa valeur précédente ) ; Fin de la boucle ) ;; -> On parcours le jeu de sélection en partant de la première entité (= 0), jusqu'à la dernière (= (n-1)) avec n le nombre d'objets sélectionnés ;; Version avec (repeat) (if (setq jsel (ssget)) (repeat (setq i (sslength jsel)) ; Démarrage de la boucle et initialisation du compteur i correspondant au nombre d'entités (setq name (ssname jsel (setq i (1- i)))) ; Récupération du nom d'entité à l'indice i et incrémentation de i de -1 ... ) ; Fin de la boucle ) ;; -> On parcours le jeu de sélection en partant de la dernière entité (= (n-1)), jusqu'à la première (= 0) avec n le nombre d'objets sélectionnés ;; PS : Si l'on utilise la fonction (ssdel) permettant de supprimer un objet du jeu de sélection, la version (while) devra incrémenter l'indice i uniquement si l'objet n'est pas supprimé du jeu de sélection (décalage de la numérotation des objets au sein du jsel de 1 vers la gauche en cas de suppression). Ce souci n'est pas préssent dans la version (repeat) car on démarre de la dernière entité donc même si la numérotation change, seules les objets déjà traités sont impactés. A part chat qui reste quasiment tout le temps identique, il y a juste à programmer le reste entité par entité comme tu l'as fait dans ton programme :3 Bisous, Luna
Guillaume.A Posté(e) le 26 avril 2021 Auteur Posté(e) le 26 avril 2021 Et re ! J'ai passé la dernière heure à décortiquer les infos que j'ai pu trouver sur les jeux de sélection ("Introduction à autoLISP de (gile) et da-code de Didier) et j'ai réussi à comprendre comment tout ça fonctionne 🙂 Donc j'ai complètement transformé ma routine pour me servir de ce fameux jeu de sélection et je suis arrivé à ça (et ça marche !) (defun c:lineaire_rupteur (/ kw ent obj prop valnum i pt lg lgs jsel) (setq lg 0) (initget 1 "L9 L10") (setq kw (getkword "\nType de rupteur ? [L9/L10]: ")) (if ( = kw "L9") (setq jsel (ssget (list '(-4 . "<AND") '(0 . "INSERT") '(8 . "01 BA Rupteurs L9") '(-4 . "AND>")))) (setq jsel (ssget (list '(-4 . "<AND") '(0 . "INSERT") '(8 . "01 BA Rupteurs L10") '(-4 . "AND>")))) ) (setq i 0) (while (< i (sslength jsel)) (progn (setq ent (ssname jsel i)) (setq obj (vlax-ename->vla-object ent)) (setq prop (vlax-invoke obj 'getdynamicblockproperties)) (setq valnum (vlax-variant-value (vlax-get-property (nth 0 prop) 'value))) (setq lg (+ lg valnum)) (setq i (1+ i)) ) ) (setq lgs (strcat (rtos (/ lg 100.00) 2 1) " ml")) (setq pt (getpoint "\nPoint d'insertion texte : ")) (command "texte" pt "15" "0" lgs) ) Pour ce qui est des bâtiments, suffit juste de faire une fenêtre de sélection uniquement autour du bâtiment qu'on étudie et l'affaire est plié ^^ Merci pour votre aide et vos idées, ça va aller beaucoup plus vite maintenant 🙂
Luna Posté(e) le 26 avril 2021 Posté(e) le 26 avril 2021 Pas de soucis ! Je remarque que tu as enlevé la vérification sur l'EffectiveName du bloc, donc faut juste s'assurer que dans tes calques "01 BA Rupteurs*" tu n'as pas d'autres blocs :3 Autrement chat fait plaisir de voir des personnes venir pour quelques explications pour trouver la solution par soi-même ! Il n'y a que comme chat qu'on progresse de toutes façons Bisous, Luna
Guillaume.A Posté(e) le 27 avril 2021 Auteur Posté(e) le 27 avril 2021 Ah bah oui, j'ai oublié de remettre la vérification ! C'est pourtant pour ça que j'étais venu au début 😂 Le final donne donc ça : (defun c:lineaire_rupteur (/ kw ent obj prop valnum i pt lg lgs jsel) (setq lg 0) (initget 1 "L9 L10") (setq kw (getkword "\nType de rupteur ? [L9/L10]: ")) (if ( = kw "L9") (setq jsel (ssget (list '(-4 . "<AND") '(0 . "INSERT") '(8 . "01 BA Rupteurs L9") '(-4 . "AND>")))) (setq jsel (ssget (list '(-4 . "<AND") '(0 . "INSERT") '(8 . "01 BA Rupteurs L10") '(-4 . "AND>")))) ) (setq i 0) (while (< i (sslength jsel)) (setq ent (ssname jsel i)) (if (and (= (cdr (assoc 0 (entget ent))) "INSERT") (= (getpropertyvalue ent "ClassName") "") (= (getpropertyvalue ent "BlockTableRecord/Name") "01_BA_Rupteur") ) (progn (setq obj (vlax-ename->vla-object ent)) (setq prop (vlax-invoke obj 'getdynamicblockproperties)) (setq valnum (vlax-variant-value (vlax-get-property (nth 0 prop) 'value))) (setq lg (+ lg valnum)) (setq i (1+ i)) ) (ssdel ent jsel) ) ) (setq lgs (strcat (rtos (/ lg 100.00) 2 1) " ml")) (setq pt (getpoint "\nPoint d'insertion texte : ")) (command "texte" pt "15" "0" lgs) ) Encore merci à vous, et à la prochaine 🙂
Luna Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 Juste pour ton information, les codes DXF -4 ne sont pas nécessaire dans ta liste des filtres de la fonction (ssget) :3 (ssget (list '(-4 . "<AND") '(0 . "INSERT") '(8 . "01 BA Rupteurs L10") '(-4 . "AND>"))) ;; Equivaut à (ssget '((-4 . "<AND") (0 . "INSERT") (8 . "01 BA Rupteurs L10") (-4 . "AND>"))) ;; Equivaut à (ssget (list '(0 . "INSERT") '(8 . "01 BA Rupteurs L10"))) ;; Equivaut à (ssget '((0 . "INSERT") (8 . "01 BA Rupteurs L10"))) ;; On peut ici s'épargner des (-4 . "<AND>") car la liste fonctionne naturellement selon une logique AND ;; et comme ta liste de filtres n'est pas variable, tu peux également t'épargner la fonction (list) ;; suivie de plusieurs ' (= (quote)) pour chaque filtre, une seule ' (= (quote)) suffit ! Bisous, Luna
Guillaume.A Posté(e) le 27 avril 2021 Auteur Posté(e) le 27 avril 2021 Ah ok, j'avais pas compris ça ^^ ça allège un peu l'écriture, c'pas plus mal 🙂 Mais alors, quand est ce que la fonction (list) devient nécessaire ? et les opérateurs logique ?
Luna Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 La fonction (quote), également notée ' permet de lire une expression sans l'évaluer donc c'est pour cela que les listes écrites en dur, on utilise cette fonction (quote) command: (setq lst (list 1 2 3)) (1 2 3) command: (setq lst '(1 2 3)) (1 2 3) command: (setq lst (1 2 3)) ; erreur: fonction incorrecte: 1 ;; Si on ne met pas de quote ou qu'on n'utilise pas (list), AutoCAD va vouloir évaluer la ;; liste comme s'il s'agissait d'une fonction, induisant ici une erreur command: (setq a 1) (1 2 3) command: (setq lst (list a 2 3)) (1 2 3) command: (setq lst '(a 2 3)) (A 2 3) command: (setq lst (a 2 3)) ; erreur: fonction incorrecte: A ;; Si l'on a besoin d'injecter une variable dans la liste, la fonction (quote) ne fonction plus ;; car elle ne va pas évaluer la variable A en utilisant sa valeur. ;; La fonction (quote) est également souvent utilisée pour les fonctions d'ordre supérieur comme ;; (mapcar), (vl-sort), (vl-remove-if), ... car le but étant de spécifier en argument une fonction ;; sans qu'elle soit évaluée comme argument (on a besoin de l'expression telle quelle, et non sa ;; valeur). Après c'est uniquement un "raccourci" d'écriture donc si tu ne comprends pas parfaitement son utilisation, utilise ce que tu connais et maîtrise le avant d'avancer un peu plus :3 Au début ce n'est pas toujours évident de percevoir toutes les subtilités et comme il n'existe jamais qu'une seule et unique vérité, le plus simple est de progresser pas à pas en consolidant les bases :3 Les cours de (gile) et didier sont excellents pour débuter et consolider les bases au maximum et pour ce qui est de la maîtrise, il n'y a qu'en forgeant qu'on devient forgeron :) Bon courage ! Bisous, Luna
Luna Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 Les opérateurs logiques AND, OR, XOR sont peu utilises et souvent ils sont utilisés ensemble par exemple : (ssget '( (-4 . "<OR") (-4 . "<AND") (0 . "INSERT") (8 . "Calque#") (-4 . "AND>") (-4 . "<AND") (0 . "LWPOLYLINE") (90 . 4) (70 . 1) (-4 . "AND>") (-4 . "<OR") ) ) ;; Sélectionne soit les blocs situés sur les calques nommés "Calque0", "Calque1", "Calque2", ;; "Calque3", "Calque4", "Calque5", "Calque6", "Calque7", "Calque8" ou "Calque9" OU BIEN les ;; polylignes fermées possédant 4 sommets. Bisous, Luna
Olivier Eckmann Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 Bonjour @Luna, Juste une petite remarque sur le code 70 des polylignes, en plus du bitcode 1 pour le flag fermée, il y a aussi le bitcode 128 pour le flag de génération du type de ligne. Donc une polyligne fermée avec la génération du type de ligne activée aura un code 70 à 129 (128 + 1) et pas seulement 1. Olivier
Luna Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 En effet, ne l'utilisant jamais (notamment parce que je ne m'y suis jamais intéressée) je l'ai oublié malheureusement :3 Bien qu'il s'agisse d'un simple exemple il faudrait dans ce cas prendre les deux valeurs (1 ou 129) (ssget '( (-4 . "<OR") (-4 . "<AND") (0 . "INSERT") (8 . "Calque#") (-4 . "AND>") (-4 . "<AND") (0 . "LWPOLYLINE") (90 . 4) (-4 . "<OR") (70 . 1) (70 . 129) (-4 . "OR>") (-4 . "AND>") (-4 . "OR>") ) ) ;; Sélectionne soit les blocs situés sur les calques nommés "Calque0", "Calque1", "Calque2", ;; "Calque3", "Calque4", "Calque5", "Calque6", "Calque7", "Calque8" ou "Calque9" OU BIEN les ;; polylignes fermées possédant 4 sommets. PS : j'avais également mal orthographié la fermeture de mon "OR>" :S Bisous, Luna
(gile) Posté(e) le 27 avril 2021 Posté(e) le 27 avril 2021 @Luna, pour rebondir sur la pertinente remarque de @Olivier Eckmann, revois ce sujet et l'opérateur bitwise AND dans les filtres de sélection, je te laisse chercher... Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
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