Aller au contenu

rappeler une sélection


x_all

Messages recommandés

bonjour

ça fait un mnt que je veux me faire une fonction qui sélectionne tous les blocs dynamique en ft de leur nom
J'ai piquer des bout de code à droite et à gauche, (merci (gile) et lee mac) mais je bute sur la fin

comment faire pour que quand le lisp me rend la main, les bloc soit effectivement "au bout de la souris" 
Naïvement je croyait que le rappel de Bsel à la fin ferai ce boulot comme il m'a sembler le voir faire dans ssd de (gile) mais apparemment, ça suffit pas...

Tout tourne pas trop mal il me semble sauf que rien n'est sélect bien que bsel contienne bien les bloc que je veux à l'inspection dans l'éditeur

merci de vos lumières

;; ssbn sélectionne par nom de bloc dynamique


(defun C:ssbn (/ doc-vba bs sel-vba nom-ch ent-vba sbloc bl j bsel )

  (print
    " sélectionner un bloc, retourne une sélection des blocs ayant le même non (blocdyn acceptés) "
  )

					; initialisation VL
  (vl-load-com)
  (setq doc-vba (vla-get-activedocument (vlax-get-acad-object)))
  (vla-startundomark doc-vba)		; Activer le début de l'undo



  (while (not bs) (setq bs (ssget '((0 . "INSERT")))))
					; seléctionne un bloc
  (setq sel-vba (vla-get-activeselectionset doc-vba))
					; sel-vba est le selection set courant de doc
  (setq ent-vba (vla-item sel-vba 0))	;ent-vba est le 1er élément de sel-vba

  (setq nom-ch (LM:blockname ent-vba))
  (princ nom-ch)

  ;;  sélection de tous les blocs du dessin (astuce (gile) pour prendre que les blocdyn avec un nom *u
  (setq	sbloc	(ssget "X" (list (cons 0 "INSERT") (cons 2 (strcat nom-ch ",`*U*"))) )				
	sel-vba	(vla-get-activeselectionset doc-vba)
					; sel-vba est le selection set courant de doc-vba
	j	0
	bsel	(ssadd)
  )

  (vlax-for bl sel-vba

    (if	(= (LM:blockname bl) nom-ch)
      (progn
	(ssadd (vlax-vla-object->ename bl) bsel)  
	(setq j (+ 1 j))
      )
    )
    ;; fin de if
    (print j)
  )
(print)
 bsel
)


;; Block Name  -  Lee Mac
;; Returns the true (effective) name of a supplied block reference

(defun LM:blockname (obj)
  (if (vlax-property-available-p obj 'effectivename)
    (defun LM:blockname (obj) (vla-get-effectivename obj))
    (defun LM:blockname (obj) (vla-get-name obj))
  )
  (LM:blockname obj)
)

 

Lien vers le commentaire
Partager sur d’autres sites

Salut,

On peut faire plus simple.
La routine de Lee Mac, outre son côté quelque peu 'cryptique', date certainement d'avant la sortie d'AutoCAD 2012 et des fonctions getpropertyvalue et setpropertyvalue qui évitent d'utiliser l'interface COM/ActiveX (VBA).

(defun c:ssbn (/ ent bloc nombloc ss i)

  ;; sélection du bloc source
  (while
    (not
      (and
	(setq ent (car (entsel "\nSéléctionnez le bloc source: ")))
	(= (cdr (assoc 0 (entget ent))) "INSERT")
      )
    )
     (prompt "Sélection non valide.")
  )

  ;; récupération du nom effectif du bloc source
  (setq nombloc (strcat (getpropertyvalue ent "BlockTableRecord/Name")))

  ;; sélection de tous les blocs dynamiques
  (setq	ss
	 (ssget	"_X"
		(list (cons 0 "INSERT") (cons 2 (strcat nombloc ",`*U*")))
	 )
  )

  ;; filtre des blocs dynamiques suivant leur nom effectif
  (repeat (setq i (sslength ss))
    (setq bloc (ssname ss (setq i (1- i))))
    (if	(/= (strcat (getpropertyvalue bloc "BlockTableRecord/Name"))
	    nombloc
	)
      (ssdel bloc ss)
    )
  )
  ;; affichage de la sélection
  (sssetfirst nil ss)
  (princ)
)

 

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

Lien vers le commentaire
Partager sur d’autres sites

Une bonne pratique consiste à séparer le code de la commande en plusieurs fonctions réutilisables et testables séparément.

Dans ce cas :

  • une fonction getEffectiveName déterminer le nom effectif d'une référence de bloc (dynamique ou statique)
  • une fonction selectBlockByName pour obtenir un jeu de sélection contenant tous les blocs de l'espace courant dont le nom correspond à celui passé en argument.
  • une fonction ssbn qui appelle selectBlockByName en lui passant le nom effectif du bloc sélectionné.
  • une commande c:SSBN qui lance ssbn et affiche la sélection (grips).
;; getEffectiveName (fonction LISP)
;; Obtient le nom effectif d'un bloc (dynamique ou statique)
;; Renvoie nil si ent n'est pas le ename d'un bloc
(defun getEffectiveName	(ent)
  (if (= (cdr (assoc 0 (entget ent))) "INSERT")
    (getpropertyvalue
      (getpropertyvalue ent "BlockTableRecord")
      "Name"
    )
  )
)

;; selectBlockByName(fonction LISP)
;; Renvoie un jeu de sélection de tous les blocs (dynamiques ou statiques) de l'espace courant
;; dont le nom effectif correspond au nom passé en argument.
;; Renvoie niil si l'espace courant ne contient aucun bloc du nom spécifié ou dynamique.
(defun selectBlockByName (nombloc / ss i bloc)
  ;; sélection de tous les blocs
  (if (setq ss (ssget "_X"
		      (list
			(cons 0 "INSERT")
			(cons 2 (strcat nombloc ",`*U*"))
			(cons 410 (getvar 'ctab))
		      )
	       )
      )
    ;; filtre des blocs dynamiques suivant leur nom effectif
    (repeat (setq i (sslength ss))
      (setq bloc (ssname ss (setq i (1- i))))
      (if (/= (strcat (getEffectiveName bloc))
	      (strcat nombloc)
	  )
	(ssdel bloc ss)
      )
    )
  )
  ;; renvoi de la sélection
  ss
)

;; ssbn (fonction LISP)
;; Renvoie un jeu de sélection de tous les blocs (dynamiques ou statiques) de l'espace courant
;; ayant le même nom que le bloc sélectionné.
(defun ssbn (/ ent nombloc)
  ;; sélection du bloc source
  (while
    (not
      (and
	(setq ent (car (entsel "\nSéléctionnez le bloc source: ")))
	(setq nombloc (getEffectiveName ent))
      )
    )
     (prompt "Sélection non valide.")
  )
  ;; renvoi de la sélection
  (selectBlockByName nombloc)
)

;; SSBN (commande LISP)
;; Affiche en surbrillance (grips) le jeu de sélection de tous les blocs de l'espace courant
;; ayant le même nom que le bloc sélectionné.
(defun c:SSBN ()
  ;; affichage de la sélection
  (sssetfirst nil (ssbn))
  (princ)
)

 Les fonctions selectBlockByName et ssbn peuvent être appelées en réponse à une invite de commande "Sélectionner des objets: ".

Commande: _MOVE

Sélectionnez des objets: (ssbn)

Séléctionnez le bloc source: <Selection set: b1>
5 trouvé(s)

Sélectionnez des objets:

Spécifiez le point de base ou [Déplacement] <Déplacement>:
Spécifiez le second point ou <utiliser le premier point comme déplacement>:

 

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

Lien vers le commentaire
Partager sur d’autres sites

Coucou @(gile),

Une petite précision car j'avais pour habitude de travailler avec les fonctions (getpropertyvalue) et (setpropertyvalue) mais également avec des entités réseaux. Il faut se méfier de ces entités réseaux car elles sont sélectionnées par un simple

(ssget '((0 . "INSERT") (2 . "`*U*")))

et génère une erreur lors de l'utilisation de

(getpropertyvalue ent "BlockTableRecord/Name")

car cette propriété existe bel et bien pour les références de blocs standards et dynamiques mais pas pour les entités réseaux. J'avais donc tendance soit à vérifier la propriété ClassName

(if (wcmatch (getpropertyvalue ent "ClassName") "*Array*")
  ...
)

soit d'ignorer l'erreur via

(if (not (vl-catch-all-error-p (setq val (vl-catch-all-apply 'getpropertyvalue (list ent "BlockTableRecord/Name")))))
  ...
)

afin d'éviter toutes erreurs possibles en raison de ces entités délicates. Évidemment ces entités ne sont pas courantes dans tous les cœurs de métier, mais il me semblait important de préciser ce que j'ai pu apprendre à mes dépends.

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Merci pour ce rappel @Luna. Je me sers tellement peu de ces 'nouveaux' réseaux associatifs que je n'arrive pas à intégrer qu'ils sont aussi des blocs dynamiques...

Le dernier code corrigé avec une nouvelle fonction isAssociativeArray qui évalue si une entité est un réseau associatif.

;; isAssociativeArray
;; Renvoie T, si le ename passé en argument est celui d'un réseau associatif ; nil, sinon.
(defun isAssociativeArray (ename)
  (wcmatch (getpropertyvalue ename "ClassName") "AcDbAssociative*Array")
)

;; getEffectiveName (fonction LISP)
;; Obtient le nom effectif d'un bloc (dynamique ou statique)
;; Renvoie nil si ent n'est pas le ename d'un bloc
(defun getEffectiveName	(ent)
  (if
    (and
      (= (cdr (assoc 0 (entget ent))) "INSERT")
      (not (isAssociativeArray ent))
    )
    (getpropertyvalue
      (getpropertyvalue ent "BlockTableRecord")
      "Name"
    )
  )
)

;; selectBlockByName(fonction LISP)
;; Renvoie un jeu de sélection de tous les blocs (dynamiques ou statiques) de l'espace courant
;; dont le nom effectif correspond au nom passé en argument.
;; Renvoie niil si l'espace courant ne contient aucun bloc du nom spécifié ou dynamique.
(defun selectBlockByName (nombloc / ss i bloc)
  ;; sélection de tous les blocs
  (if (setq ss (ssget "_X"
		      (list
			(cons 0 "INSERT")
			(cons 2 (strcat nombloc ",`*U*"))
			(cons 410 (getvar 'ctab))
		      )
	       )
      )
    ;; filtre des blocs dynamiques suivant leur nom effectif
    (repeat (setq i (sslength ss))
      (setq bloc (ssname ss (setq i (1- i))))
      (if
	(or
	  (isAssociativeArray bloc)
	  (/= (strcat (getEffectiveName bloc))
	      (strcat nombloc)
	  )
	)
	(ssdel bloc ss)
      )
    )
  )
  ;; renvoi de la sélection
  ss
)

;; ssbn (fonction LISP)
;; Renvoie un jeu de sélection de tous les blocs (dynamiques ou statiques) de l'espace courant
;; ayant le même nom que le bloc sélectionné.
(defun ssbn (/ ent nombloc)
  ;; sélection du bloc source
  (while
    (not
      (and
	(setq ent (car (entsel "\nSéléctionnez le bloc source: ")))
	(setq nombloc (getEffectiveName ent))
      )
    )
     (prompt "Sélection non valide.")
  )
  ;; renvoi de la sélection
  (selectBlockByName nombloc)
)

;; SSBN (commande LISP)
;; Affiche en surbrillance (grips) le jeu de sélection de tous les blocs de l'espace courant
;; ayant le même nom que le bloc sélectionné.
(defun c:SSBN ()
  ;; affichage de la sélection
  (sssetfirst nil (ssbn))
  (princ)
)

 

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

Lien vers le commentaire
Partager sur d’autres sites

qui aurai pu prévoir...

🙂

 moi non plus j'utilise pas trop ces réseaux nouveaux, mais au passage, on est quand même à un niveau super pointu car, si j'ai bien compris, que ces blocs soit sélect ou pas par le  (strcat nombloc ",`*U*"), il sont retesté. C'est de l'optimisation fine algorithmique non?

Je suis, entendons nous bien, très sensible au travail bien fait, mais je m'attendait pas à ce qu'une simple question pour récupérer ma bidouille débouche sur un truc aussi abouti et optimisé

merci cadXP 

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é