Matt666 Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Bonjour tout le monde !Ca faisait longtemps... Bon voici une routine qui tourne très bien sur BricsCAD, et c'est en pur autolisp, donc ça devrait fonctionner sur AutoCAD. Je ne sais pas si elle a déjà été écrite ici. Ça ne m'étonnerait pas :) Cette routine est l'équivalent de la copie équidistante disponible dans SketchUP (et ArchiCAD je crois). Elle copie d'abord la sélection au point de destination définit par l'utilisateur, puis insère un nombre de copies voulues entre les deux, et ce avec le même écartement. Elle demande : 1- Une sélection si rien n'est sélectionné2- Un point de base de copie de la sélection3- Un point de destination de la première copie.4- Le nombre de copies équidistantes Et voilà. A savoir que le point 4 est en boucle. C'est à dire que si on voit que le nombre de copies est inexact (ou insuffisant, ou y en a trop...) la routine remplace les entités créées entre l'original et la première copie par le nombre à copier. Comme sur SketchUP. ;;; Copier à équidistance (defun c:CPE (/ *error* m:err sel ptb ptd cmdecho div dst ang entl dst2 entl2) (defun CPE_Error (msg) (if (= msg "Fonction annulée") (princ "\nAnnuler") (princ (strcat "\nErreur -> " msg)) ) (command "_.undo" "_end") (setvar "CMDECHO" cmdecho) (setq *error* m:err m:err nil ) (princ) ) (setq m:err *error* *error* CPE_Error) (if (and (setq sel (ssget)) (setq ptb (getpoint "\nPoint de base : ")) ) (progn (setq cmdecho (getvar "cmdecho")) (setvar "cmdecho" 0) (command "_undo" "D" "_copy" sel "" ptb) (setvar "cmdecho" 1) (while (not (zerop (getvar "cmdactive")))(command pause)) (setq ptd (getvar "lastpoint") dst (distance ptb ptd) ang (angle ptb ptd) entl (entlast) ) (setvar "cmdecho" 0) (if (> dst 0) (progn (while (setq div (getint "\nNombre de copies équidistantes : ")) (setq entl2 entl) (setq sel2 (ssadd)) (while (setq entl2 (entnext entl2)) (ssadd entl2 sel2)) (if sel2 (command "_erase" sel2 "")) (setq dst2 (/ dst div)) (repeat (1- div) (command "_copy" sel "" ptb (polar ptb ang dst2)) (setq dst2 (+ dst2 (/ dst div))) ) (princ (strcat "\n" (itoa div) " entités copiées avec entraxe de " (rtos (/ dst div)) " unités.")) ) (command "_undo" "F" "regen") ) (progn (princ "\nDistance entre l'original et le 1er objet copié nul. Fonction annulée.") (command "_undo" "F" "_undo" 1 "regen") ) ) (setvar "cmdecho" cmdecho) (setq *error* m:err m:err nil) ) ) (princ) ) Possibilités d'améliorations : - Donner une distance à la place du nombre de copies à créer.- Au niveau code, tout passer avec vl-cmdf (un truc comme ça), pour AutoCAD- Au niveau code, créer des marques d'annulation à chaque demande de nobmre de copies. Pour l'instant (et parce que c'est la seule méthode qui fonctionne bien sur BricsCAD) le code efface les entités puis les recrée. Les commentaires / remarques d'amélioration / Trouvailles de bugs sont les bienvenus ;) EDIT1 : Routine mise à jour suite aux commentaires de bseb67EDIT2 :Ajout d'une fonction d'erreur suite au commentaire de Patrick_35. Merci à toi et (gile) pour le coup de main sur la fonction d'erreur ! [Edité le 19/12/2008 par Matt666] "Chacun compte pour un, et nul ne compte pour plus d'un."
bseb67 Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Salut Matt666! Chez moi ca marche très bien, mais il y a des petits trucs :1- il demande deux fois le "point de base", au lieu de "point de base" et "point d'arrivée".2- on peut copier avec un déplacement de 0, à part faire le cochon dans le dessin, ce serai mieux de le bloquer3- le nombre de copies équidistantes est interne, je m'explique: je choisi 5 copies, mais en faitje me retrouve avec 6 fois mes éléments, celui qui à servi pour le point d'arrivée et donc 5 copiesentre le point de base et ce point. Sinon, je pense l'ajouter dans ma fonction de copie. Car travaillant avec des groupes,il faut que je rajoute dans le groupe existant les entités et non créer un nouveau groupe sans nom. [Edité le 18/12/2008 par bseb67] Tous pour lisp, Lisp pour tous!Avec Revit, cela ne vas trop vite...
Matt666 Posté(e) le 18 décembre 2008 Auteur Posté(e) le 18 décembre 2008 Salut bseb67 !Merci pour les retours... Les points 2 et 3 sont corrigés. Par contre le point 1, sur BricsCAD cela fonctionne très bien. Je ne peux pas corriger ce problème, désolé... Encore merci ! :D "Chacun compte pour un, et nul ne compte pour plus d'un."
bseb67 Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Re, En fait pour le 3, cela dépend de l'utilisateur, et puis j'ai relut le début du code:"Copier à équidistance entre l'original et la première copie" => c'est donc clair ;) et moi qui ne suit plus trop réceptif :P. Normal, c'est bientot les vacances, avec peut-être une nouvelle voiture pour noël pour moi :D ,et un tas de bredele qui m'attend à la maison (que j'ai fait ces deux derniers week-end) :cool: Tous pour lisp, Lisp pour tous!Avec Revit, cela ne vas trop vite...
Matt666 Posté(e) le 18 décembre 2008 Auteur Posté(e) le 18 décembre 2008 En fait j'ai regardé l'outil sur SketchUp, et il fait comme tu l'as décrit. J'ai donc modifié le code.Bon courage pour ton tas de bretzels... C'est salé comme humour... Bref.. "Chacun compte pour un, et nul ne compte pour plus d'un."
Patrick_35 Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Bonjour Très bien Matt666 :) Cela pourrait aussi être utile avec une insertion au lieu d'une copie. Une autre remarque. Dans ta commande _undo, tu utilises le paramètre D pour début. En international, c'est _begin ou _group.Idem pour F qui donne _end. J'ai remarqué tu avais oublié de déclarer la variable sel2 en local Une dernière est que tu ne gère pas les erreurs.Si par exemple, je fais un échapp pour terminer la commande, la variable cmdecho ne retrouve pas sa valeur initiale. Juste un bémol, je ne sais pas si les étudiants et lycéens apprécieront. Dominique de Villepin sûrement @+ Les Lisps de PatrickLe but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.Joseph Joubert, 1754-1824
Tramber Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Fana deSketch'Up que je suis, je suis pour ! Autre chose, ne pas oublier la commande originelle INSERM ! Bureau d'études dessin. Spécialiste Escaliers Développement - Formation ./__\. (.°=°.)
Matt666 Posté(e) le 18 décembre 2008 Auteur Posté(e) le 18 décembre 2008 Salut Patrick_35 !Ok pour la variable et les commande d'annulation, merci !Je n'ai jamais trop rien compris à la gestion des erreurs via LISP... Peut être une occasion d'éclaircissement ? :cool: Ce que je ne comprends pas, c'est le jeu des variables en début et en fin de lisp... Bref. Salut Tramber !Fana de Sketch'Up que je suis, je suis pour !Et c'est juste pour toi que je l'ai publiée, cette routine... :thumbup: Je me doutais bien que cela plairait aux SketchUsers... Je me sers tellement souvent de cet outil sur SU, fallait faire qqh pour AutoCAD :) Merci à vous ! "Chacun compte pour un, et nul ne compte pour plus d'un."
Patrick_35 Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Re Dès que tu fais un échapp, tu génères une erreur Tu as une fonction lisp qui s'appelle *error*On détourne cette fonction pour nos besoins, tout en conservant dans une variable l'origine(setq ancienne_erreur *error* *error* ma_gestion_des_erreurs) Je crée ma routine de gestion(defun ma_gestion_des_erreurs(msg) ... ... ... (setq *error* ancienne_erreur) ; je réaffecte la gestion des erreurs à l'origine (princ) ) Voilà le principe Un sujet à voir Autre chose, ne pas oublier la commande originelle INSERM !Pas aussi pratique, et de plus, on travail sur un rectangle sans tenir compte d'un angle (pas celui de l'insertion du bloc) @+ Les Lisps de PatrickLe but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.Joseph Joubert, 1754-1824
(gile) Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Salut, Je ne sais pas si BricsCAD a une fonction LISP *error*. Assure t'en d'abord en entrant : !*error* à la ligne de commande.Si le retour est du type : # c'est que c'est bon. *error* est une fonction LISP qui accepte 1 argument : le message d'erreur retourné.Cette fonction peut être redéfinie, il y a en gros 2 façons de faire suivant qu'on redéfinit la fonction à l'extérieur ou à l'intérieur du programme.Dans tous les cas, il faut limiter la portée de la fonction redéfinie à la routine de façon à ce qu'elle revienne à sa définition initiale après l'exécution du programme. Exemple 1 : definition d'une routine à l'extérieur du programme et redéfinition de *error* dans le programme. On note que la fin du programme et la fin de la routine MonErreur sont identiques. ;; la fonction de gestion des erreurs (defun MonErreur (msg) ;; affichage ou non du message d'erreur (if (= msg "Fonction annulée") (princ) (princ (strcat "\nErreur: " msg)) ) ;; Restauration de l'environnement (setvar "CMDECHO" cmdecho) (command "_.undo" "_end") ;; restauration de la fonction *error* (setq *error* m:err m:err nil ) (princ) ) ;; le programme (defun c:MonProgramme (/ cmdecho) ;; redéfinition de *error* (setq m:err *error* *error* MonErreur ) (command "_undo" "_begin") (setq cmdecho (getvar "CMDECHO")) ;; ici le corps du programe ;; Restauration de l'environnement (setvar "CMDECHO" cmdecho) (command "_.undo" "_end") ;; restauration de la fonction *error* (setq *error* m:err m:err nil ) (princ) ) Exemple 2 : on redéfinit la fonction *error* à l'intérieur du programme. Il est impératif de déclarer la fonction *error* en local pour limiter sa portée et elle retrouvera automatiquement sa valeur initiale à la fin du programme. (defun c:MonProgramme (/ *error* cmdecho) (defun *error* (msg) ;; affichage ou non du message d'erreur (or (= msg "Fonction annulée") (princ (strcat "\nErreur: " msg)) ) ;; Restauration de l'environnement (setvar "CMDECHO" cmdecho) (command "_.undo" "_end") (princ) ) (command "_undo" "_begin") (setq cmdecho (getvar "CMDECHO")) ;; ici le corps du programe ;; Restauration de l'environnement (setvar "CMDECHO" cmdecho) (command "_.undo" "_end") (princ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
usegomme Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Salut , voilà une petite leçon bien intéressante ! Mais il me semble que nos experts ont oublié une partie de tes interrogations. Ce que je ne comprends pas, c'est le jeu des variables en début et en fin de lisp... (defun c:CPE (/ sel ptb ptd cmdecho div dst ang entl dst2 entl2) En début de lisp derrière le "/" , elles sont définies temporaires et ne resteront pas en mémoire .A la fin c'est pour restaurer les paramètres originaux. Bon et bien on attend la suite Donner une distance à la place du nombre de copies à créer [Edité le 18/12/2008 par usegomme]
Matt666 Posté(e) le 18 décembre 2008 Auteur Posté(e) le 18 décembre 2008 Salut usegomme !Merci pour la précision, mais je connaissais déjà cela ;) ! Là je parlais des variables locales qui faisaient référence à la fonction d'erreur.. [Edité le 18/12/2008 par Matt666] "Chacun compte pour un, et nul ne compte pour plus d'un."
usegomme Posté(e) le 18 décembre 2008 Posté(e) le 18 décembre 2008 Suis-je bête ,j'aurai pu le comprendre en lisant ton lisp , c'est pas du "cargot".A+
Matt666 Posté(e) le 19 décembre 2008 Auteur Posté(e) le 19 décembre 2008 La routine a été mise à jour !Merci à Patrick_35 et (gile) pour l'aide sur la fonction d'erreur ! Ca fonctionne parfaitement. "Chacun compte pour un, et nul ne compte pour plus d'un."
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