-
Compteur de contenus
12 247 -
Inscription
-
Dernière visite
-
Jours gagnés
209
Type de contenu
Profils
Forums
Calendrier
Blogs
Tout ce qui a été posté par (gile)
-
Re, Je suis un peu honteux, je n'ai jamais essayé la légende automatique. Alors comme je ne sais pas si tu comptes les blocs insérés ou le bloc de la collection, j'ai fait pour les deux : Pour la collection : (vlax-for bloc (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)) ) (if ( (if (= (vla-get-IsDynamicBlock bloc) :vlax-true) (princ (strcat "\nLe bloc \"" (vla-get-Name bloc) "\" est un bloc dynamique" ) ) ) ) ) Pour tous les blocs insérés : (setq ss (ssget "_X" '((0 . "INSERT")))) (repeat (setq n (sslength ss)) (setq ref (vlax-ename->vla-object (ssname ss (setq n (1- n))))) (if ( (if (= (vla-get-IsDynamicBlock ref) :vlax-true) (princ (strcat "\nLe bloc \"" (vla-get-EffectiveName ref) "\" est un bloc dynamique" ) ) ) ) )
-
Salut Patrick_35, Ton LISP est encore une belle démonstration d'utilisation des réacteurs. Juste deux petites remarques, tu ne testes pas si le nouveau nom n'est pas déjà dans la collection, et pour les blocs dynamiques (anonymes) il faut récupérer le EffectiveName de la référence qui correspond au Name de la définition : (if (vlax-property-available-p ref 'EffectiveName) (setq name (vla-get-EffectiveName ref)) (setq name (vla-get-Name ref)) ) PS : J'ai failli te piquer ton "InputBox" pour mon LISP, je ne regrettes pas de t'en avoir laissé la primeur ;) [Edité le 7/8/2006 par (gile)]
-
Salut, Dans l'éditeur de bloc, tu spécifies les paramètres et les actions à ton bloc, puis tu enregitres (deuxième icone de la barre d'outils de l'éditeur "Enregistrer la définition du bloc") et tu fermes l'éditeur et ton bloc doit avoir aquis ses propriétés dynamiques. Si tu veux seulement modifier l'échelle de plusieurs blocs tu peux utiliser Edit_bloc. Télécharger Edit_bloc
-
Bien sûr ! Des fois je ne vois pas mon nez au milieu de ma figure ! Je te remercie pour le conseil d'utilisation de (sssetfirst), je ne connaissais pas cette incidence. Merci pour tout.
-
Salut, En attendant on peut toujours utiliser ce petit LISP qui permet la sélection de la référence avant le lancement de la commande (si PICKFIRST est à 1) et peut donc d'être glissé dans le Menu contextuel des objets de référence de bloc. http://img324.imageshack.us/img324/4304/renomblockc2.png Le code : ;;; Renomme le bloc sélectionné avant ou après le lancement de la commande (defun c:rename_block (/ AcDoc ss ref name new) (vl-load-com) (setq AcDoc (vla-get-ActiveDocument (vlax-get-acad-object))) (if (and (= 1 (getvar "pickfirst")) (setq ss (ssget "_I" '((0 . "INSERT")))) (eq 1 (sslength ss)) ) (sssetfirst nil nil) (progn (sssetfirst nil nil) (while (not (setq ss (ssget "_:S:E" '((0 . "INSERT"))))) ) ) ) (setq ref (vlax-ename->vla-object (ssname ss 0))) (if (vlax-property-available-p ref 'EffectiveName) (setq name (vla-get-EffectiveName ref)) (setq name (vla-get-Name ref)) ) (setq bloc (vla-item (vla-get-blocks AcDoc) name)) (while (not (and (setq new (getstring "\nSpécifiez le nouveau nom : ")) (not (tblsearch "BLOCK" new)) (/= new "") ) ) (if (tblsearch "BLOCK" new) (princ (strcat "\Le bloc \"" new "\" existe déjà.")) ) ) (vla-put-Name bloc new) (princ) ) [Edité le 7/8/2006 par (gile)]
-
Boucle d\'extraction attribut fixe dans bloc imbriqués
(gile) a répondu à un(e) sujet de Bred dans Débuter en LISP
Si ça t'intéresse, Un petit topo sur la récursivité ici. -
Il arrive qu'on parle ici ou là de "récursivité" ou de "fonctions récursives". Qu'en est il plus précisément ?... Comment ça se traduit en LISP ?... Je vais tenter de répondre à ces questions. Une fonction récursive est une fonction qui s'appelle elle même pendant son exécution. En LISP on reconnaît un fonction récursive à l'appel fait à elle même dans son DEFUN. L'exemple le plus souvent utilisé pour expliquer la récursivité est la fonction factorielle, petit rappel de math : Factorielle n s'écrit n! si n = 0 => n! = 1 et pour tout n > 0 => n! = n * (n - 1)! Par exemple : 4! = 4 * 3! = 4 * 3 * 2! = 4 * 3 * 2 * 1! = 4 * 3 * 2 * 1 = 24 En LISP, on peut écrire : (defun fact (n) (if (zerop n) 1 (* n (fact (1- n))) ) ) Une fonction définie récursivement contient au moins une condition d'arrêt : (zerop n) -> 1 et un appel récursif : (* n (fact (1- n))) Par exemple : (fact 4) sera interprété une première fois (* 4 (fact 3)), puis (* 4 (* 3 (fact 2))) etc,... jusqu'à (* 4 (* 3 (* 2 (* 1 (fact 0))))) où (fact 0) remplit la condition d'arrêt et retourne 1 On appelle "empilement" les appels successifs à la fonction jusquà la condition d'arrêt et "dépilement" leurs interprétations depuis cette condition. On peut voir la procédure dans la fenêtre de suivi de la console VisualLISP en "traçant" la fonction fact avec la fonction LISP trace : http://img155.imageshack.us/img155/4381/rcurs1ku8.png Du fait de l'utilisation de la pile, l'usage de fonctions récursives permet souvent de faire de manière plus élégante ce qui avec une boucle (while) aurait nécéssité l'utilisation d'une nouvelle variable pour stocker les résultats successifs. Par exemple la fonction fact définie de manière itérative, avec while : (defun fact (n / rslt) (cond (( (T (setq rslt n) (while ( (setq rslt (* rslt (setq n (1- n)))) ) ) ) ) L'usage de fonction récursives est aussi très pratique avec des listes. ;;; TRUNC Retourne la liste tronquée à partir de la première occurrence ;;; de l'expression (liste complémentaire de celle retournée par MEMBER) (defun trunc (expr lst) (cond ;; Conditions d'arrêt ((or (null lst) (equal (car lst) expr) ) nil ) ;; Appel récursif (T (cons (car lst) (trunc expr (cdr lst)))) ) ) http://img86.imageshack.us/img86/4333/rcurs2je6.png Pour comparaison, la fonction trunc définie de façon itérative : (defun trunc (elt lst / n rslt) (setq n 0) (while ;; Conditions d'arrêt (and ( (not (equal (nth n lst) elt)) ) (setq rslt (cons (nth n lst) rslt)) (setq n (1+ n)) ) ;; Résultat (reverse rslt) ) Les fonctions récursives ont aussi quelques inconvénients, la pile n'est pas infinie et ne permet qu'un certains nombre d'évaluations au-delà duquel la "limite de la pile interne atteinte" produit une erreur. D'après mes essais, cette limite semble être fixée à 19975 sur AutoCAD. On ne peut donc utiliser de fonction récursives sur des listes de plus de 19975 éléments. L'avantage de cet inconvénient est que si la condition d'arrêt n'est jamais remplie, on n'entre pas dans une boucle sans fin comme avec (while ...) On peut faire le test avec (fact -1) D'autre part, l'exécution des fonctions récursives semble plus lente que celle des fonctions itératives et ce d'autant plus que le nombre d'interprétations (hauteur de la pile) est important. Bien évidemment, tous les eventuels ajouts, remarques, corrections, questions sont les bienvenus. [Edité le 6/8/2006 par (gile)]
-
Salut Christian, Je pense que lecrabe fait référence à ce message.
-
Boucle d\'extraction attribut fixe dans bloc imbriqués
(gile) a répondu à un(e) sujet de Bred dans Débuter en LISP
Pour récupérer les blocs imbriqués quelque soit leur niveau d'imbrication, il faut explorer toutes les entités du bloc et tant que dans ces entités on trouve un bloc explorer les entités de ce bloc et ainsi de suite jusqu'à avoir fait le tour de toutes les entités de tous les blocs. Je ne vois que deux façon de faire : soit avec une liste contenant au départ le ou les blocs à traiter qu'on parcourt tant qu'elle contient des éléments. On traite le premier, s'il contient dans ses entité un (ou des) bloc(s), on le (ou les) rajoute à la fin de la liste et on supprime ce premier élément de la liste, puis on traite le second et ainsi de suite jusqu'à ce que la liste soit vide. soit on se sert d'une routine récursive, comme la routine de Bonuscad xplore. C'est peut-être un peu moins facile à comprendre mais à mon goût beaucoup plus élégant. Une fonction récursive est une fonction qui s'appelle elle même dans sa propre définition, chaque appel à la fonction s'ajoute au précédent provoquant un "empilement" et est évalué ensuite lors du "dépilement". Fais une recherche dans les forums avec "récurs" j'en ai parlé ailleurs (Bonuscad aussi) et je donne quelque exemples simples avec une fois l'utilisation de la fonction (trace ...) et de la fenêtre de suivi de l'éditeur VisualLISP pour voir l'empilement et le dépilement. Bonne nuit ... un lien vers un message qui contient d'autres liens. ou encoreici,, par exemple, la fonction TRUNC est définie de manière récursive. [Edité le 6/8/2006 par (gile)] -
Boucle d\'extraction attribut fixe dans bloc imbriqués
(gile) a répondu à un(e) sujet de Bred dans Débuter en LISP
Salut, Je n'ai pas tout suivi, mais tu peux esayer ça. J'ai un peu modifié la routine xplore de Bonuscad qui attaquait la boucle sur la deuxième entité du bloc (setq ent (entnext (cdar l))) pour que la première soit aussi traitée. ;;; la routine de Bonuscad modifiée (defun xplore (ent / l) (while ent (setq l (entget ent)) (if (eq (cdr (assoc 0 l)) "INSERT") (xplore (cdr (assoc -2 (tblsearch "BLOCK" (cdr (assoc 2 l))))) ) ) (if (eq (cdr (assoc 0 l)) "ATTDEF") (print (strcat "Etiquette = " (cdr (assoc 2 l)) " ; Valeur = " (cdr (assoc 1 l)) ) ) ) (setq ent (entnext ent)) ) ) ;;; Pour traiter les blocs d'un jeu de sélection (if (setq sel (ssget '((0 . "INSERT")))) (repeat (setq n (sslength sel)) (setq bloc (tblsearch "BLOCK" (cdr (assoc 2 (entget (ssname sel (setq n (1- n)))))) ) ) (if ( (progn (print (strcat "Bloc : " (cdr (assoc 2 bloc)))) (xplore (cdr (assoc -2 bloc))) ) ) ) ) -
J'ai aussi été étonné par le message de Didier, je n'ai que 2007 sur mon poste et n'ai remarqué aucun problème avec les xrefs. Je dois dire que je n'en a pas manipulé beaucoup ces derniers temps, si ce n'est pas mal de tests (charger/décharger, attacher/détacher) pour essayer de mettre au point certains LISP.
-
C'est lui qui a fixé la hauteur de la barre en choisissant son objectif ;)
-
Il peut être intéressant (d'ailleurs je l'ai fait parceque j'en ai eu besoin) d'inverser une sélection. Voici donc un petit LISP qui le fait, on peut taper inv_sel à la ligne de commande ou mettre la macro ^C^Cinv_sel; dans un bouton, ou dans le menu contextuel "Edition" : http://img149.imageshack.us/img149/1389/invselvw5.png Le LISP : (defun c:inv_sel (/ ssa ssf n e) (setq ssa (ssget "_A" '((0 . "~VIEWPORT")))) (if (setq ssf (cadr (ssgetfirst))) (repeat (setq n (sslength ssa)) (if (ssmemb (setq e (ssname ssa (setq n (1- n)))) ssf) (ssdel e ssa) ) ) ) (sssetfirst nil ssa) )
-
Re, J'ai oublié une chose, l'exemple précédent vaut si les polylignes qui servent à faire le polygone sont "ouvertes". Si les polylignes sont fermées, il faudra utiliser une autre méthode de sélection. Sélectionner toutes les polylignes strictement à l'intérieur de la poly la plus à l'extérieur (option WindowPolygon de ssget) et oter de ce jeu de sélection toutes les polylignes qui croisent la poly le plus à l'intérieur (option CrossingPolygon de ssget) Il faut donc faire 2 jeux de sélection (on suppose que ent à été décalée vers l'intérieur, decal_ent est à l'intérieur de ent) (setq ss1 (ssget "_WP" (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent) ) ) (list '(0 . "LWPOLYLINE")) ) ) (setq ss2 (ssget "_CP" (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget decal_ent) ) ) (list '(0 . "LWPOLYLINE")) ) ) Et oter de ss1 les entités contenues dans ss2, pour ce faire on parcours ss1 et on teste, pour chaque entité, si elle est présente dans ss2, si c'est le cas, on la supprime de ss1 : (setq n (sslength ss1)) ; nombre d'entités dans ss1 (repeat n ; Répète autant de fois (setq n (1- n)) ; Incrémentation de n pour l'index dans le jeu de sélection (setq e (ssname ss1 n)) ; Entité à l'index n dans ss1 (première entité : index 0) (if (ssmemb e ss2) ; Si e est membre de ss2 ... (ssdel e ss1) ; ... e est supprimé de ss1 ) ) Donc, avant tout, il faut interroger les propriétés de ent (ou decal_ent, c'est pareil) pour savoir si elle est ouverte ou fermée. On trouve ça dans la "liste entget" de l'entité (voir dans l'aide aux développeurs >> Référence DXF >> Section ENTITIES). Elle est dans le code de groupe dxf 70, la valeur est un code binaire, c'est la somme de plusieurs entiers qui sont des puissances de 2 (1 2 4 8 16 ...). Les fonction LISP boole, logang et logior permettent de tester la présence dans un entier quelconque d'un ou de plusieurs bits. L'expression : (logand 1 (cdr (assoc 70 (entget ent)))) retourne 1 si 1 est présent dans la valeur du code 70 de la liste entget de ent ou 0 sinon. On peut donc faire un test pour savoir si la polyligne (et celle créée par le décalage) est fermée ou non pour appliquer l'une ou l'autre méthode. (if (= (logand 1 (cdr (assoc 70 (entget ent)))) 1) (progn ;; Appliquer la deuxième méthode ) (progn ;; Appliquer la première méthode ) )
-
Re, Je viens de lire à nouveau cette histoire de faire marcher la molette hors de la fenêtre ici Edit : Oooops, erreur dans le message ci-dessus, en 2006 c'est déjà les CUI et plus les MNS. Donc dans la fenêtre "Personnaliser l'interface utilisateur" tu déroules l'arborescence "Raccourcis clavier", tu fais glisser/déposer la commande Régénérer (ou Régénérer tout) depuis la liste des commandes vers les "Touches de raccourci", tu sélectionnes la commande dans l'arborescence pour qu'elle s'affiche dans la partie de droite et là, tu cliques dans la case "Touche(s)" puis sur l'icone avec "..." qui s'affiche, et dans la boite de dialogue , tu spécifies la touche (ou combinaison de touches) à affecter à la commande. [Edité le 5/8/2006 par (gile)]
-
Ça fait plusieurs fois que je remarque que je n'ai pas droit à ma tasse de café (icône dans la fenêtre "Membres en lignes") quand je viens dans le salon. Et comme j'y suis seul, je me demande si tout fonctionne bien chez moi ?
-
Salut, Je m'immisce dans la leçon. Pour faire un jeu de sélection, on utilise la fonction ssget. Cette fonction comporte beaucoup d'options, donc de possibilités pour faire la sélection et pour filtrer le type d'entités sélectionnées. Dans ton cas, par exemple si tu veux sélectionner toute le polylignes (on va dire les poly optimisées seulement) strictement entre les deux poly. Tu vas choisir l'option de sélection WP (window polygon), ça sera le premier argument pour la fonction ssget, qui sélectionne toutes les entités entièrement à l'intérieur du polygone défini par une liste de points. La difficulté va être de constituer la liste de points (ça sera le second argument pour la fonction ssget) à partir des sommets des deux polylignes (ent et decal_ent on suppose que tu as fait un : (setq decal_ent (entlast)) après le décalage pour stocker le nom d'entité -ename- de la poly créée dans la variable decal_ent). La formule magique pour récupérer es sommets d'une lwpolyligne est : (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget lwpolyline))) Elle est expliquée en détail ici dans notre cas on sait maintenant faire la liste des sommets de chacune des polylignes mais pour "dessiner" notre polygone de sélection il ne faut qu'une liste et inverser l'ordre des sommets pour un des deux polyligne. La fonction append "assemble plusieurs liste en une seule et la fonction reverse inverse l'ordre des éléments d'une liste. Pour constituer la liste des sommets du polygone on peut donc écrire : (setq pt_lst (append (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget ent))) (reverse (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) (entget decal_ent)))) ) ) Tu vas aussi filtrer les lwpolylines pour ne sélectionner que ce type d'entité. C'est le troisième argument pour la fonction ssget. Ce doit être une liste dont les éléments sont aussi des liste (ou paires pointées) telle que ceux constituant les listes retournées par la fonction entget. chaque élément contient un "code de groupe dxf" et sa valeur. Ici : (list '(0 . "LWPOLYLINE")) pour ne sélectionner que les entités "polyligne". On peut maintenant faire notre jeu de sélection : (setq jeu_sel (ssget "_WP" pt_lst (list '(0 . "LWPOLYLINE")))) Voilà, je pense que tu as de quoi cogiter ;) N'hésite pas à consulter l'aide : si tu travailles avec l'éditeur VisualLISP, ce que je te recommande fortement il suffit de sélectionner une fonction -double-clic sur le nom de la fonction- puis de cliquer sur l'icône avec un point d'interrogation. Tu peux aussi voir les fonctions décrites en français ici.
-
Non, il s'agit de surfaces, donc sans épaisseur... Pour les feuillets fins, on doit pouvoir ne faire qu'un développé à l'axe du feuillet (fibre neutre), pour les plus épais il faudrait en faire un par face (ceux des "joints de colle" servant 2 fois). À première vue, le plus rapide serait de faire un solide par feuillet (soit un bloc par feuillet et d'utiliser le même chemin), puis de "copier des arrêtes" (édition de solides) pour faire les surfaces gauches et les développés.
-
Aide pour macro insertion automatique de présentation
(gile) a répondu à un(e) sujet de Autocadiens dans AutoCAD LT 2004
Au temps pour moi ! De toutes façon, je fais partie de ceux qui pensent qu'il est toujours préférable d'utiliser le noms de commande en langage international (en macro comme en LISP). -
Aide pour macro insertion automatique de présentation
(gile) a répondu à un(e) sujet de Autocadiens dans AutoCAD LT 2004
Salut Yohann, Je n'ai pas suivi de très prés ce sujet, mais il me semble que l'ouverture ou non des boites de dialogue n'est pas du à l'utilisation du nom de commande en français ou en international (avec underscore) mais à la présence du tiret "-" (celui de la touche 6). -présentation fonctionne comme _-layout et empèche l'ouverture des dialogue. -
Salut, Il me semble me souvenir que sur les versions 2002 -> 2006 je le faisais par la fenêtre "Personalisation" onglet "Raccourcis clavier". Sinon, dans ton fichier .mns, section ACCELERATORS tu ajoutes : ID_Regen ["F4"] ou ID_Regenall ["F4"] La syntaxe : ["F4"]^C^C_regenall devrait fonctionner aussi.
-
Pour JL Pour les développés, j'avais fait un LISP ici, qui fait le dévellopé de surfaces réglées (contrairement au titre du sujet il fait aussi un développé -faux- des surfaces réglées non-développables, je ne suis pas assez fort en math pour arriver à filtrer les surfaces développables). Cela demanderais, pour ton usage, de faire une surface réglée pour les faces intérieure et extérieure de chaque limon (ou pour chaque feuillets), de les développer avec le LISP et de les imprimer à l'échelle 1 sur un traceur à rouleau.
-
Je copie ici le code en question, issu du Forum Autodesk - Discussion Groups Discussion Groups Index > AutoCAD Groups > Visual LISP, AutoLISP and General Customization Issues > How to distingu a close polyline is clockwise direction or counter-clockwise ? Patrick, si tu y vois un inconvenient, tu peut supprimer le message, il restera le lien ci dessus. ;Reverse "LWPOLYLINE" (defun c:rlw (/ E LW X1 X2 X3 X4 X5 X6) ; Writer Evgeniy Elpanov. (if (and (setq lw (car (entsel "\nSelect lwpolyline"))) (= (cdr (assoc 0 (setq e (entget lw)))) "LWPOLYLINE") ) ;_ and (progn (foreach a1 e (cond ((= (car a1) 10) (setq x2 (cons a1 x2))) ((= (car a1) 40) (setq x4 (cons (cons 41 (cdr a1)) x4))) ((= (car a1) 41) (setq x3 (cons (cons 40 (cdr a1)) x3))) ((= (car a1) 42) (setq x5 (cons (cons 42 (- (cdr a1))) x5))) ((= (car a1) 210) (setq x6 (cons a1 x6))) (t (setq x1 (cons a1 x1))) ) ;_ cond ) ;_ foreach (entmod (append (reverse x1) (append (apply (function append) (apply (function mapcar) (cons 'list (list x2 (cdr (reverse (cons (car x3) (reverse x3)))) (cdr (reverse (cons (car x4) (reverse x4)))) (cdr (reverse (cons (car x5) (reverse x5)))) ) ;_ list ) ;_ cons ) ;_ apply ) ;_ apply x6 ) ;_ append ) ;_ append ) ;_ entmod (entupd lw) ) ;_ progn ) ;_ if ) ;_ defun
-
Bonuscad avait déjà attiré mon attention sur la pureté du style des LISP de Elpanov Evgeniy ici ou là. Si les routines pour inverser les sommets d'une polyligne ne sont pas rares sur le net et que j'étais plutôt assez fier de ce que j'avais écris, celle que donne Elpanov (ou Yelpanov ?)dans ce sujet me laisse carrément sans voie ! J'ai refait le lien ... [Edité le 3/8/2006 par (gile)]
