krunch Posté(e) le 8 mai 2009 Posté(e) le 8 mai 2009 Bonjour à tous Pour des raisons compliquées, je dois utiliser (ssget "_P").Seulement dans le cas où la sélection utilisateur est vide, cette fonction renvoie tout de même le jeu de sélection précédent au lieu d'un jeu vide... Y a t-il un moyen de purger la sélection précédente ?J'ai essayé (gc) et (vla-update(vlax-get-acad-object)), ça ne marche pas..
bonuscad Posté(e) le 8 mai 2009 Posté(e) le 8 mai 2009 Bonjour, Je ne pense pas qu'il soit possible de réinitialisé le jeux de sélection "Précédent". Il te faut contrôler tes propres jeux de sélection dans ton code. (ssadd) sans argument de nom d'entité va te créer un jeu vide. Par exemple (setq js (ssadd)) JS sera vide! A partir de là, dans ton code tu pourra ajouter (ou enlever) des entités dans ton jeu de sélection Un exemple possible (sans voir de code, difficile de t'orienter) ((lambda ( / js js_tmp n) (setq js (ssadd)) (setq js_tmp (ssget)) (if js_tmp (repeat (setq n (sslength js_tmp)) (setq js (ssadd (ssname js_tmp (setq n (1- n))) js)))) (sssetfirst nil js) )) Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius
krunch Posté(e) le 8 mai 2009 Auteur Posté(e) le 8 mai 2009 Merci pour le rappel (ssadd), mais comme je disais je dois utiliser (ssget "_P") au lieu d'un ssget 'normal' (c'est après un appel de commande).La différence est que si la sélection est vide, (ssget) renvoie nil alors que (ssget "_P") renvoie la sélection d'avant, qui n'a rien à voir..
bonuscad Posté(e) le 9 mai 2009 Posté(e) le 9 mai 2009 Extrait de l'aide sur la sélection: PrécédentSélectionne le jeu de sélection le plus récent. Le jeu de sélection Précédent est effacé par toutes les opérations supprimant des objets du dessin. Le programme mémorise l'espace dans lequel chaque jeu de sélection a été défini : espace papier ou espace objet. Le jeu de sélection Précédent n'est pas pris en compte si vous changez d'espace. Ce qui laisserai penser que si dans ton code tu crée une entité dans l'espace courant. Un point par exemple par (entmake) ou autre puis que tu fasse (entdel (entlast)), le jeu de sélection "Précédent" serait alors remis à nil (vide) Essayé rapidement et effectivement ça à l'air de fonctionner. Je pense quand même qu'il faut s'assurer que le calque en cours ne soit pas verrouillé (pas testé). Je pense aussi que c'est la seule voie à creuser pour répondre a ta question. Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius
krunch Posté(e) le 10 mai 2009 Auteur Posté(e) le 10 mai 2009 Merci, je n'avais pas pensé à regarder dans l'aide général.. Par contre.. ça ne marche pas chez moi.J'ai testé avec ce code qui renvoie le 1er objet de (ssget "_P") avant et après création point.. chez moi ça ne purge pas ((lambda() (print (ssname (ssget "_P") 0)) (entmake '((0 . "POINT") (10 0.0 0.0 0.0))) (entdel (entlast)) (print (ssname (ssget "_P") 0)) (princ) ))
(gile) Posté(e) le 10 mai 2009 Posté(e) le 10 mai 2009 Salut, Je ne comprends pas ce qui peut "t'obliger" à utiliser (ssget "_P").Si tu assignes à une variable le jeu de sélection précédent :(setq ss (ssget))tu peux toujours vérifier si le jeu de sélection est vide :(if ss ...) Tu dis y être obligé après un appel de commande, cet appel fait-il parti de ton programme ?ou le lancement du programme est provoqué par l'appel (réacteur) ? Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
bonuscad Posté(e) le 10 mai 2009 Posté(e) le 10 mai 2009 Par contre.. ça ne marche pas chez moi. En fait avec (entdel) cela ne fonctionne pas aussi chez moi. Cette fonction (entdel) est un peu particulière en lisp. En effet elle peut aussi restorer une entité supprimé tant que le nom de l'entité n'est pas perdu (sauvé dans une variable et durant l'édition du dessin en cours)Est aussi il est bien spécifié dans l'aide de entdel que l'on ne peut pas effacer une entité complexe.Cela montre bien que cette commande ne peut pas avoir de bons effets sur par exemple un bloc ou une ancienne polyligne qui seraient dans le jeu de sélection précédent. Ceci explique cela ! :P Si tu utilises la commande SELECT choisis des objets et applique le code suivant en mettant la commande ENTMAKE et ERASE en remarque (rem => ";" en début de ligne), tu verras que les grips sont activés sur la sélection précédente.Refais la même démarche mais sans les rems, le jeux de sélection précèdent sera vide. ((lambda() (entmake '((0 . "POINT") (10 0.0 0.0 0.0) (60 . 1))) (setvar "CMDECHO" 0) (command "_.erase" "_last" "") (setvar "CMDECHO" 1) (sssetfirst nil (ssget "_P")) (prin1) )) Peut être qu'une commande VLA serait plus efficace que (entdel) et plus élégant que (command), pas testé.... Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius
krunch Posté(e) le 11 mai 2009 Auteur Posté(e) le 11 mai 2009 Encore merci Bonuscad, ça m'a effectivement l'air de marcher comme ça. Je l'ai refait avec vla-delete et toujours avec (print(ssget"_P")) avant/après, ça donne ça (pas sûr que ce soit mieux)... ((lambda() (print (ssget "_P")) (entmake '((0 . "POINT") (10 0.0 0.0 0.0) (60 . 0))) (vla-delete (vlax-ename->vla-object (ssname(ssget "_L")0))) (print (ssget "_P")) (princ) )) Pour voir la "purge" de (ssget"_P") il faut d'abord éditer un objet avec une commande (et non pas un déplacement par saisie)D'autre part si on remplace (ssname(ssget "_L")0) par (entlast) ça ne marche plus.Tout ça est plutôt curieux.. et confirme qu'il faut parfois aller chercher des solutions relativement tordues... Pour répondre aux questions de gile.. il s'agit bien de récupérer les objets traités par un appel de commande, l'appel est lancé par mon programme et la récupération (ssget"_P") est lancée par un réacteur commandEnded.. compliqué..
(gile) Posté(e) le 11 mai 2009 Posté(e) le 11 mai 2009 Salut, Si l'appel de la commande est lancé depuis un programme, tu peux assigner le jeu de sélection à une variable globale :(setq *selset* (ssget))(command ... *selset* ....) Puis dans la fonction callback de ton réacteur, tester la validité du jeu de sélection et le supprimer après usage :(if *selset* ...) (setq *selset* nil) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 11 mai 2009 Auteur Posté(e) le 11 mai 2009 Oui.. mais non : la sélection est faites par la commande justement, d'où le (ssget"_P") placé après. Et donc avec (ssget"_P") il faut purger avant pour le cas d'une sélection vide...
(gile) Posté(e) le 11 mai 2009 Posté(e) le 11 mai 2009 Si tu donnais un peu plus de détails, on pourrait peut-être t'aider mieux. Des fois on se focalise tellement sur ce qu'on pense être le problème qu'on ne peut voir une solution qui le contournerait.C'est quoi la commande ?Avec quelle fonction est elle appelée (command ou vl-cmdf) ? Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 11 mai 2009 Auteur Posté(e) le 11 mai 2009 Si je te dis quel est la commande tu vas me trouver encore plus tordu.. en fait la commande est un SELECT ! Alors voilà ce que je veux faire..Le déroulement de la commande est comme celui de _pedit par exemple : quand tu survoles une entité elle est highlightée , et quand tu cliques dessus elle est traitée.. (bref la structure est une boucle grread).Pour pouvoir traiter plusieurs objets il y a une option Multiple... mais ce que je veux en plus, qui n'est pas dans _pedit, et qui s'avère très pratique et très immédiat à l'usage... c'est qu'on puisse aussi sélectionner les entités (multiples) simplement en cliquant sur du vide : si tu cliques à côté d'un objet tu lances une sélection normale.Or comment faire ça ? Il n'y a pas d'option (ssget) qui permette de faire une sélection normale (windows-capture..) en spécifiant juste le 1er point et en attendant le 2è, pas que je sache... Voilà pourquoi je suis parti sur cet appel de commande* "_SELECT" avec toutes les complications qui s'en suivent : c'est pour faire (command "_SELECT" pt0) ! Si tu as plus simple je suis preneur.. * pour ce qui est de command ou vl-cmdf, je ne connais pas la différence en fait
(gile) Posté(e) le 11 mai 2009 Posté(e) le 11 mai 2009 J'avais fait une simulation des fenêtres de sélection avec grread. La fonction gr-sel-display requiert un argument : un point dans le SCU courant qui sert de base à la fenêtre. Elle retourne un liste dont le premier élément est le mode de sélection (capture ou fenêtre) et les autres les sommets de la fenêtre.Pour un fonctionnement cohérent quelle que soit la vue courante (vues 3d) certaines conversions de coordonnées sont nécessaires ainsi que la routine ilp. On peut utiliser la liste retourner par gr-sel-display pour faire une sélection avec ssget comme dans l'exemple suivant. (defun c:test (/ pt gsd ssmod) (and (setq pt (getpoint "\nPremier coin: ")) (setq gsd (gr-sel-display pt)) (setq ss (ssget (car gsd) (cdr gsd))) (sssetfirst ss ss) ) (princ) ) La fonction gr-sel-display ;| gr-sel-display (gile) Utilisation de grread pour simuler une fenêtre de sélection Argument : un point (coordonnées SCU courant) Retour : une liste dont le premier élément correspond au mode de sélection ("_CP" ou "_WP") et les éléments suivants les sommets de la fenêtre (coordonnées SCU courant) Exemple d'utilisation : (setq pt (getpoint) gsd (gr-sel-display pt) ss (ssget (car gsd) (cdr gsd)) ) |; (defun gr-sel-display ( pt1ucs / gr pt1ucs pt2ucs pt3ucs pt4ucs pt1view pt2view pt3view pt4view ssmode result) (while (and (setq gr (grread T 12 0)) (/= (car gr) 3)) (redraw) (setq pt3ucs (cadr gr) pt1view (trans pt1ucs 1 2) pt3view (trans pt3ucs 1 2) pt2view (list (car pt3view) (cadr pt1view) (caddr pt1view)) pt4view (list (car pt1view) (cadr pt3view) (caddr pt3view)) pt2ucs (trans (ilp pt2view (mapcar '+ pt2view '(0 0 1)) (trans '(0 0 0) 1 2) (trans '(0 0 1) 1 2 T) ) 2 1 ) pt4ucs (trans (ilp pt4view (mapcar '+ pt4view '(0 0 1)) (trans '(0 0 0) 1 2) (trans '(0 0 1) 1 2 T) ) 2 1 ) ssmode (if ( "_CP" "_WP" ) ) (grvecs (list (if (= ssmode "_CP") -255 255 ) pt1ucs pt2ucs pt2ucs pt3ucs pt3ucs pt4ucs pt4ucs pt1ucs ) ) ) (redraw) (list ssmode pt1ucs pt2ucs pt3ucs pt4ucs) ) ;; VXV ;; Retourne le produit scalaire (réel) de deux vecteurs ;; ;; Arguments : deux vecteurs (defun vxv (v1 v2) (apply '+ (mapcar '* v1 v2))) ;; ILP (gile) ;; Retourne le point d'intersection de la droite définie par p1 p2 ;; et du plan défini par un point et sa normale. ;; ;; Arguments ;; p1 et p2 : les points définissant la droite dont on cherche l'intersection ;; org : un point quelconque du plan d'intersection ;; nor : le vecteur normal du plan d'intersection (defun ilp (p1 p2 org nor / scl) (if (and (/= 0 (setq scl (vxv nor (mapcar '- p2 p1)))) (setq scl (/ (vxv nor (mapcar '- p1 org)) scl)) ) (mapcar (function (lambda (x1 x2) (+ (* scl (- x1 x2)) x1))) p1 p2 ) ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 11 mai 2009 Auteur Posté(e) le 11 mai 2009 En effet c'est efficace, et ça peut être ça..Ton code* a l'avantage de ne pas sortir de la boucle (de ne pas perdre les variables), et le principal inconvénient est juste qu'on n'a pas le vert-bleu de la capture ! Merci beaucoup, je vais voir si je vais pas l'intégrer vu que ça marche toujours à moitié mon bricolage à réacteurs... * ajouter l'argument à l'appel (gr-sel-display) et ajouter la fonction vxv __________________Question: mais pourquoi projeter (ilp) sur le plan de la vue pour obtenir les points de (ssget) ? [Edité le 11/5/2009 par krunch]
(gile) Posté(e) le 11 mai 2009 Posté(e) le 11 mai 2009 Question: mais pourquoi projeter (ilp) sur le plan de la vue pour obtenir les points de (ssget) ? grread retourne des coordonnées SCU et la liste de points requises par ssget sont aussi des coordonnées SCU mais si le SCU courant n'est pas parallèle à la vue la fenêtre de sélection ne sera pas rectangulaire.Pour avoir une fenêtre rectangulaire il faut calculer les coordonnées des 4 sommets dans le SCU courant de façon à ce qu'ils affichent un rectangle dans la vue. Ceci nécessite de tradure le point de base et celui retourné par grread en "coordonnées vue" (trans pt 1 2), puis de calculer les 2 autres sommets pour avoir un rectangle en coordonnées vue. Les coordonnées SCU de ces deux points sont leur projection sur le plan du SCU courant, on les obtient avec ILP. Si j'ai bien compris ce que tu veux faire, voici une fonction qui crée un jeu de sélection avec grread. Si l'utilisateur commence par sélectionner une entité avec un clic, la sélection s'arrête et le jeu de sélection ne contenant que cette entité est retourné. S'il commence par une fenêtre ou une capture la sélection continue jusqu'à validtion. Pendant la sélection, cliquer sur une entité sélectionnée, la dé sélectionne. ;; SelOneOrMore (gile) ;; Créé un jeu de sélection d'une ou plusieurs entités. ;; Si l'utilisateur commence par sélectionner une entité en 1 clic, ;; la sélection s'arrête, s'il commence par une fenêtre la sélection ;; continue jusqu'à la validation. cliquer sur une entité déjà sélectionner ;; la retire du jeu de sélection. ;; ;; Arguments ;; msg : un message ou nil (defaut "Choix des objets: ") ;; fltr : un filtre de sélection ou nil (defun SelOneOrMore (msg fltr / *error* gr-sel-one gr-sel-more sel gsm ent ss n del) (defun *error* (msg) (or (= msg "Fonction annulée") (princ (strcat "\nErreur: " msg)) ) (if (and sel (= (type sel) 'PICKSET)) (repeat (setq n (sslength sel)) (redraw (ssname sel (setq n (1- n))) 4) ) ) (if ss (repeat (setq n (sslength ss)) (redraw (ssname ss (setq n (1- n))) 4) ) ) (if ss1 (redraw (ssname ss1 0) 4) ) (princ) ) (defun gr-sel-one (fltr / loop gr pt ss1) (setq loop T) (while (and (setq gr (grread T 12 2)) (/= (car gr) 3) loop) (if ss1 (progn (setq ent (ssname ss1 0)) (or (and ss (ssmemb ent ss)) (redraw ent 4)) (setq ss1 nil) ) ) (cond ((= (car gr) 5) (setq pt (cadr gr)) (if (and (setq ss1 (ssget pt fltr)) (not del)) (redraw (ssname ss1 0) 3) (setq del nil) ) ) ((or (member gr '((2 13) (2 32))) (or (= (car gr) 11) (= (car gr) 25)) ) (if ss1 (progn (redraw (ssname sel 0) 4) (setq ss1 nil) ) ) (setq loop nil pt nil ) ) ) ) (if pt (cond ((setq ss1 (ssget pt fltr)) (redraw (ssname ss1 0) 4) ss1 ) (pt) ) ) ) (defun gr-sel-more (pt1ucs / gr pt2ucs pt3ucs pt4ucs pt1view pt2view pt3view pt4view ssmode result ) (while (and (setq gr (grread T 12 0)) (/= (car gr) 3)) (redraw) (setq pt3ucs (cadr gr) pt1view (trans pt1ucs 1 2) pt3view (trans pt3ucs 1 2) pt2view (list (car pt3view) (cadr pt1view) (caddr pt1view)) pt4view (list (car pt1view) (cadr pt3view) (caddr pt3view)) pt2ucs (trans (ilp pt2view (mapcar '+ pt2view '(0 0 1)) (trans '(0 0 0) 1 2) (trans '(0 0 1) 1 2 T) ) 2 1 ) pt4ucs (trans (ilp pt4view (mapcar '+ pt4view '(0 0 1)) (trans '(0 0 0) 1 2) (trans '(0 0 1) 1 2 T) ) 2 1 ) ssmode (if ( "_CP" "_WP" ) ) (grvecs (list (if (= ssmode "_CP") -255 255 ) pt1ucs pt2ucs pt2ucs pt3ucs pt3ucs pt4ucs pt4ucs pt1ucs ) ) ) (redraw) (list ssmode pt1ucs pt2ucs pt3ucs pt4ucs) ) (or msg (setq msg "\nChoix des objets: ")) (princ msg) (setq sel (gr-sel-one fltr)) (if (vl-consp sel) (progn (setq ss (ssadd)) (princ "\nSpécifiez le coin opposé: ") (setq gsm (gr-sel-more sel)) (if (setq sel (ssget (car gsm) (cdr gsm) fltr)) (repeat (setq n (sslength sel)) (setq ent (ssname sel (setq n (1- n)))) (redraw ent 3) (ssadd ent ss) ) ) (while (and (princ msg) (setq sel (gr-sel-one fltr))) (if (vl-consp sel) (progn (princ "\nSpécifiez le coin opposé: ") (setq gsm (gr-sel-more sel)) (if (setq sel (ssget (car gsm) (cdr gsm) fltr)) (repeat (setq n (sslength sel)) (setq ent (ssname sel (setq n (1- n)))) (redraw ent 3) (ssadd ent ss) ) ) ) (progn (setq ent (ssname sel 0)) (if (ssmemb ent ss) (progn (redraw ent 4) (ssdel ent ss) (setq del T)) (progn (redraw ent 3) (ssadd ent ss)) ) ) ) ) ) (setq ss sel) ) (repeat (setq n (sslength ss)) (redraw (ssname ss (setq n (1- n))) 4) ) ss ) ;; VXV ;; Retourne le produit scalaire (réel) de deux vecteurs ;; ;; Arguments : deux vecteurs (defun vxv (v1 v2) (apply '+ (mapcar '* v1 v2))) ;; ILP Retourne le point d'intersection de la droite définie par p1 p2 ;; et du plan défini par un point et sa normale. ;; ;; Arguments ;; p1 et p2 : les points définissant la droite dont on cherche l'intersection ;; org : un point queconque du plan d'intersection ;; nor : le vecteur normal du plan d'intersection (defun ilp (p1 p2 org nor / scl) (if (and (/= 0 (setq scl (vxv nor (mapcar '- p2 p1)))) (setq scl (/ (vxv nor (mapcar '- p1 org)) scl)) ) (mapcar (function (lambda (x1 x2) (+ (* scl (- x1 x2)) x1))) p1 p2 ) ) ) Une fonction test (defun c:test () (sssetfirst nil (SelOneOrMore "\nSélectionnez les blocs: " '((0 . "INSERT")) ) ) (princ) ) PS : je corrige le code donné plus haut Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 13 mai 2009 Auteur Posté(e) le 13 mai 2009 Alors oui mais ça ne marche qu'avec les blocs chez moi, pas avec les entités... J'avoue que je n'ai pas cherché pourquoi, de toutes façons je vois le principe, et c'est vrai que ça évite un réacteur pour (command "SELECT") Sinon pour la projection j'avais bien compris que c'était pour le traçage du rectangle de capture, mais j'avais cru que les points projetés partaient aussi dans (ssget). Merci beaucoup pour tes efforts
(gile) Posté(e) le 13 mai 2009 Posté(e) le 13 mai 2009 Salut, Alors oui mais ça ne marche qu'avec les blocs chez moi, pas avec les entités... La fonction SelOneOrMore accepte 2 arguments:- le message qui s'affichera sur la ligne de commande- un filtre de sélection : une liste comme celles utilisées avec ssget Dans l'exemple, le filtre de sélection est '((0 . "INSERT")) c'est pour ça qu'on ne peut sélectionner que des références de blocs. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
(gile) Posté(e) le 14 mai 2009 Posté(e) le 14 mai 2009 Salut, Merci beaucoup pour tes efforts J'ai à peine modifié des routines que j'avais fait.Je trouve quand même que c'est un peu lourd pour juste éviter un clic dans le vide (ou un clic gauche). (defun c:toto (/ ss) (princ "\nSélectionnez un objet ou ") (setq ss (cond ((ssget "_+.:S:E")) ((ssget)))) (sssetfirst nil ss) (princ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 14 mai 2009 Auteur Posté(e) le 14 mai 2009 Toto utilise le renvoie (ssget) de façon très futée..Mais ce n'est pas tout à fait ça : quand tu cliques dans le vide il faut recliquer ensuite pour faire une sélection multiple, or ce que je veux c'est que ton clic vide soit déjà le 1er point d'une sélection multiple. A priori (je l'ai pas intégré encore) ça peut marcher avec ta fonction (SelOneOrMore), il suffit d'ajouter un test sur le 1er pointage : (if (not(ssget "_S" pt0)) (SelOneOrMore pt0)) Je bricole une commande qui marche par défaut en sélection unique (selon un déroulement comparable à celui de _pedit par exemple). Eh bien dans ce cas je confirme que ce "raccourci" est diablement pratique, tu peux quasiment supprimer l'option M..[Edité le 14/5/2009 par krunch] [Edité le 14/5/2009 par krunch]
(gile) Posté(e) le 14 mai 2009 Posté(e) le 14 mai 2009 Mais ce n'est pas tout à fait ça : quand tu cliques dans le vide il faut recliquer ensuite pour faire une sélection multiple, or ce que je veux c'est que ton clic vide soit déjà le 1er point d'une sélection multiple. C'est bien ce que je disais : "Je trouve quand même que c'est un peu lourd pour juste éviter un clic dans le vide (ou un clic gauche)." ça peut marcher avec ta fonction (SelOneOrMore), il suffit d'ajouter un test sur le 1er pointage :(if (not(ssget "_S" pt0)) (SelOneOrMore pt0)) Pas besoin d'ajouter de test SelOneOrMore fait exactement ce que tu décris et retourne le jeu de sélection.Essaye (SelOneOrMore nil nil) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
krunch Posté(e) le 14 mai 2009 Auteur Posté(e) le 14 mai 2009 Pas besoin d'ajouter de test SelOneOrMore fait exactement ce que tu décris et retourne le jeu de sélection.Essaye (SelOneOrMore nil nil) Il manque une parenthèse finale dans SelOneOrMore. Sinon c'est tout à fait ça.. Et je confirme qu'à l'usage c'est un (petit) raccourci qui fait que tu ne te sers plus du tout de l'option M..
(gile) Posté(e) le 14 mai 2009 Posté(e) le 14 mai 2009 Il manque une parenthèse finale dans SelOneOrMore Non.Ça doit être un problème de copier/coller. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant