Aller au contenu

Messages recommandés

Posté(e)

Bonjou à tous,

 

j'ai une liste calques que j'ai moi-même défini par

(setq liste1 (list "calque1" "calque2" ...)

puis une autre de liste des calques liste2 du dessin que je veux analyser.

J'ai fait ca

 

 
(setq d 0)
(repeat (length liste2)
(setq nom_plan (nth d liste2))
[surligneur] (if (tblsearch liste1 nom_plan)[/surligneur]
(prompt (strcat "Le calque " nom_plan " est compris dans la liste"))
(setq d (+ d 1))
)

 

Je voudrais mettre une condition que si un des calques de la liste2 est le même que celui d'un des calques de la liste1 alors j'affiche dans la barre de commande autocad un texte avec un prompt.

J'ai un problème avec le if et le tblsearch qui à mon avis n'est pas approprié,

je ne sais pas comment faire pour rechercher si le nom d'un calque de la liste2 est compris dans la liste1.

 

Merci par avance de votre aide.

John.

Posté(e)

Salut,

 

La fonction tblsearch (comme les fonctions tblnext et tblobjname) fonctionne avec les "tables" (ou collections) du dessin.

Ces fonctions requièrent comme premier argument le nom de la table soit : "LAYER", "LTYPE", "VIEW", "STYLE", "BLOCK", "UCS", "APPID", "DIMSTYLE", et "VPORT" pour, respectivement : les calques, types de lignes, vues nommées, styles de texte, blocs, SCU nommées, applications enregistrées et fenêtre nommées.

 

N'hésite jamais à regarder dans l'aide aux développeurs les arguments requis et les valeurs retournées des fonctions LISP que tu veux utiliser. Si tu travaille avec l'éditeur Visual LISP (ce que je recommande fortement), il suffit de sélectionner une fonction dans la fenêtre active (par double clic) et de faire CTRL+F1 pour que l'aide s'ouvre à la page de la fonction sélectionnée

 

Pour tester si un élément est contenu dans une liste, tu peux utiliser la fonction member qui retourne la liste à partir de la première occurrence de l'élément ou nil s'il n'est pas trouvé.

 

(member 5 '(3 9 7 5 6 8)) retourne (5 6 8)

(member "z" '("a" "b" "c")) retourne nil

 

donc, pour une utilisation avec if :

(if (member ele lst)
 (princ "Est dans la liste")
 (princ "N'est pas dans la liste")
)

 

Dans ton cas précis, la fonction tblsearch correctement employée te permettrait de savoir si les calques de la liste prédéfinie sont présents dans le dessin (sont contenus dans la table)

(foreach l lst1
 (if (tblsearch "LAYER" l)
   (princ
     (strcat "\nLe calque \"" l "\" est dans le dessin")
   )
   (princ
     (strcat "\nLe calque \"" l "\" n'est pas dans le dessin")
   )
 )
)

 

Inversement, si tu veux tester tous les calques du dessin pour savoir s'ils sont dans la liste prédéfinie, tu peux utiliser tblnext :

(setq lay nil)
(while (setq lay (tblnext "LAYER" (not lay)))
 (setq name (cdr (assoc 2 lay)))
 (if (member name lst1)
   (princ
     (strcat "\nLe calque \"" name "\" est dans la liste")
   )
   (princ
     (strcat "\nLe calque \"" name "\" n'est pas dans la liste")
   )
 )
)

 

Je te propose deux petites routines (peut-être un peu moins faciles à comprendre parce qu'elles utilisent la récursivité) qui comparent deux listes.

 

;;; COMMON Retourne la liste des éléments communs à l1 et l2
;;; (COMMON '(1 2 3 4) '(2 3 4 5)) -> (2 3 4)
(defun common (l1 l2)
 (if l1
   (if	(member (car l1) l2)
     (cons (car l1) (common (cdr l1) l2))
     (common (cdr l1) l2)
   )
 )
)

;;; EXCLUSIVE Retourne une liste contenant les éléments appartenant exclusivement à l1
;;; (exclusive '(1 2 3 4) '(2 3 4 5)) -> (1)
;;; (exclusive '(2 3 4 5) '(1 2 3 4)) -> (5)
(defun exclusive (l1 l2)
 (if l1
   (if	(member (car l1) l2)
     (exclusive (cdr l1) l2)
     (cons (car l1) (exclusive (cdr l1) l2))
   )
 )
)

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

Posté(e)

Merci Gile pour ta réponse.

Je travaille avec l'aide de Visual Lisp mais des fois je ne comprend pas très bien du fait de manque de connaissances.

Un autre truc que je ne comprend pas.

 

Je veux sélectionner suivant le nom d'un calque les polylignes 3D fermées ou non appartenant à ce calque.

J'ai donc fait

(setq ss1 (ssget "X" (list (cons 0 "POLYLINE") (cons 70 1) (cons 8 lay)))) 

mais ceci ne marche pas.

J'ai donc essayé par une autre méthode

 (setq ss1 (ssget "X" (list((0 . "POLYLINE") (-4 . "&") (70 . 1) (-4 . "")))))

 

alors que ce code sans le 70 (qui indique la fermeture ou non d'une polyligne) marche bien

(setq ss1 (ssget "X" (list (cons 0 "POLYLINE") (cons 8 lay)))) 

Pourquoi ?

 

De même, j'essaye de comparer le noms des blocs contenu dans un calque avec le nom de ce même calque qui doivent dans ma nomenclature identique.

Ainsi, un bloc BLOCK1 doit être dans le calque nommé "BLOCK1"

Si il y en a un autre c pas bon, du coup

j'ai essayé de suivre tes conseils avec

 

(setq bloc nil)

(setq d 0)

(repeat (length layers)

(setq nom_plan (nth d layers))

(if (setq ss (ssget "X" (list (cons 0 "INSERT") (cons 8 nom_plan))))

(while (setq bloc (tblnext "BLOCK" (not bloc)))

(setq nom_bloc (cdr (assoc 2 bloc)))

(if (not (= nom_bloc nom_plan))

(princ

(strcat "\nLe bloc " nom_bloc " est contenu dans le calque " nom_plan )

)

)

)

)

(setq d (+ d 1))

)

 

 

Mais je n'arrive pas à faire la liste des blocs contenu dans un seul calque vu que je fais un repeat.

 

Pour ce qui concerne la partie précedente en première partie du post, j'ai utilisé la fonction member qui est très pratique et simple.. Ca fonctionne nickel.

 

Merci par avance de ton aide.

John.

Posté(e)

Tout d'abord essaye de ne pas poser de questions qui ne sont pas en rapport avec le sujet du fil de discussion ("liste à comparer"). Tu avais commencé un fil qui parlait des filtres de sélections ici, ta question y aurait été plus à sa place.

Ceci pour faciliter les recherches ultérieures (même pour toi).

 

(setq ss1 (ssget "X" (list (cons 0 "POLYLINE") (cons 70 1) (cons 8 lay))))

Le problème vient du groupe 70. Avec ton filtre seuls les polylignes sur le calque 'lay' ayant un groupe 70 égal à (70 . 1) seront sélectionnées. Les polylignes 3d sont caractérisées par le groupe 8 mais peuvent être ouverts ou fermées (elles peuvent aussi être splinées mais on va faire simple) :

- polyligne 3d ouverte -> (70 . 8)

- polyligne 3d fermée -> (70 . 9) où 9 = 8 + 1

Si tu veux sélectionner toutes les polylignes 3d, codes (70 . 8) et (70 . 9), tu peux utiliser l'opérateur logique OR :

(setq ss1 (ssget "X"
	 (list '(0 . "POLYLINE")
	       '(-4 . "		       '(70 . 8)
	       '(70 . 9)
	       '(-4 . "OR>")
	       (cons 8 lay)
	 )
  )
)

ou, plus élégant, l'opérateur relationnel sur les codes binaire & qui vérifie si le (ou les) code(s) binaire(s) spécifié(s) est (sont) contenu(s) dans le code de groupe.

(setq ss1 (ssget "X"
	 (list '(0 . "POLYLINE")
	       '(-4 . "&")
	       '(70 . 8)
	       (cons 8 lay)
	 )
  )
)

NOTA : le premier filtre ne sélectionnera pas les polylignes 3d splinées, (70 . 12) et (70 . 13), le second oui.

 

(setq ss1 (ssget "X" (list((0 . "POLYLINE") (-4 . "&") (70 . 1) (-4 . "")))))

Cette expression retournera une erreur :

"; erreur: syntaxe incorrecte de l'appel de fonction: (0 . "POLYLINE")"

 

En LISP toute expression qui commence par une parenthèse est considérée comme un "appel de fonction. L'interpréteur attend donc que le premier terme de l'espression soit une fonction, or (0 . "POLYLINE") n'est pas une fonction et ne peut pas non plus être évaluée car 0 non plus, n'est pas une fonction.

Quand on veut éviter l'évaluation d'une liste, on utilise la fonction quote (généralement abrégée avec une apostrophe).

'((0 . "POLYLINE")) ou (quote ((0 . "POLYLINE"))) retourne ((0 . "POLYLINE")) sans l'évaluer et c'est un filtre de sélection valide.

Si on utilise la fonction list, il y aura évaluation. Il faut donc "quoter" la paire pointée pour ne pas avoir d'erreur :

(list '(0 . "POLYLINE")) retourne aussi ((0 . "POLYLINE"))

Un peu plus avant, si le filtre de sélection doit être construit avec une variable, lay par exemple, qui doit donc être évaluée on ne peut "quoter" ni la paire pointée ni la liste :

'((0 . "POLYLINE") (8 . lay)) retournerait ((0 . "POLYLINE") (8 . LAY)) sans rien évaluer

(list '(0 . "POLYLINE") '(8 . lay)) retournerait ((0 . "POLYLINE") (8 . LAY)) sans évaluer lay

(list '(0 . "POLYLINE") (8 . lay)) provoquerait ; erreur: syntaxe incorrecte de l'appel de fonction: (8 . LAY)

'((0 . "POLYLINE") (cons 8 lay)) retournerait ((0 . "POLYLINE") (CONS 8 LAY)) sans évaluer (cons 8 lay)

Il faut donc écrire :

(list (cons 0 "POLYLINE") (cons 8 lay))

ou, plus simplement, puisque "POLYLINE" n'a pas besoin d'être évalué :

(list '(0 . "POLYLINE") (cons 8 lay))

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

Posté(e)

Décolé d'avoir posé certaines questions dans ce post mais dans mon cas, les deux sont liés.

J'ai compris maintenant pour les filtres de sélection. Un peu complexe mais c'est bon.

Merci pour ton aide.

Je vais m'en sortir je pense.

 

John.

Posté(e)

Bonjour,

 

Je n'ai pas trouvé le moyen de comparer le nom d'un bloc avec le nom du calque auquel il appartient. J'ai essayé de faire la liste des noms de blocs contenues dans ce dessin puis de la faire comparer au nom de calque.

Car dans ma nomenclature, un bloc qui s'appelle BLOCK1 doit se trouver dans le calque nommé BLOCK1 et non dans un autre.

 

Merci par avance de votre aide.

John.

 

 

Posté(e)

C'est bon. Avec beaucoup de recherches car je ne suis pas un pro du lisp,

j'ai réussi à faire ce que je voulais si cela peut en aider certains d'entre vous.

 

 
(setq blo nil)
(setq d 0)
(repeat (length layers)
(setq nom_plan (nth d layers))
(if (ssget "X" (list (cons 0 "INSERT") (cons 8 nom_plan)))
(while (setq blo (tblnext "BLOCK" (not blo)))
(setq nom_bloc (cdr (assoc 2 blo)))
(if (/= nom_bloc nom_plan)
(if (setq ss (ssget "X" (list (cons 0 "INSERT") (cons 2 nom_bloc) (cons 8 nom_plan))))
(write-line
     (strcat "\Il y a " (rtos (sslength ss) 2 0) " blocs " nom_bloc " contenu(s) dans le calque " nom_plan )
   file)
   )
 ))
)
(setq d (+ d 1))
)

 

John

  • 4 semaines après...
Posté(e)

Bonjour,

 

J'ai dans un dessin un grand nombre de blocs type point avec un seul attribut et je dois être sur qu'il n'y a pas de doublons dans les attributs, c'est à dire deux blocs de position différente mais avec un attribut numéro identique.

 

J'ai pensé à faire une liste de tous les attributs d'un dessin mais après pour voir s'il n'y a pas de doublons, la je bloque.

 

Un conseil ?

Merci par avance.

John

Posté(e)

Salut

 

Queque chose de ce style ?

 

(defun c:dbl( / bl doc ent lst nombl msg)

 (defun nombl(bl)
   (if (vlax-property-available-p bl 'effectivename)
     (vla-get-effectivename bl)
     (vla-get-name bl)
   )
 )

 (defun msg(ent)
   (princ (strcat "Le bloc " (nombl (cadr ent)) " à la position "))
   (princ (trans (vlax-get (cadr ent) 'insertionpoint) 0 1))
 )

 (setq doc (vla-get-activedocument (vlax-get-acad-object)))
 (and (ssget "x" (list (cons 0 "INSERT") (cons 66 1)))
   (progn
     (vlax-for ent (setq sel (vla-get-activeselectionset doc))
(setq lst (cons (list (vla-get-textstring (car (vlax-invoke ent 'getattributes))) ent) lst))
     )
     (vla-delete sel)
     (while (setq ent (car lst))
(setq lst (cdr lst)
      sui lst
)
(while (setq bl (assoc (car ent) sui))
  (terpri)
  (msg ent)
  (princ "\ à le même attribut que ")
  (msg bl)
  (setq sui (cdr (member bl sui))
	ent bl
	lst (vl-remove bl lst)
  )
)
     )
   )
 )
 (princ)
)

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

  • 2 semaines après...
Posté(e)

Bonjour Patrick35,

 

Je viens juste de voir ta réponse car j'étais en déplacement depuis deux semaines.

Oui c'est exactement ce qu'il faut par contre serait il possible au lieu d'afficher le nom du bloc d'avoir la valeur de l'attribut correspond.

 

Merci par avance de ton aide.

John.

Posté(e)

J'ai essayé de modifier la première partie du code avec le defun nombl mais en intervenant directement dans le while c'est plus simple.

Merci de ton aide Gile

John.

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é