Aller au contenu

Copie equidistante


Messages recommandés

Posté(e)

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élection

3- 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 bseb67

EDIT2 :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."

Posté(e)

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 bloquer

3- le nombre de copies équidistantes est interne, je m'explique: je choisi 5 copies, mais en fait

je me retrouve avec 6 fois mes éléments, celui qui à servi pour le point d'arrivée et donc 5 copies

entre 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...

Posté(e)

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."

Posté(e)

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...

Posté(e)

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."

Posté(e)

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 Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Posté(e)

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

 

./__\.
(.°=°.)
Posté(e)

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."

Posté(e)

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 Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Posté(e)

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

Posté(e)

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]

Posté(e)

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."

Posté(e)

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."

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é