Aller au contenu

entmod sans aucun effet


Touan

Messages recommandés

Bonjour tout le monde,

 

Ceci est mon premier message sur le forum que je consulte énormément depuis le début de mon apprentissage d'AutoLISP et j'y trouve la plupart du temps une réponse à mes problèmes mais là j'avoue que je butte.

 

Pour la petite histoire, je dois développer une série de routines permettant d'automatiser au maximum la transformation de nos plans vers une charte client.

 

Parmi ces routines, j'en ai une qui doit exploser des blocs pour en récupérer les polylignes, les joindre et les mettre dans les bons calques, types de lignes et couleur.

 

J'ai réussi dans un premier jet à le faire en passant par des command _explode/_pedit /_chprop, et j'essaye d'optimiser mon code afin d'éviter de passer par des command.

J'en arrive donc à ce code qui s’exécute mais qui ne prends pas en compte mes modifications de couleur et de type de ligne. Mes append/subst sont bien appliqués à mes elist mais le entmod "n'a pas l'air de fonctionner".

 

(defun c:SOGCLIENT-BLK-EXP2()						;;Fonction de décomposition des blocs puis jointure + modification des calques, types de lignes et couleur
(setq lst '(										;; Liste des blocs à exploser avec nouveau type de ligne, couleur et calque
(((0 . "INSERT") (2 . "GU15") (8 . "AEP_SYM")) ("z_lz" 150 "OD--D_LI"))
(((0 . "INSERT") (2 . "GU15") (8 . "RESDIV_SYM")) ("z_lz" 7 "OD--D_LI"))
)
)	
(foreach n lst 										;; Pour chaque type de bloc de lst ...
(if
(setq ss (ssget "X" (car n))) 						;; ... on crée une ss de ces blocs...
(repeat (setq i (sslength ss)) 						;; ... puis on répète autant de fois qu'il y a de ce bloc ...
(setq ssent (ssadd)) 								;; création d'une nouvelle ss (vide)
(ssadd (setq ent (ssname ss (setq i (1- i)))) ssent) ;; on ajoute a cette ss le dernier bloc de la liste des mêmes blocs
(setq *LastEnt* (entlast)) 							;; *LastEnt* = dernière entité créée dans le dessin
(command "_explode" ss "") 							;; Retourne une erreur alors que tout fonctionne...
(setq ss2 (ssadd)) 									;; création d'une nouvelle ss (vide)
(if (setq en (entnext *LastEnt*))					;; en = entité qui suit *LastEnt*
(while en
(setq ss2 (ssadd en ss2) en (entnext en)) 			;; on rempli ss2 de toutes les entités qui suivent *LastEnt* (issues du burst du bloc)
)
)
(setq *LastEnt* (entlast)) 							;; *LastEnt* = dernière entité créée dans le dessin
(command "PEDITACCEPT" "1") 						;; on enlève le message davertissement "pas des polylignes..."
(command "_pedit" "m" ss2 "" "j" "" "")				;; on joint les entités de la ss2 (les éléments issus du burst)
(setq ss2 (ssadd)) 									;; création d'une nouvelle ss (vide)
(if (setq en (entnext *LastEnt*)) 
(while en
(setq ss2 (ssadd en ss2) en (entnext en)) 			;;on ajoute à ss2 les nouveaux éléments créés (issus des jointures)
)
)
(repeat (setq i2 (sslength ss2)) 					;; ... puis on répète autant de fois qu'il y a de nouveaux éléments créés
(setq e1 (ssname ss2 (setq i2 (1- i2)))) 			;; e1 = dernier élément de la ss
(setq e1p (entget e1))								;; e1p = propriété de e1
(setq layer (caddr (cadr n)))						;; layer = nouveau calque à attribuer
(setq ltype (car (cadr n)))							;; ltype = nouveau type de ligne à attribuer
(setq color (cadr (cadr n)))						;; color = nouvelle couleur à attribuer
(setq e1p (subst (cons 8 layer) (assoc 8 e1p) e1p))
(if (= (assoc 62 e1p) nil)
(setq e1p (append (list (cons 62 color)) e1p))		;;insertion couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était en couleur "ducalque")
(setq e1p (subst (cons 62 color) (assoc 62 e1p) e1p))	;;modification de la couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était déja en couleur forcée)
)
(if (= (assoc 6 e1p) nil)
(setq e1p (append (list (cons 6 ltype)) e1p))		;;insertion du ltype forcé dans les propriétés de l'entité du bloc CLIENT (cas où la pl était en ltype "ducalque")
(setq e1p (subst (cons 6 ltype) (assoc 6 e1p) e1p))	;;modification du ltype forcé dans les propriétés de l'entité du bloc CLIENT (cas où la pl était déja en ltype forcée)
)
(entmod e1p)
)
)
)
)
(princ)
)

 

J'en profite aussi pour vous demander si vous auriez des alternatives à l'utilisation des _explode et _pedit afin d'exploser les blocs et joindre les polylignes issues de ces décompositions?

 

Je vous remercie d'avance et j'espère que ma demande reste clair.

 

 

 

Touan

Lien vers le commentaire
Partager sur d’autres sites

Salut !

 

Je n'ai pas tester ton code, mais dans un premier temps, es-tu sûr que le type de ligne que tu souhaites forcer est bien charger dans le dessin sur lequel tu travailles ? Cela pourrait être une source d'erreur car ton programme essaye de forcer un type de ligne qu'il ne connait pas. Normalement il ne devrait pas y avoir de problème si le calque n'existe pas, il se créé automatiquement.

 

Tu peux également essayer de voir du côté des fonctions (setpropertyvalue), (getpropertyvalue) et (dumpallproperties) qui permettent d'accéder aux propriétés d'un objet (donc on a accès aux propriétés visible dans la palette de propriétés d'AutoCAD concrètement).

 

Auquel cas, si jamais la couleur et le type de ligne ne fonctionne pas vraiment via (entmod), je rappelle que je n'ai pas tester ton programme (désolé), tu peux tenter de remplacer

(if (= (assoc 62 e1p) nil)
(setq e1p (append (list (cons 62 color)) e1p))          ;;insertion couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était en couleur "ducalque")
(setq e1p (subst (cons 62 color) (assoc 62 e1p) e1p))   ;;modification de la couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était déja en couleur forcée)
)

par

(setpropertyvalue e1 "COLOR" color)

 

En revanche pour les type de lignes c'est plus complexe, car les fonctions (-propertyvalue) requièrent l'ID du type de ligne, et non le nom...

 

PS : il s'agit juste d'une remarque pour éviter les erreurs d'interactions entre tes différents LISP, mais je te conseille d'utiliser des variables locales, au lieu de variables globales.

La fonction (defun) fonctionne de la manière suivante

(defun sym ([arguments] [/ variables ...]) expr ...)

 

Avec :

- "sym" le nom de ta fonction (ou commande si précédée d'un "c:")

- [arguments] pour les arguments, donc ici inutile car il s'agit d'une commande (à savoir que lorsque c'est écrit entre crochets, cela signifie que c'est optionnel)

- [/ variables] pour déclarer des variables locales (elles sont placées dans la même parenthèse que les arguments mais séparées des arguments d'un unique slash)

- expr correspond au code de ton programme

 

Donc si tu veux, une fonction possédant 1 argument et 1 variable locale s'écrit

(defun func (arg1 / var1) ...)

0 arguments et 2 variables locales

(defun func (/ var1 var2) ...)

2 arguments et 0 variables locales

(defun func (arg1 arg2) ...)

 

Bref l'idée de déclarer des variables locales c'est qu'à chaque exécution du programme, une fois terminé, toutes les variables locales déclarées sont vidées de la mémoire (= nil) ce qui évite par exemple que dans un programme qui construit une liste via la fonction (cons) dans une boucle du genre

 

(defun func (n)
 (repeat n
   (setq lst (cons (setq n (1- n)) lst))
 )
)

Au premier lancement lst = nil, puis pour n=4, tu obtiens lst = (0 1 2 3)

Au second lancement lst = (0 1 2 3) puis pour n = 7, tu obtiens lst = (0 1 2 3 4 5 6 0 1 2 3)

etc

 

Mais en regardant, tu insères dans ta boucle un (setq ss (ssadd)) pour tes jeux de sélection donc tu les remets à 0 manuellement donc tu ne dois pas avoir de soucis pour ce programme à ce niveau là, mais c'est un confort supplémentaire et ça limite les erreurs :)

 

Bref je ne t'aide pas des masses...

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

C'est super que tu te mettes au LISP.

 

Je me permettrais juste quelques recommandations qui devraient te permettre de plus facilement résoudre tout seul tes problèmes.

 

Premièrement, déclare les variables localement.

Deuxièmement, utilise des "sous-routines" pour décomposer une tâche complexe en plusieurs tâches plus simple et testables séparément.

 

Par exemple tu peux faire une fonction qui décompose un bloc et renvoie un jeu de sélection contenant les objets issus de la décomposition.

(defun explode (bloc / ent ss)
 (setq	ent (entlast)
ss  (ssadd)
 )
 (command "_.explode" bloc)
 (while (setq ent (entnext ent))
   (ssadd ent ss)
 )
 ss
)

Tu peux tester cette routine en faisant : (setq ss (explode (car (entsel)))) et ensuite tester ss.

 

Tu peux faire une autre routine qui prend un jeu de sélection en argument, exécute la commande "_pedit" pour joindre les entités du jeu de sélection et renvoie la liste des entités nouvellement créées.

(defun join (ss / ent lst)
 (setq ent (entlast))
 (command "_pedit" "m" ss "" "j" "" "")
 (while (setq ent (entnext ent))
   (setq lst (cons ent lst))
 )
)

Tu peux alors tester tes deux fonctions en faisant : (setq lst (join (explode (car (entsel))))) et examiner la liste renvoyée.

 

Pour finir tu peux faire une fonction qui modifie le calque, la couleur et le type de ligne d'une entité.

 

Et, quand tu est sûr que chaque routine fonctionne comme tu le souhaites, tu peux les assembler dans ta commande.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Ah et euh...

 

Il s'agit d'un avis purement personnel, mais pour les commandes j'ai pris l'habitude de renvoyer dans l'historique de commande les résultats car ça permet au développeur de vérifier les infos (dans un premier temps si la commande parvient jusqu'au bout, et ensuite de checker les infos directement dans AutoCAD et non l'espion) mais aussi à l'utilisateur lambda qui, en lançant une commande, aimerait bien être sûr que ça a marché :)

 

C'est un moyen d'informer par exemple le nombre d'objets impactés, le calque, la couleur forcée et ce genre de choses (tout dépend des informations qui te semblent utile pour l'utilisateur pour faire un check lui aussi de son côté).

Parce que les commandes fantômes, même si on voit un résultat visuel parfois, on n'a pas vu qu'on a modifié plus que prévu ou moins... ^^"

 

Aller bisous,

Luna

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

Pas tester ton code non plus, pour cela un petit extrait de dessin aurait été nécessaire.

 

Mais tu dis que tes elist sont bien modifiées mais que entmod n'a pas l'air de fonctionner.

Il faut savoir que entmod fonctionne (sauf pour les VIEWPORT / fenêtres), mais que pour des entités complexes tel que des blocs ou des polylignes lourdes par exemple l'utilisation de entupd (avec le nom de l'entité d'entête) est nécessaire pour mettre à jour la base de données d'Autocad.

Je crois même qu'un regen par la suite soit aussi indispensable pour voir les modifications, ce qui n'est pas le cas pour des entités simples; on voit tout de suite la modification après entmod.

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Lien vers le commentaire
Partager sur d’autres sites

Salut,

Je crois même qu'un regen par la suite soit aussi indispensable pour voir les modifications, ce qui n'est pas le cas pour des entités simples; on voit tout de suite la modification après entmod.

c'est tout a fait vrai pour les multilignes, et pire pour ces bestioles,

pour avoir une mise à jour systématique à l'écran,

j'en était venu a lancer la commande "etirer" sélection de la zone englobante, et 2 pt identiques: la miracle, la multiligne change d'échelle.

a+

Gégé

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Lien vers le commentaire
Partager sur d’autres sites

Bonjour à tous et merci pour vos retours riches en informations.

 

Désolé pour la réponse tardive mais j'ai été rattrapé par le boulot et la livraison de plans est passée prioritaire donc l'optimisation attendra hélas ...

Je continue donc pour le moment avec l'ancienne version qui fonctionne avec _chprop.

 

J'ai cependant bien pris note de toutes vos remarques et tâcherait d'appliquer vos conseils pour la suite.

 

Je ne connaissait pas (setpropertyvalue) qui a l'air très intuitive pour la modification rapide de propriété d'un objet.

 

Pour les variables locales, je ne les déclarait pas car j'avais pour habitude de tester mes routines directement dans la ligne de commande Autocad et de tester mes variables pour étudier le fonctionnement. Une fois mon code fonctionnel, il faudrait que je m'efforce à déclarer mes variables en locale :P Et j'avoue ne pas encore avoir pris le temps d'essayer le VLIDE... Promis je m'y mets dès que possible.

 

Concernant les messages sur le bon déroulement de mes routines, j'ai pris l'habitude de le faire sur les plus petites mais celle-ci fait partie d'un ensemble d'une vingtaine de routines (déplacement de blocs, substitution de blocs, changement de calques, forçage des couleurs et type de ligne, ...) qui s’exécutent en chaîne à partir d'une commande. Il y a bien un message de confirmation à la fin. Cependant, c'est vrai qu'il serait pas mal d'ajouter un récap de toutes les opérations effectuées à la fin.

 

Pour les "sous-routines", c'est une des optimisations que j'aimerais apporter à tout mon code car il est vrai que beaucoup de choses se répètent (ayant développé chaque routines unes à unes sur le tas).

 

Pour en revenir à mon soucis, j'ai remarqué par hasard en écrivant une autre routine, que mes entmod (même avec entupd) ne fonctionnaient pas sur les LWPOLYLINE mais que les POLYLINE (j'ai bien élargi mes filtres de SSGET). J'effectue donc un _convertpoly avant et cela semble me régler le soucis. Cela vous semble normal? Ça m'intrigue vraiment...

 

Merci encore à vous.

 

Très bonne soirée et bon confinement!

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é