Aller au contenu

Faire une sélection d'un bloc en fonction de deux de ses attributs


asptt9

Messages recommandés

Bonjour à tous,

 

J'ai plusieurs blocs différents dans mon dessin qui ont des attributs communs, j'aimerais si c'est possible créer un jeu de sélection en fonction de deux de ces attributs quel que soit le nom du bloc. Ce jeu de sélection devra au final me donner qu'un seul bloc vu que les attributs concernés sont la commune (nom d'étiquette: COMMUNE) et un numéro (nom d'étiquette: NUMGEOREF) (il n'y a pas deux fois le numéro dans la même commune). Mon but étant de faire apparaitre en gros plan le bloc sélectionné. Je pense que c'est possible en lisp mais ça dépasse mes compétences...

 

Ma commune et mon numéro sont déjà attribué aux variables commune et numg

 

A savoir que le zoom objet ne fonctionne pas correctement sur mon poste donc si il y a moyen de le contourner pour zoomer sur le bloc au final...

 

J'espère avoir été assez clair dans ma demande.

 

Merci par avance.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour ,

 

A savoir que le zoom objet ne fonctionne pas correctement sur mon poste donc si il y a moyen de le contourner pour zoomer sur le bloc au final...

Bon en repartant d’un code similaire de (gile) publié sur le forum, qui prend 2 minutes à adapter, je m’y colle par contre, je réponds plus à ton post publié ici:

http://cadxp.com/index.php?/topic/37570-zoom-sur-un-jeu-de-selection/page__p__206824#entry206824

 

En te proposant de tester une fonction équivalente au zoom objet, même si je ne comprends pas pourquoi il ne fonctionne pas chez toi..

 

A tester

;; Zsel - VDH-Bruno
;; D'aprés le code zbbox (gile) publié sur CadXP à l'adresse suivante:
;; http://cadxp.com/index.php?/topic/14427-les-lisp-de-gile/page__view__findpost__p__74705
;;
;; Effectue un zoom fenêtre dans la fenêtre courante, sur l'emprise des objets 
;; grippées à l'écran.
;; Code lisp équivalent à la commande zoom objet d'AutoCAD

(defun c:zsel (/ ss lst minpt maxpt)
 (vl-load-com)
 (or *acad* (setq *acad* (vlax-get-acad-object)))
 (or *acdoc* (setq *acdoc* (vla-get-ActiveDocument *acad*)))
 (if (setq ss (ssget "_I"))
   (progn (vla-StartUndoMark *acdoc*)
          (vlax-for o (setq ss (vla-get-ActiveSelectionSet *acdoc*))
            (vla-getBoundingBox o 'minpt 'maxpt)
            (setq lst (cons (vlax-safearray->list minpt) (cons (vlax-safearray->list maxpt) lst)))
          )
          (vla-ZoomWindow
            *acad*
            (vlax-3d-point (apply 'mapcar (cons 'min lst)))
            (vlax-3d-point (apply 'mapcar (cons 'max lst)))
          )
          (vla-EndUndoMark *acdoc*)
   )
 )
 (princ)
)

A+

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Bonjour VDH-Bruno et merci pour ta réponse,

 

J'étais en vacances donc je n'ai pas pu répondre avant. Je viens de tester ton programme pour le zoom objet et il marche très bien donc je te remercie.

 

Aurais-tu une idée par contre pour faire une sélection par attribut de bloc à l'intérieur d'une autre sélection (en gros filtrer une sélection courante selon un attribut donné)

 

Merci par avance.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

Special_selections : Plusieurs routines pour faire des jeux de sélection suivant les propriétés d'un objet,suivant une fenêtre parallèle au SCU courant ou ou une fenêtre délimitée par un objet.

commandes : ssc (suivant la couleur), ssl (suivant le calque), sse (suivant le type d'entité), sstl (suivant le type de ligne), ssatt (suivant la valeur d'un attribut) , sscu (fenêtre parallèle au SCU), ssof (fenêtre définie par un objet), ssoc (capture définie par un objet), inv_sel (inverser la sélection),

ssd (suivant les valeurs de paramètres de blocs dynamiques).

liens : Sélection de tous les objets d'un calque ; Sélection suivant SCU... ; Sélection rapide de blocs par valeur d'attribut ? ; SELETION BLOC DYNAMIC!!!!!!!!

 

La fonction ssat dans Les LISP de (gile) sur la page suivante http://cadxp.com/index.php?/topic/14427-les-lisp-de-gile/ ne conviendrait –elle pas ?

 

A+

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

J'ai déjà testé le programme ssatt de (gile) mais je n'arrive pas à la faire fonctionner...

Il me demande l'attribut source et je ne comprends pas bien ce que c'est...

Du coup j'ai trouvé un programme qui me permet de faire une sélection par attribut que j'ai légèrement modifié pour que la sélection se fasse toujours avec le même attribut mais je ne sais pas comment faire pour faire une sélection selon deux attributs en même temps... Voici le bout de code dont je me sert:

 

(defun c:ssnum (/ att elst tag val ss1 ss2 n ent)

 

(setq numg (getstring "quel est le numéro géoréférencé à rechercher ?"))

 

(and

 

(setq att "NUMGEOREF")

 

(if (or (= att "") (= att " "))

 

(and (setq att (car (nentsel "\nSélectionnez l'attribut source: ")))

 

(= (cdr (assoc 0 (setq elst (entget att)))) "ATTRIB")

 

(setq tag (cdr (assoc 2 elst))

 

val (cdr (assoc 1 elst))

 

)

 

)

 

(setq tag (strcase att)

 

val numg

 

)

 

)

 

(setq ss2 (ssadd))

 

(setq ss1 (ssget "_X" '((0 . "INSERT") (66 . 1))))

 

(repeat (setq n (sslength ss1))

 

(setq ent (ssname ss1 (setq n (1- n)))

 

att (entnext ent)

 

)

 

(while (= (cdr (assoc 0 (setq elst (entget att)))) "ATTRIB")

 

(if (and (= (cdr (assoc 2 elst)) tag)

 

(= (cdr (assoc 1 elst)) val)

 

)

 

(ssadd ent ss2)

 

)

 

(setq att (entnext att))

 

)

 

)

 

(sssetfirst nil ss2)

 

)

 

(princ)

 

)

 

Avec ce programme je sélectionne tous les blocs dont l'étiquette d'attribut NUMGEOREF correspond au numéro que j'ai renseigné. En fait ce que j'aimerais faire c'est sélectionner tous les blocs qui contiennent les étiquettes d'attributs NUMGEOREF et COMMUNE (les deux en même temps) avec les valeurs que je renseigne dans le programme.

Lien vers le commentaire
Partager sur d’autres sites

Bonsoir,

 

En fait ce que j'aimerais faire c'est sélectionner tous les blocs qui contiennent les étiquettes d'attributs NUMGEOREF et COMMUNE (les deux en même temps) avec les valeurs que je renseigne dans le programme.

 

Un code écrit à la volée (donc pas vraiment testé), le code si dessous permet de sélectionner les blocs, en fonction d’une ou plusieurs étiquettes d’attributs à sélectionner dans une liste de zone déroulante et en fonction de valeurs spécifiques (attention à la casse) pour les attributs spécifiés.

 

 

;; VDH-Bruno                                               le: 28/05/2013
;; ======================================================================
;; Sélection des références de bloc en fonction des étiquettes d'attribut
;; et de leurs valeurs spécifiques.

(defun c:ssEtVal (/ lstTagAtt tagAtt doc ss1 ss2 inclu-p inputval)
 (vl-load-com)
 (setq	doc (vla-get-ActiveDocument (vlax-get-acad-object))
ss2 (ssadd)
 )

 ;; liste les noms des définition d'attribut de la table des blocs
 (vlax-for b (vla-get-Blocks doc)
   (if	(and (= (vla-get-IsLayout B) :vlax-false)
     (= (vla-get-IsXref B) :vlax-false)
     (not (wcmatch (vla-get-Name B) "*|*"))
)
     (vlax-for	o b
(and (= (vla-get-ObjectName o) "AcDbAttributeDefinition")
     (not (member (setq tagAtt (vla-get-TagString o)) lstTagAtt))
     (setq lstTagAtt (cons tagAtt lstTagAtt))
)
     )
   )
 )

 ;; Affiche la liste dans une zone de liste pour un choix multiples
 (setq
   lstTagAtt (listbox
	"Etiquettes des définitions d'attributs "
	"Sélectionnez les étiquettes à filtrer..."
	(mapcar 'cons (setq lstTagAtt (vl-sort lstTagAtt '<)) lstTagAtt)
	2
      )
 )

 ;; Valeurs à associer aux étiquettes correspondantes
 (defun inputval (l)
   (if	l
     (cons
(cons
  (car l)
  (getstring (strcat "Valeur à rechercher pour l'étiquette " (car l) ": ")
  )
)
(inputval (cdr l))
     )
   )
 )

 (cond
   ((setq lstTagAtt (inputval lstTagAtt))

    ;; Définition de la zone de sélection
    (princ "\nSélectionnez les blocs ou <tout>: ")
    (or (ssget (list '(0 . "INSERT") '(66 . 1)))
 (ssget "_X" (list '(0 . "INSERT") '(66 . 1)))
    )

    ;; Prédicat d'inclusion d'une liste l1 dans une autre liste l2
    (defun inclu-p (l1 l2)
      (cond ((null l1) t)
     ((member (car l1) l2) (inclu-p (cdr l1) l2))
     (t nil)
      )
    )

    ;; Filtrage de la sélection
    (vlax-for b (setq ss1 (vla-get-ActiveSelectionSet doc))
      ;; vérifie que les critères de filtres liste (Tag .Val) sont compris dans le bloc
      (if (inclu-p
     lstTagAtt
     ;; Liste les couples (Tag .Val) de la référence de bloc   
     (mapcar
       '(lambda (x) (cons (vla-get-TagString x) (vla-get-TextString x)))
       (vlax-invoke b 'GetAttributes)
     )
   )
 (ssadd (vlax-vla-object->ename B) ss2)
      )
    )
    (vla-delete ss1)
    (sssetfirst nil ss2)
   )
 )
 (princ)
)

 

Les routines associés à charger avant la fonction principale

;;============================================================================;;

;; STR2LST
;; Transforme un chaine avec séparateur en liste de chaines
;;
;; Arguments
;; str : la chaine à transformer en liste
;; sep : le séparateur

;;
;; Exemples
;; (str2lst "a b c" " ") -> ("a" "b" "c")
;; (str2lst "1,2,3" ",") -> ("1" "2" "3")
;; (mapcar 'read (str2lst "1,2,3" ",")) -> (1 2 3)

(defun str2lst (str sep / pos)
 (if (setq pos (vl-string-search sep str))
   (cons (substr str 1 pos)
  (str2lst (substr str (+ (strlen sep) pos 1)) sep)
   )
   (list str)
 )
)


;; ListBox (gile)
;; Boite de dialogue permettant un ou plusieurs choix dans une liste
;;
;; Arguments
;; title : le titre de la boite de dialogue (chaîne)
;; msg ; message (chaîne), "" ou nil pour aucun
;; keylab : une liste d'association du type ((key1 . label1) (key2 . label2) ...)
;; flag : 0 = liste déroulante
;;        1 = liste choix unique
;;        2 = liste choix multipes
;;
;; Retour : la clé de l'option (flag = 0 ou 1) ou la liste des clés des options (flag = 2)
;;
;; Exemple d'utilisation
;; (listbox "Présentation" "Choisir une présentation" (mapcar 'cons (layoutlist) (layoutlist)) 1)


(defun ListBox (title msg keylab flag / tmp file dcl_id choice)
 (setq        tmp  (vl-filename-mktemp "tmp.dcl")
                   file (open tmp "w")
 )
 (write-line
   (strcat "ListBox:dialog{label=\"" title "\";")
   file
 )
 (if (and msg (/= msg ""))
   (write-line (strcat ":text{label=\"" msg "\";}") file)
 )
 (write-line
   (cond
     ((= 0 flag) "spacer;:popup_list{key=\"lst\";")
     ((= 1 flag) "spacer;:list_box{key=\"lst\";")
     (T "spacer;:list_box{key=\"lst\";multiple_select=true;")
   )
   file
 )
 (write-line "}spacer;ok_cancel;}" file)
 (close file)
 (setq dcl_id (load_dialog tmp))
 (if (not (new_dialog "ListBox" dcl_id))
   (exit)
 )
 (start_list "lst")
 (mapcar 'add_list (mapcar 'cdr keylab))
 (end_list)
 (action_tile
   "accept"
   "(or (= (get_tile \"lst\") \"\")
   (if (= 2 flag) (progn
   (foreach n (str2lst (get_tile \"lst\") \" \")
   (setq choice (cons (nth (atoi n) (mapcar 'car keylab)) choice)))
   (setq choice (reverse choice)))
   (setq choice (nth (atoi (get_tile \"lst\")) (mapcar 'car keylab)))))
   (done_dialog)"
 )
 (start_dialog)
 (unload_dialog dcl_id)
 (vl-file-delete tmp)
 choice
)

 

A+

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup VDH-Bruno,

 

J'ai testé ton programme et il fonctionne parfaitement.

Cependant il reste trop général par rapport à ce que je souhaitais, en fait seul les deux étiquettes NUMGEOREF et COMMUNE m'intéressent. Le fait d'aller les sélectionner dans une liste déroulante me fait perdre pas mal de temps...

 

En fait je connais déjà les valeurs que je vais rechercher dans les étiquettes COMMUNE et NUMGEOREF, je les récupère précédemment via un petit programme lié à un fichier texte généré par une base de donnée ACCESS. Les valeurs sont stockées dans les variables commune pour l'étiquette COMMUNE et numg pour l'étiquette NUMGEOREF.

 

En fait, je voudrais qu'en cliquant sur le bouton pour appliquer la commande, la sélection se fasse toute seule sans que je n'ai à réintervenir. Est-ce possible ?

 

Si oui, peut-être peux-tu me guider pour que j'essaye de le faire tout seul parce que pour le moment tu fais tout à ma place...(précision: je suis débutant en LISP)

 

En tout cas merci beaucoup pour le temps que tu me consacre.

 

PS: je garde ton programme dans un coin car il peut être très utile pour une recherche précise.

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

J'ai testé ton programme et il fonctionne parfaitement.

Cependant il reste trop général par rapport à ce que je souhaitais, en fait seul les deux étiquettes NUMGEOREF et COMMUNE m'intéressent. Le fait d'aller les sélectionner dans une liste déroulante me fait perdre pas mal de temps...

C’était un peu fait exprès, pour que cela soit réutilisable pour le plus grand nombre.

 

En fait je connais déjà les valeurs que je vais rechercher dans les étiquettes COMMUNE et NUMGEOREF, je les récupère précédemment via un petit programme lié à un fichier texte généré par une base de donnée ACCESS. Les valeurs sont stockées dans les variables commune pour l'étiquette COMMUNE et numg pour l'étiquette NUMGEOREF.

 

En fait, je voudrais qu'en cliquant sur le bouton pour appliquer la commande, la sélection se fasse toute seule sans que je n'ai à réintervenir. Est-ce possible ?

 

Oui bien sur.

 

Si oui, peut-être peux-tu me guider pour que j'essaye de le faire tout seul parce que pour le moment tu fais tout à ma place...(précision: je suis débutant en LISP)

Il est plus facile d’expliquer une ligne de code ou une portion que tout un programme, j’ai laissé quelques commentaires dans le code, en l’exécutant ligne par ligne et en analysant les valeurs en retour tu devrais avoir un bon aperçu de son fonctionnement.

 

Pour personnaliser le programme tu t’apercevra que toutes la première partie du code ainsi que les routines associés STR2LST ListBox de (gile) ne sert qu’à la gérer les entrées utilisateurs. Donc si tu veux coder en dure, il faut supprimer ceci :

  ;; liste les noms des définition d'attribut de la table des blocs
 (vlax-for b (vla-get-Blocks doc)
   (if (and (= (vla-get-IsLayout B) :vlax-false)
            (= (vla-get-IsXref B) :vlax-false)
            (not (wcmatch (vla-get-Name B) "*|*"))
       )
     (vlax-for o b
       (and (= (vla-get-ObjectName o) "AcDbAttributeDefinition")
            (not (member (setq tagAtt (vla-get-TagString o)) lstTagAtt))
            (setq lstTagAtt (cons tagAtt lstTagAtt))
       )
     )
   )
 )

 ;; Affiche la liste dans une zone de liste pour un choix multiples
 (setq
   lstTagAtt (listbox
               "Etiquettes des définitions d'attributs "
               "Sélectionnez les étiquettes à filtrer..."
               (mapcar 'cons (setq lstTagAtt (vl-sort lstTagAtt '<)) lstTagAtt)
               2
             )
 )

 ;; Valeurs à associer aux étiquettes correspondantes
 (defun inputval (l)
   (if l
     (cons
       (cons
         (car l)
         (getstring (strcat "Valeur à rechercher pour l'étiquette " (car l) ": ")
         )
       )
       (inputval (cdr l))
     )
   )
 )

 

Puis tu peux remplacer l’expression suivante :

((setq lstTagAtt (inputval lstTagAtt))

 

Par tes valeurs en dure sous forme d’une liste de paire pointé du type (("ETIQUETTE1" . "VALEUR1") ("ETIQUETTE2" . "VALEUR2") ...). Dans ton cas cela devrait être dans les variable global précédemment définie avec des valeurs de type chaînes.

(setq lstTagAtt (list (cons "COMMUNE" commune) (cons "NUMGEOREF" numg)))

 

Puis si tu ne veux pas non plus avoir le choix de la sélection remplace également ceci :

;; Définition de la zone de sélection
    (princ "\nSélectionnez les blocs ou <tout>: ")
    (or (ssget (list '(0 . "INSERT") '(66 . 1)))
        (ssget "_X" (list '(0 . "INSERT") '(66 . 1)))
    )

 

Ne garde que cela:

(ssget "_X" (list '(0 . "INSERT") '(66 . 1)))

 

Enfin en sécurisant un peu et en simplifiant les instructions devenus inutiles, le code pourrait donné à peu près cela :

 

(defun c:ssasptt9 (/ lstTagAtt doc ss1 ss2 inclu-p)
 (vl-load-com)
 (or commune (setq commune "")); au cas ou elle n'est pas définie
 (or numg (setq numg "")); au cas ou elle n'est pas définie
 (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))
       ss2 (ssadd)
       lstTagAtt (list (cons "COMMUNE" commune) (cons "NUMGEOREF" numg)))
  
    ;; Définition de la zone de sélection
    (ssget "_X" (list '(0 . "INSERT") '(66 . 1)))

    ;; Prédicat d'inclusion d'une liste l1 dans une autre liste l2
    (defun inclu-p (l1 l2)
      (cond ((null l1) t)
            ((member (car l1) l2) (inclu-p (cdr l1) l2))
            (t nil)
      )
    )

    ;; Filtrage de la sélection
    (vlax-for b (setq ss1 (vla-get-ActiveSelectionSet doc))
      ;; vérifie que les critères de filtres liste (Tag .Val) sont compris dans le bloc
      (if (inclu-p
            lstTagAtt
            ;; Liste les couples (Tag .Val) de la référence de bloc   
            (mapcar
              '(lambda (x) (cons (vla-get-TagString x) (vla-get-TextString x)))
              (vlax-invoke b 'GetAttributes)
            )
          )
        (ssadd (vlax-vla-object->ename B) ss2)
      )
    )
    (vla-delete ss1)
    (sssetfirst nil ss2) 
 (princ)
)

 

Pour tester avant de lancer la commande ssasptt9, tu peux paramétrer tes variables comme ceci:

(setq commune (getstring "Valeur à rechercher pour l'étiquette COMMUNE: ")
     numg    (getstring "Valeur à rechercher pour l'étiquette NUMGEOREF: ")
)

 

Cordialement,

Apprendre => Prendre => Rendre

Lien vers le commentaire
Partager sur d’autres sites

Merci beaucoup VDH-Bruno, grâce à toi je vais gagner beaucoup de temps.

Voici le programme final qui me permet de zoomer sur un bloc dont la valeur des étiquettes est égale à celle que l'on renseigne en début de programme:

 

(defun c:zoomnum (/ lstTagAtt doc ss1 ss2 inclu-p)
 (vl-load-com)
 (setq numg (getstring "Quel est le numéro à rechercher ?")
       commune (getstring "Quelle est la commune à rechercher ?")
 )
 (or commune (setq commune "")); au cas ou elle n'est pas définie
 (or numg (setq numg "")); au cas ou elle n'est pas définie
 (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))
       ss2 (ssadd)
       lstTagAtt (list (cons "COMMUNE" commune) (cons "NUMGEOREF" numg)))
  
    ;; Définition de la zone de sélection
    (ssget "_X" (list '(0 . "INSERT") '(66 . 1)))

    ;; Prédicat d'inclusion d'une liste l1 dans une autre liste l2
    (defun inclu-p (l1 l2)
      (cond ((null l1) t)
            ((member (car l1) l2) (inclu-p (cdr l1) l2))
            (t nil)
      )
    )

    ;; Filtrage de la sélection
    (vlax-for b (setq ss1 (vla-get-ActiveSelectionSet doc))
      ;; vérifie que les critères de filtres liste (Tag .Val) sont compris dans le bloc
      (if (inclu-p
            lstTagAtt
            ;; Liste les couples (Tag .Val) de la référence de bloc   
            (mapcar
              '(lambda (x) (cons (vla-get-TagString x) (vla-get-TextString x)))
              (vlax-invoke b 'GetAttributes)
            )
          )
        (ssadd (vlax-vla-object->ename B) ss2)
      )
    )
    (vla-delete ss1)
    (sssetfirst nil ss2)
 (zsel)
 (command)
 (princ)
 )

(defun zsel (/ ss lst minpt maxpt)
 (vl-load-com)
 (or *acad* (setq *acad* (vlax-get-acad-object)))
 (or *acdoc* (setq *acdoc* (vla-get-ActiveDocument *acad*)))
 (if (setq ss (ssget "_I"))
   (progn (vla-StartUndoMark *acdoc*)
          (vlax-for o (setq ss (vla-get-ActiveSelectionSet *acdoc*))
            (vla-getBoundingBox o 'minpt 'maxpt)
            (setq lst (cons (vlax-safearray->list minpt) (cons (vlax-safearray->list maxpt) lst)))
          )
          (vla-ZoomWindow
            *acad*
            (vlax-3d-point (apply 'mapcar (cons 'min lst)))
            (vlax-3d-point (apply 'mapcar (cons 'max lst)))
          )
          (vla-EndUndoMark *acdoc*)
   )
 )
 (princ)
)

 

 

Un grand merci à toi VDH-Bruno.

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é