-
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)
-
[Résolu] Petit problème avec l'IDE Visual LISP pour AutoCAD
(gile) a répondu à un(e) sujet de DenisHen dans LISP et Visual LISP
Salut, C'est un problème avec les systèmes 64 bits et Windows 7 (et peut-être ultérieurs). Le message d'avertissement suivant s'affiche dans la console : C'est parce que le dossier C:/Program Files/Autodesk/AutoCAD 201X est en lecture seule pour les Utilisateurs que Visual LISP ne peut pas créer de fichier DCL temporaire. Si tu as des droits Administrateur sur ton poste, tu peux modifier les paramètres de sécurité des Utilisateurs pour ce dossier en cochant Modification et Écriture. -
Salut, Essaye ça: (defun c:text2block (/ txt bname ss i) (vl-load-com) (defun *error* (msg) (and msg (/= msg "Fonction annulée") (princ (strcat "\nErreur: " msg)) ) (vla-EndUndoMark doc) (princ) ) (setq doc (vla-get-Activedocument (vlax-get-acad-object))) (vla-startUndoMark doc) (if (/= "" (setq txt (vl-string-trim " \t" (getstring "\nEntrez le texte à remplacer: ")))) (if (/= "" (setq bname (vl-string-trim " \t" (getstring "\nEntrez le nom du bloc: ")))) (if (tblsearch "block" bname) (if (ssget "_X" (list (cons 0 "TEXT") (cons 1 txt) (cons 410 (getvar 'ctab)))) (progn (setq space (vla-get-Block (vla-get-ActiveLayout doc))) (vlax-for obj (setq ss (vla-get-ActiveSelectionSet doc)) (vla-InsertBlock space (vla-get-InsertionPoint obj) bname 1. 1. 1. (vla-get-Rotation obj)) (vla-delete obj) ) (vla-Delete ss) ) ) (prompt (strcat "\nLe bloc '" bname "' est introuvable")) ) ) ) (*error* nil) )
-
BricsCAD a aussi une version Linux
-
Tu as probablement déjà fait un entget sur une région, un solide 3D ou une surface... Même en DXF, Autodesk ne montre que ce qu'il veut bien montrer.
-
On doit certainement pouvoir y accéder avec ObjectARX/C++, mais pour VBA ou .NET les objets vlo_VL sont des objets personnalisés au même titre que les "custom objects" des applications verticales ou externes. En .NET par exemple, je "vois" le dictionnaire et une (ou plusieurs) entrée(s) de type vlo_VL mais je ne peux pas accéder directement à leur valeur. En "pur AutoLISP", on peut y accéder via les DXF : (vlax-ldata-put "dict" "key" 42)crée le dictionnaire nommé "dict" avec une entrée "key" qui a 42 pour valeur. (setq dict (dictsearch (namedobjdict) "dict"))retrouve le dictionnaire dans le dictionnaire des objets nommés. (entget (cdr (assoc 350 (member '(3 . "key") dict))))renvoie la liste DXF de l'objet vlo_VL (nom DXF : VLO-VL)
-
Salut, J'ai modifié tes messages en ajoutant les balises bbcode pour conserver le formatage du code (voir ce sujet) Sinon, juste deux petites remarques : - la fonction vla-get-ActiveDocument n'active pas l'espace de travail, elle renvoie le document actif (le dessin courant) sous forme d'object vla (CAOM/ActiveX) - pour formater la date, tu peux utiliser la fonction menucmd avec une expression diesel : (menucmd "M=$(edtime,$(getvar,date),YYYY-MM-DD)")
-
Utilisation des balises bbcodes : [code] ici le code [/code] donne : ici le code Accessible via l'icône : http://gilecad.azurewebsites.net/Resources/bbcode.png
-
Les fonctions vlax-ldata* étaient dépréciées au moment de leur arrivée avec Visual LISP (R14 / 2000), parce qu'elles présentaient, à l'époque, des problèmes de compatibilité entre versions d'AutoCAD. Ceci est oublié aujourd'hui. L'autre reproche fait à ces fonctions (toujours d'actualité), c'est qu'elles utilisent pour stocker les données (dans des dictionnaires ou dictionnaires d'extension créés automatiquement) des objets de type vlo_VL au lieu d'objets Xrecord et que ces objets vlo_VL ne sont accessibles qu'en LISP contrairement aux objets Xrecord qui sont accessibles par tous les environnement de programmation.
-
Dans la plupart des cas, je préfère récupérer les données brutes sous forme de liste et traiter ensuite la liste renvoyée. AutoLISP est dialecte du LISP (LISt Processing), donc plutôt bien armé pour le traitement des listes.
-
Pour revenir au sujet (2ème message), pour lire un fichier texte et retourner une liste de lignes, on fait généralement : (lambda (filename / file line lst) (if (setq filename (findfile filename)) (progn (setq file (open filename "r")) (while (setq line (read-line file)) (setq lst (cons line lst)) ) (close file) (reverse lst) ) ) )
-
Ça dépend si les données à enregistrer sont liées au dessin ou si elles doivent être accessibles depuis tous les dessins. Je pense qu'il peut être intéressant de s'inspirer des variables systèmes, celles qui sont enregistrées le sont soit dans le dessin soit dans la base registre (par utilisateur ou par profil).
-
Le choix de la façon dont on veut enregistrer des données devrait dépendre en premier lieu du fait que ces données sont liées au dessin ou à l'application. Dans le premier cas, on enregistre les données dans le dessin, soit dans un dictionnaire, soit dans des données étendues, soit dans des attributs de bloc. Ma préférence va plutôt au dictionnaire (avec la possibilité d'utiliser les dictionnaires de données LISP avec les fonctions vlax-ldata*). Ecriture : (vlax-ldata-put "DenisHen" "LotiCoteLotPerimHaut" 2.5) (vlax-ldata-put "DenisHen" "LotiCoteLotPerimNbDec" 2) (vlax-ldata-put "DenisHen" "LotiCoteLotPerimFlech" 1) (vlax-ldata-put "DenisHen" "LotiNumLotHaut" 1) Lecture : (vlax-ldata-get "DenisHen" "LotiCoteLotPerimHaut") (vlax-ldata-get "DenisHen" "LotiCoteLotPerimNbDec") (vlax-ldata-get "DenisHen" "LotiCoteLotPerimFlech") (vlax-ldata-get "DenisHen" "LotiNumLotHaut") Dans le second cas, on enregistre les données à l'extérieur du dessin, dans un fichier texte, un fichier Excel, une base de données ou la base de registre. Ma préférence irait plutôt à la base de registre qui permet en plus d'enregistrer des données par produit AutoCAD, par profil, etc. AutoLISP fournit les fonctions vl-registry* qui permettent d'écrire et de lire dans la base de registre. Ecriture : (vl-registry-write "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimHaut" "2.5") (vl-registry-write "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimNbDec" "2") (vl-registry-write "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimFlech" "1") (vl-registry-write "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiNumLotHaut" "5") Lecture : (vl-registry-read "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimHaut") (vl-registry-read "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimNbDec") (vl-registry-read "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiCoteLotPerimFlech") (vl-registry-read "HKEY_CURRENT_USER\\Software\\DenisHen" "LotiNumLotHaut")
-
Pour construire une liste, on utilise la fonction cons. Les fonctions cons, car et cdr sont les fonctions fondamentales du traitement des listes, voir ce sujet.
-
Salut Que penses tu que fait cette ligne : (setq LstIni (list LstIni 'Line))
-
Salut, Je n'ai pas répondu plus tôt, parce qu'aborder ce sujet ne me réjouis pas plus que ça : il me reste encore 5 ans à tirer pour avoir le taux plein (si ça ne change pas d'ici là).
-
Déclarer localement variables et fonctions serait un moindre mal. Mais, à mon avis, prendre l'habitude de définir des fonctions qui prennent un ou plusieurs argument et d'utiliser la valeur renvoyée par ces fonctions (comme on le fait avec les fonctions prédéfinies) est essentiel. Je te rappelle ce sujet dont je te recommande grandement la lecture.
-
Si on t'a conseillé de déclarer localement les variables, ce n'est pas "par principe". En ne le faisant pas tu t'exposes à des bugs difficiles à localiser. La probabilité que ces bugs surviennent augmente avec le nombre de variables globales. Il y en a déjà un nombre assez considérable. Si j'ai bien compris, tu penses étoffer ta routine et, vu la façon dont tu as commencé, ça veut dine encore plus de variables. Je vais essayer, à l'aide d'un exemple très simple, d'expliquer ce qui pourrait être une meilleure pratique et ensuite, ce que je pense être une bonne pratique La manière dont tu procèdes avec des variables globales : (defun c:mauvaisePratique () (setq a 10) (calculGlobal) (prompt (strcat "\n" (itoa B))) (princ) ) (defun calculGlobal () (setq b (+ a 5)) ) En localisant variables et fonctions, tu éviteras tout risque d'interaction avec l'extérieur de ta routine : (defun c:meilleurePratique (/ calculLocal a B) (defun calculLocal () (setq b (+ a 5)) ) (setq a 10) (calcul) (prompt (strcat "\n" (itoa B))) (princ) ) Mais vu le nombre de variables que tu utilises, même si le problème des effets secondaires (effets de bord) est conscrit à ta routine, il existe tout de même à l'intérieur de celle-ci. La bonne pratique est d'utiliser des fonctions auxquelles on passe un ou plusieurs arguments et qui renvoient une valeur. (defun c:bonnePratique (/ a B) (setq a 10 b (calculArg a) ; appel de la fonction calculArg en lui passant a comme argument ) (prompt (strcat "\n" (itoa B))) (princ) ) (defun calculArg (x) ; x est l'argument de la fonction calculArg (+ x 5) ; valeur retournée par la fonction ) De plus, cette façon de faire permet souvent de réduire le nombre de variables locales, donc d'effets secondaires. (defun c:bonnePratique () (prompt (strcat "\n" (itoa (calculArg 10)))) (princ) ) En ce qui concerne les propriétés dynamiques des blocs, il faut utiliser les fonctions vla* pour y accéder. Mais personnellement, je n'ai pas trop envie de t'en dire plus tant que que tu continues dans une voie qui fait fi des conseils qu'on a pu te donner.
-
Cette version traite récursivement les blocs imbriqués EDIT: version corrigée, il y avait une faute d'orthographe ("AcDbblockReference" au lieu de "AcDbBlockReference") (defun c:Block_3D_Only (/ doc blocks lst ss) (vl-load-com) ;; obtenir le document actif et sa collection de définitions de bloc (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)) blocks (vla-get-blocks doc) ) ;; supprimer récursivement de la définition de bloc tous les objets autres que : ;; solide 3d, surfaces, maillages, polylignes 3d, faces 3d. (defun remove2dobjects (block) (vlax-for ent block (if (not (wcmatch (vla-get-ObjectName ent) "*3dSolid,*Surface,*Mesh,*3dPolyline,*Face" ) ) (if (= (vla-get-ObjectName ent) "AcDbBlockReference") (remove2dobjects (vla-Item blocks (vla-get-EffectiveName ent)) ) (vla-delete ent) ) ) ) ) ;; démarrer un groupe d'annulation (vla-StartUndoMark doc) ;; si l'utilisateur sélectionne des block (if (ssget (list (cons 0 "INSERT"))) (progn ;; collecter les noms des blocs sans doublons (vlax-for br (setq ss (vla-get-activeselectionset doc)) (or (member (vla-get-effectivename br) lst) (setq lst (cons (vla-get-effectivename br) lst)) ) ) ;; supprimer le jeu de sélection (vla-delete ss) ;; pour chaque nom de bloc de la liste (foreach name lst ;; pour chaque entité contenue dans la définition de bloc (remove2dobjects (vla-Item blocks name)) ) ;; régénérer la fenêtre active (vla-regen doc acActiveViewport) ) ) ;; terminer le groupe d'annulation (vla-EndUndoMark doc) (princ) )
-
En remplaçant : "*3dSolid,*Surface,*SubDMesh" par : "*3dSolid,*Surface,*Mesh,*3dPolyline,*Face" on retiendra les solides 3d, tous types de surfaces, tous types de maillages, le polylignes 3d et les faces 3d
-
Salut, Je te conseillerais d'y aller progressivement, sans chercher à tout faire d'un coup. Les boites de dialogue en LISP (DCL) ne sont pas très faciles à faire (ni le design ni la gestion), donc, dans un premier temps, concentre toi sur les calculs (ce qui est important), tu peux toujours afficher les résultats dans la fenêtre de texte avec de simples (prompt ...).
-
Salut, Erreur typique d'un copier/coller avec modifications sans faire de tests... Faudrait voir à écouter didier un peu ! (defun c:d2d (/ doc blocks lst ss) (vl-load-com) ;; obtenir le document actif et sa collection de définitions de bloc (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)) blocks (vla-get-blocks doc) ) ;; démarrer un groupe d'annulation (vla-StartUndoMark doc) ;; si l'utilisateur sélectionne des block (if (ssget (list (cons 0 "INSERT"))) (progn ;; collecter les noms des blocs sans doublons (vlax-for b (setq ss (vla-get-activeselectionset doc)) (or (member (vla-get-effectivename B) lst) (setq lst (cons (vla-get-effectivename B) lst)) ) ) ;; supprimer le jeu de sélection (vla-delete ss) ;; pour chaque nom de bloc de la liste (foreach name lst ;; pour chaque entité contenue dans la définition de bloc (vlax-for ent (vla-item blocks name) ;; si l'objet n'est pas un solide 3d, une surface ou un maillage (if (not (wcmatch (vla-get-ObjectName ent) "*3dSolid,*Surface,*SubDMesh")) ;; supprimer l'objet (vla-delete ent) ) ) ) ;; régénérer la fenêtre active (vla-regen doc acActiveViewport) ) ) ;; terminer le groupe d'annulation (vla-EndUndoMark doc) (princ) )
-
J'ai dû mal m'exprimer, je répondais à GEGEMATIC à propos de "dialogues" entre LISP et VBA ou LISP et .NET. Ces dernières années, j'ai beaucoup vu, des demandes pour appeler des routines LISP (et récupérer le retour) depuis des programmes .NET pensant que c'était plus simple que ré-écrire le LISP en C# ou VB alors que la vraie difficulter est de faire dialoguer deux environnement de programmations si différents (typage faible ou fort, dynamique ou statique, contexte document ou contexte application, etc.). Même dans l'autre sens, où il est prévu de pouvoir définir des fonctions LISP avec .NET, les choses ne sont pas simples (typage des arguments et valeurs de retour, gestion des erreurs).
-
Commande très curieuse dans une suite de lisp...
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
C'est exactement ça. ;; Extraction nom du fichier d'un chemin complet (defun UtFname (FileName /) (while (wcmatch FileName "*/*,*\\*") (setq FileName (substr FileName 2)) ) (UtReturn FileName) ) On pourrait remplacer (UtReturn FileName) par FileName, ou même par rien du tout dans ce cas là puisque une fonction LISP retourne toujours le résultat de l'évaluation de la dernière expression, donc ici : (setq FileName (substr FileName 2)) En bref, ce bout de code est équivalent à : ;; Extraction nom du fichier d'un chemin complet (defun UtFname (FileName /) (while (wcmatch FileName "*/*,*\\*") (setq FileName (substr FileName 2)) ) (setq FileName FileName) ) et pourrait être simplement écrit : ;; Extraction nom du fichier d'un chemin complet (defun UtFname (FileName /) (while (wcmatch FileName "*/*,*\\*") (setq FileName (substr FileName 2)) ) ) -
Commande très curieuse dans une suite de lisp...
(gile) a répondu à un(e) sujet de DenisHen dans Débuter en LISP
Salut, As-tu cherché où et comment cette fonction est utilisée dans le code ? J'ai vraiment l'impression que c'est du verbiage tout à fait superfétatoire. J'ai vu des codes où, pour spécifier la valeur de retour d'une routine on utilisait l'expression : (setq retval retVal) à la fin du code plutôt que tout simplement retVal. Cette fonction permettrait donc d'écrire : (UtReturn retVal) à la fin du code plutôt que tout simplement retVal... -
Salut, On peut faire dialoguer différentes interfaces de programmation (LISP VBA ou LISP .NET) mais souvent on se retrouve vite confronté à des problèmes qui font que ce qui semblait plus simple au départ finit par devenir un vrai casse-tête. Je recommanderais donc d'essayer de choisir l'interface qui semble la mieux adaptée et de tout faire avec celle-ci.
