Aller au contenu

Parcourir un jeu de sélection pour modifier un attribut DXF


Messages recommandés

Posté(e)

Bonjour à tous

 

Je vous contact car je sèche sur un bout de script.

Le but est de sélectionner tous les objets d'un calque choisi par l'utilisateur et ensuite de supprimer les couleurs personnalisées de chaque objet pour qu'il récupère la couleur du calque.

La sélection est bonne mais je n'arrive pas à modifier les objets.
Je pense que je m'embrouille dans la récupération des éléments des entités et attribut DXF 😢 et dans le parcours du jeu de sélection.

Quelqu'un pourrait-il me dire où ? J'ai un comportement aléatoire de mon côté.

	(setq nomcalc (getstring T "\nNom du calque: "))

	(setq ss (ssget "_X" (list (cons 8 nomcalc))))
	(sssetfirst nil ss) ; Pour afficher le jeu de sélection
	
	; Si ss non nil
	(if ss									
		(progn
			(repeat (sslength ss)										; Répéter autant de fois que d'entités dans ss
				(setq ent (ssname ss 0))								; ent = nom de l'entité
				(setq en (entget ent))									; en = liste DXF de l'entité
				(setq nameent (entnext ent))							; nameent = Nom de l'entité
				(setq suben (entget nameent))							; suben = liste dxf de l'attribut
				(entmod (subst (cons 62 256) (assoc 62 suben) suben))
				(setq nameent (entnext nameent))
				(entupd ent)
				(ssdel ent ss)
			)
		)
	)

Je joins un ficher de test dans lequel les objets du calque "1" sont forcés en jaune.
Si on applique le script au calque "1", ils doivent devenir rouge.

Merci d'avance

OrionLG

Dessin1.dwg

Posté(e)

Coucou,

Le problème vient du (entnext), qui n'a pas lieu d'être... Il faudrait quelque chose comme ceci :

(setq nomcalc (getstring T "\nNom du calque : "))

(setq ss (ssget "_X" (list (cons 8 nomcalc))))
(sssetfirst nil ss) ; Pour afficher le jeu de sélection

; Si ss non nil
(if ss
  (repeat (sslength ss)                                                      ; Répéter autant de fois que d'entité dans ss
    (setq ent (ssname ss 0))                                                 ; ent = nom de la première entité de ss
    (setq en (entget ent))                                                   ; en = liste DXF de l'entité
    (setq en (vl-remove-if '(lambda (x) (member (car x) '(420 430))) en))    ; Suppression des codes DXF facultatifs 420 et 430 pour les couleurs non ACI
    (if (assoc 62 en)                                                        ; Vérification si couleur forcée (code DXF 62)
      (entmod (subst (cons 62 256) (assoc 62 en) en))                        ; Modification de la liste DXF de l'entité
    )
    (ssdel ent ss)                                                           ; Suppression de la première entité de ss
  )
)

Une autre remarque : Pour parcourir un jeu de sélection il est préférable d'utiliser une variable que l'on incrémente pour à la place de l'index 0 de (ssname). Cela évite de devoir supprimer l'entité du jeu de sélection et donc de se réserver le droit d'utiliser (ssdel) pour une autre raison. Donc on utilise par exemple l'écriture ci-dessous :

(repeat (setq i (sslength ss))
  (setq ent (ssname ss (setq i (1- i))))
  ...
)

Ensuite, pourquoi as-tu utilisé (entnext) pour modifier la couleur de tes objets alors qu'ils sont sélectionnés par ton (ssget) ?

Bisous,
Luna

Posté(e)

Merci beaucoup Luna !!!! 🥳

Je suspectais en effet les entnext de poser problèmes.

Je me suis aidé de codes existant (d'où l'erreur de choix des commandes) et du cours de Gilles.
Et grâce avec ta version épurée je comprend mieux. J'ai été trop loin dans l'entité j'ai l'impression

Bien que je maitrise d'autres langages de programmation, le LISP me perturbe facilement 🤪.

Je vais tout de suite essayer de modifier la boucle avec l'incrément de variable.

Merci encore de ton aide.

OrionLG

 

Posté(e)

Bonjour

@Luna Tu utilises le code suivant pour  supprimer les codes DXF facultatifs.

(setq en (vl-remove-if '(lambda (x) (member (car x) '(420 430))) en))

Je peine à trouver l'inverse.
Je souhaiterai, pour un autre bout de script, ajouter le code 420 avec la couleur RGB 255,0,0.

Ça donnerai la paire (420. 16711680).

Si j'ai bien compris, je ne peux pas utiliser (entmod (subst (cons 62 256) (assoc 62 en) en)) car si la référence 420 n'existe pas ça plante.

J'ai essayé plusieurs syntaxes en vain.
Je vois comment créer la paire dans un nouvelle objet avec entmake, mais pas comment ajouter une paire sur un objet existant.

Auriez-vous une idée s'il vous plait ?

 

Posté(e)
Le 23/12/2014 à 20:04, VDH-Bruno a dit :

- Application à la fonction entmod

 

De ce qui précède, on comprend mieux pourquoi il est possible de modifier une définition d'entité seulement par ajout de propriétés à la définition existante. Sans passer par la fonction de substitution subst et sans devoir tester la présence ou non de codes DXF facultatif.

 

Ex: Modification du calque, de la couleur et des coordonnées d'un sommet de la ligne précédemment dessiné par ajout au moyen de la fonction append des nouvelles définitions

 

(entmod
 (append (entget (entlast))
  (list '(62 . 7) '(8 . "MonNouveauCalque") (cons 10 (getpoint)))
 )
)
 

 

 

Attention toutefois à la valeur de retour qui correspond à la liste transmis en argument et pas forcément à la nouvelle définition de l'entité..

Citation
_$ (entget (entlast))

 

((-1 . <Nom d 'entité: 7d549110>) (0 . "LINE") (330 . <Nom d 'entité: 7d464cf8>) (5 . "11CF7A") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "MonNouveauCalque") (62 . 7) (100 . "AcDbLine") (10 36352.5 18939.2 0.0) (11 31111.1 30231.9 0.0) (210 0.0 0.0 1.0))

Apprendre => Prendre => Rendre

Posté(e) (modifié)

Coucou,

La modification de la couleur forcée d'un objet via la liste DXF est toujours un peu....délicat ^^" Car le code 420 doit être calculé et le code 62 reflète la valeur ACI la plus proche du code 420. Donc pour les TrueColor, je te conseille fortement de regarder le travail de LeeMac sur la question. Je pense que passer par le Visual LISP est un peu plus simple que la liste DXF. Ci-dessous un exemple en Visual LISP pour modifier la couleur d'un objet

(setq color '(255 0 0))                 ; liste de la forme ( R G B ) avec R, G et B des entiers compris entre 0 et 255
(setq ent (vlax-ename->VLA-Object ent)) ; ent correspondant au nom d'entité de l'objet initial (entité graphique, calque, ...)
(setq true (vla-get-TrueColor ent))     ; Récupère le VLA-Object définissant la propriété TrueColor de l'objet 'ent'
(apply 'vla-setRGB (cons true color))   ; Modifie les propriétés RGB du VLA-Object TrueColor de l'objet 'ent' avec les nouvelles valeurs
(vla-put-TrueColor ent true)            ; Réaffecte le VLA-Object TrueColor modifié à l'entité 'ent'

Autrement, en passant par la liste DXF, regarde >>ici<< sur les fonctions de conversion des couleurs développées par LeeMac. C'est un peu plus..complexe mais cela fonctionne avec la liste DXF :

(setq R 255 G 0 B 0) ; Défini la valeur des couleurs RGB séparemment
(setq DXF420 (LM:RGB->True R G B)) ; Calcule l'entier du code DXF 420 correspondant à la couleur RGB
(setq DXF62 (LM:RGB->ACI R G B))   ; Calcule la couleur ACI la plus proche du code DXF 420
(setq entlist
  (if (assoc 62 (entget ent))
    (subst (cons 62 DXF62) (assoc 62 (entget ent)) (entget ent))
    (append (entget ent) (list (cons 62 DXF62)))
  )
)
(setq entlist
  (if (assoc 420 entlist)
    (subst (cons 420 DXF420) (assoc 420 entlist) entlist)
    (append entlist (list (cons 420 DXF420)))
  )
)
(entmod entlist)

PS: J'avais en effet oublié ce détails @VDH-Bruno concernant les listes DXF et (entmod), s'il y a des doublons, la dernière occurrence uniquement est interprétée ^^"
Merci du rappel ! ♥

Bisous,
Luna

Modifié par Luna
Posté(e)

Bonjour,

Je n'ai pas d'AutoCAD sous la main pour te faire du surmesure, mais tu peux procéder avec entmode comme tu procedes avec entmake au moyen de la fonction append pour ajouter la paire DXF qui t'intéresse, dans mon message précedant je t'ai copier coller à titre d'exemple une réponse précedemment faite sur le forum lisp

Cdt

 

Apprendre => Prendre => Rendre

Posté(e)

Merci beaucoup pour ces réponses rapides et complètes.

C'est parfait.

En ajoutant ce code c'est nikel pour la manip que j'ai à faire :

(entmod (append en (list '(420 . 16711680))))

Je vais creuser tout ce que tu m'as fournit @Luna pour approfondir.

Merci

Posté(e)
Il y a 1 heure, Luna a dit :
(setq entlist
  (if (assoc 62 (entget ent))
    (subst (cons 62 DXF62) (assoc 62 (entget ent)) (entget ent))
    (append (entget ent) (list (cons 62 DXF62)))
  )
)
(setq entlist
  (if (assoc 420 entlist)
    (subst (cons 420 DXF420) (assoc 420 entlist) entlist)
    (append entlist (list (cons 420 DXF420)))
  )
)
(entmod entlist)

PS: J'avais en effet oublié ce détails @VDH-Bruno concernant les listes DXF et (entmod), s'il y a des doublons, la dernière occurrence uniquement est interprétée ^^"
Merci du rappel ! ♥

Bisous,
Luna

Bonjour Luna,

Oui c'était l'occasion de rappeler une astuce parmi d'autres, mais si on veut être puriste la méthode avec if, subst, append est plus académique et c'est celle que j'utilise bien plus volontier (plus lisible) dans du code appelé à être réutilisé, et c'est celle que je recommanderais pour un débutant, après une fois que les bases sont bien assimilés, on peut effectivement prendre quelques libertés pour du code ponctuel qui doit être taper à la va vite, ou pendant la phase de prototypage de son code.

Amicalement Bruno

Apprendre => Prendre => Rendre

Invité
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • 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é