FAQ AutoLISP comp.cad.autocad

Titre : FAQ AutoLISP comp.cad.autocad 
Nom Archive : CAD/autolisp-faq
URL : http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html

Version : 2.28
Dernière modification de la VO : datée 4 avril mais modifiée le 23 avril et publiée le 1er mai 2001
Traduction française : 4 mai 2001
Postée par : Reini Urban <rurban@x-ray.at
Traduction française : Roger Rosec <cadplus@free.fr>
Fréquence de postage : mensuelle 
Copyright : voir l'Appendice [A]

Bienvenue dans la FAQ comp.cad.autocad AutoLISP !

AutoLISP est un langage de script pour AutoCAD, l'ensemble de C.A.O. renommé.
Cette FAQ AutoLISP est postée dans les groupes comp.cad.autocad, alt.cad.autocad et le * .answers chaque mois.
Plusieurs FAQ AutoCAD se trouvent à http://www.autodesk.com/support/autocad/ mais ne sont pas postées sur comp.cad.autocad.
Le contenu et les exemples s'appliquent à toutes les versions d'AutoLISP depuis la version 10, y compris Visual Lisp, Vital Lisp et ACOMP.

Il n'y a aucun newsgroup spécial AutoLISP.

Les meilleurs sont comp.cad.autocad ou adesknews.autocad.customization. Ne vous embêtez pas à essayer comp.lang.lisp !

Le code source de toutes les fonctions contenues dans cette FAQ se trouve dans FAQ-CODE.LSP - Voir l'emplacement en [A.1]

Merci à tous ceux qui ont contribué. Les corrections et contributions sont toujours bienvenues.
SVP voir http://c2.com/cgi/wiki?RulesToLiveBy pour la Nétiquette.

(| changement, + nouveau dans les repères de cet article, les commentaires intermédiaires, personnels et incertains dans <..>)


Table des Matières


1ère partie : Général


[0]Le Futur d'AutoLISP ? Est-ce que je dois l'apprendre plutôt que VB ?
[0.1] Qu'est ce qui a changé avec AutoCAD 2000?
[0.2] Vous ne pouvez plus créer des ARX ?
[1] Où trouver des routines AutoLISP sur Internet ?
[1.1] Est-ce que les articles comp.cad.autocad sont stockés quelque part ?
[1.2] Le SDK Autodesk
[2] Quels sont les meilleurs livres (en anglais) pour apprendre AutoLISP ?
[2.1] Les documents AutoLISP en ligne, Winhelp (supprimé)
[2.2] Le style de programmation en AutoLISP
[3] Comment déboguer les programmes AutoLISP ?
[3.1] Les débogueurs AutoLISP natifs
[3.2] Le style modulaire, TRACE
[3.3] La fonction BREAK, Imprimer le débogage
[4] Comment puis-je protéger mes programmes AutoLISP ? Sécurité[modifié]
[4.1] Kelvinate
[4.2] Protect
[4.3] Kelvinate et Protect
[4.4] Convert
[4.5] ACOMP
[4.6] Vital Lisp Professional
[4.7] Lisp2C
[4.8] Visual Lisp par Autodesk
[5] Compilateurs AutoLISP
[5.1] ACOMP
[5.2] Vital Lisp Professional
[5.3] Visual Lisp par Autodesk
[5.4] Les meilleurss: Common Lisp et Scheme
[6] Editeurs AutoLISP et autres outils
[6.1] Editeurs AutoLISP
[6.2] Analyseurs, Empaqueteurs et Contrôleurs de parenthèses.
[6.3] Petits Editeurs
[7] Problèmes AutoLisp et bugs [ajouté]
[8] Tris avec AutoLISP [ajouté]
[9] Récursivité
[10] Itération avec MAPCAR,...
[11] S::STARTUP, mes lisps ne se chargent plus au lancement
[12] Comment autocharger mes programmes ?
[13] Comme passer un nombre variable d'arguments à une fonction LISP ?
[14] Comment éviter des débordements de pile (stack overflows) ? [changé]
[15] (command "ROTATE3D") ne marche pas! Pourquoi ?
[16] Les programmes lisp qui opèrent avec des dessins multiples
[17] Comment exporter les fonctions Visual Lisp dans AutoLISP/AutoCAD ?

2ème partie : Exemples, code


[20] Fonctions générales d'Aide
[20.1] Manipulation de listes
[20.2] Manipulation de chaînes
[20.3] Symbole-chaîne
[20.4] Accès aux Entités AutoCAD
[21] Programmes d'exemples en lisp
[21.1] Changement global de texte, polylignes, utilitaires de calques, dateur
[21.2] Le dialogue traceur à partir du LISP. En utilisant DDE [fixé] ou ActiveX
[21.3] (entmod),(entmake) sur les calques, sans (command" _LAYER "...)
[21.4] Comment sélectionner de multiples fichiers en LISP ? (comme dans FICHIERS-Déverrouiller)[nouveau]
[21.5] Remplacez des blocs multiples
[21.6] (vports), l'entité VIEWPORT, conversion de pixel
[21.7] Sélectionnez tous les objets visibles : les coordonnées du zoom
[21.8] Comment écrire dans un fichier les données XYZ des objets sélectionnés ?
[22] Attributs de bloc
[22.1] Comment accéder aux attributs du bloc ?
[22.2] Comment modifier des attributs du bloc ? DATESTAMP.LSP
[22.3] Comment mettre à jour des attributs du bloc ?
[22.4] Comment utiliser ENTMAKE avec une entité complexe bloc dans AutoLISP ?
[23] Polylignes
[23.1] Comment accéder aux sommets d'une polyligne ?
[23.2] Comment Joindre de multiples lignes aux polylignes ?
[23.3] Changement de Largeur de polylignes multiples
[23.4] Créer une polyligne ou une spline : avec ENTMAKE ou COMMAND
[23.5] Comment calculer la Longueur des polylignes ?
[23.6] Comment intervertir la direction d'une polyligne ?
[23.7] Comment obtenir le centre d'une polyligne? [nouveau]
[24] Géométrie Cercle/Arc : Conversion de courbe, un peu de trigonométrie
[25] DCL : boîtes de listes avec tabulations ou police de caractères monospaces
[26] EED Extended Entity Data (Données étendues) : Obtenir et stocker
[26.1] Objets sélectionnés par leur EED avec (ssget " X ")
[26.2] Obtenir les données étendues (EED) d'un objet
[27] Comment interrompre une commande en LISP ?
[27.1] Comment faire un nombre illimité de messages à l'utilisateur ?
[28] Comment décoder la géométrie interne ACIS avec LISP ?
  --
[A] Responsabilités, Notes des auteurs,
[A.1] Emplacements des FAQ
[B] Remerciements
[C] Changements récents


[0] Le Futur d'AutoLISP ? Est-ce que je dois l'apprendre plutôt que VB ?

AutoLISP sera supporté dans les versions futures sans aucun doute.
VB fût introduit pour simplifier l'Automatisation d'Office ACAD <-> Excel-Access

Les deux langages ont des avantages et des inconvénients. Vous devriez jeter un oeil sur les deux.
VB paraît être plus graphique et AutoLISP plus logique. Le concept de langage objet de VBA semble plus facile à apprendre, mais vous ne pouvez pas lancer des commandes comme en AutoLISP.
Le nouveau VBA (dans R14.01) est extrêmement rapide. Voir aussi [5.2]. Le futur d'AutoLISP est déjà Visual Lisp.
Pour plus de détails voir http://www.autodesk.com/vlisp, http://www.autodesk.com/develop/devres/visual/faq.htm, et [0.1] ci-dessous.


[0.1] Qu'est ce qui a changé avec AutoCAD 2000 ?

Le nom :) Non, il y a beaucoup plus, mais vous pouez l'appeler AutoCAD 2000, version R15, A2000 ou en abrégé A2K.

Le nouveau kernel (noyau) Visual LISP (anciennement Vital Lisp) remplace l'ancien kernel AutoLISP basé sur xlisp.
A quels problèmes pouvez-vous vous attendre avec Visual Lisp dans AutoCAD 2000 ? (uniquement les mauvaises nouvelles)
En http://xarch.tu-graz.ac.at/autocad/docs/r2000-news.txt j'ai compilé un livre blanc. Utilisez LCA pour tester vos lisps.
Les points principaux sont :


[0.2] On ne peut plus créer des ARX ?

Avec AutoCAD 2000 vous ne pouvez plus faire comme avec ViLL ou VLISP 4. A la place, vous devez compiler en VLX (Visual Lisp Extension), qui au fond possède les mêmes fonctionnalités que le vieux Visual Lisp/Vital Lisp ARX, avec les différences suivantes : Vous n'avez plus besoin des modules ARX. C'est une caractéristique, pas un bug.


[1] Où trouver des routines AutoLISP sur Internet ?

Les plus grands sites d'outils AutoCAD sont :

AutoCAD Plugin Store par beyond.com.
http://www.cadplugins.com/
C'est le site d'outils "officiellement recommandé" par AutoDESK.
CADalog - The AutoCAD Shareware Clearinghouse (Mike Clark)
http://www.cadalog.com/
The CAD Depot Anciennement connu sous le nom CADSyst (David Whynot)
http://www.caddepot.com/, récemment acheté par TenLinks.

Ils se sont spécialisés dans les logiciels relatifs à AutoCAD et ont une très bonne collection AutoLISP.
D'autres sites professionnels de sharewares AutoLISP postent également leur URL dans le newsgroup.

D'importants sites portails sont nouvellement créés :
[nouveau] TenLinks et le E-zine (magazine électronique) UpFront qui sont les meilleurs nouveaux services CAO.
Autodesk vient de lancer le site portail Point A.

Voici d'autres emplacements qui ont des collections AutoLISP :

xarch AutoCAD Info & Tools (Reini Urban)
http://xarch.tu-graz.ac.at/autocad/ (avec recherche)
CAD Users Webring [nouveau]
CADalyst magazine code (compilé par "Hot Tip Harry" Art Liddle)
http://www.cadonline.com/code/
Owen Wengerd
http://www.manusoft.com
Terry Dotson
http://www.dotsoft.com/
AcadX [nouveau]
http://www.acadx.com
Paul Turvill [nouveau]
http://www.turvill.com/t2/
Vladimir Nesterowsky
http://vnestr.tripod.com/
UCCB AutoCAD and AutoLISP page (Paul Standing)
http://ucad1.uccb.ns.ca/acad/cad.htm
Theo L.A. Groenenberg
http://members.xoom.com/acadvice/autolisp.htm
The CADshack (Jeff Foster)
http://www.cadshack.com/lispfile.htm
Lisp Factory (Jay Garnett)
http://www.enteract.com/~jgarnett/
Rakesh Rao - AutoCAD Tech Center
http://www.4d-technologies.com/techcenter

Liens anciens ou rompus:

AutoCAD Tech Journal code (Peter Sheerin) [ancien]
http://www.atj.com
CADENCE magazine code (Peter Sheerin) [ancien, rompu]
http://cadence-mag.com/
UCCB AutoCAD and AutoLISP page (Paul Standing) [rompu]
http://ucad1.uccb.ns.ca/acad/cad.htm
Dr.Lisp Utilities (Alexander Medwedew)
http://idt.net/~compvent/
McNeel's lisp archive [rompu]
ftp://ftp.mcneel.com/lisp/
Desi Moreno [rompu]
http://www.invsn.com/desmos/autolisp.htm
PIRS Online
http://www.insa.com/
Henry Francis [rompu]
http://www.ez-sys.net/~coopfra/
SimTel - Coast To Coast - Archive [fixé, très vieux]
http://www.simtel.net/msdos/autocad.html

Sur le site http://support.autodesk.com/ il y avait des documents du Support Produit Autodesk qui répondent aux questions techniques. (Leur FAQ)
Le "ASA" (Support Assistance, une sorte de FAQ) était à www.autodesk.com/support/autocad/asa2000.htm, un outil amélioré mais lent se trouve à support.autodesk.com/KnowledgeBase.asp

[1.1] Les articles comp.cad.autocad sont-ils stockés quelque part ?

Il n'y a aucune archive comp.cad.autocad ou quelque chose de rapprochant, mais il y a quelques machines de recherche qui entreposent des articles de news. En particulier :

http://deja.com/usenet - La plus grande archive de news
http://www.altavista.com/
http://www.altavista.com/cgi-bin/query?pg=aq&what=news
http://www.excite.com/
http://www.excite.com/search.gw?collection=news
Phoaks - People Helping One Another Know Stuff - Extracteur automatique de liens
http://www.phoaks.com/phoaks2/newsgroups/comp/cad/autocad/index.html

Quelques vieux articles de news spécifiques sont aussi stockés à http://xarch.tu-graz.ac.at/autocad/news/contents.html


[1.2] Le SDK d'Autodesk

Jusqu'à la version 12 un SDK (kit de développement de soft) était disponible directement à AutoDESK. Les SDK1-2 ont été livrés gratuitement avec la R12 internationale. Ils incluaient beaucoup de code source et de bibliothèques pour ADS et AutoLISP.

Avec la R13 Autodesk pourvoit un réseau spécial de développeurs, comparable à celui de Microsoft, l'ADN. Le CD est comparable au vieux SDK mais est plus destiné aux développeurs ADS et ARX. .
Contactez votre revendeur Autodesk le plus proche pour en devenir un membre.

Quelques Lisps sont à l'adresse http://xarch.tu-graz.ac.at/autocad/code/adesk/SDK2/

Aux US, devenir adhérent ADN coûte 600.00 dollars par an. Les CD-ROMs n'incluent aucun SDK, mais la plupart des trucs des SDK originaux y sont inclus sous une forme ou l'autre. (Owen)


[2] Quels sont les meilleurs livres (en anglais) pour apprendre AutoLISP ?

AutoLISP to Visual LISP [nouveau]
Kevin Standiford, Autodesk Press, ISBN 0-7668-1517
AutoLISP: Programming for Productivity,
William Kramer, Autodesk Press, ISBN 0-8273-5832-6
Essential AutoLISP,
Roy Harkow, Springer-Verlag, ISBN 0-387-94571-7
AutoLISP in Plain English; A Practical Guide for Non-Programmers,
George O. Head, Ventana Press, ISBN: 156604140-6
Maximizing AutoLISP
par Rusty Gesner, Tony et Mark Middlebrook, Tony Tanzillo.
Pour en savoir plus http://www.group-a.com/~rusty
AutoLISP Reference Manual"
par Autodesk Press.
Jusqu'à la R12 il était fourni comme manuel supplémentaire. Puis, avec R13, ce fut une partie du manuel de personnalisation. Depuis la R14 c'est un fichier d'aide Windows.

Il y a beaucoup d'autres livres AutoLISP.

Livres de LISP général (mais pas AutoLISP) qui sont à recommander :

ANSI Common Lisp, (Common Lisp primer)
Paul Graham, Prentice Hall, ISBN 0-13-370875-6
Structure and Interpretation of Computer Programs, (high-level Scheme)
H.Abelson, GJ. Sussman, J. Sussman, MIT Press, ISBN 0-262-01153-0
"C"est sans aucun doute un des meilleurs livres d'ordre général pour ordinateurs jamais écrits."
LISP, 3rd Edition,
Patrick Henry Winston and Berthold Klaus Paul Horn,
Addison-Wesley Publishing Company, ISBN 0-201-08319-1
Looking at LISP,
Tony Hasemer, Addison-Wesley Publishing Company, ISBN 0-201-12080-1


[2.1] Documents en ligne AutoLISP, Winhelp [Supprimé dans la version postée]

R14 est livré avec les manuels complets convertis sous forme de fichiers Winhelp.

Les fichiers Winhelp AutoLISP sont disponibles avec :

Pour DOS, il existe un programme résident en mémoire appelé LISPHLP.EXE
(activé par Ctrl-RightShift-R, depuis 1988)

LSPDOC: En http://xarch.tu-graz.ac.at/autocad/lsp_tools/#lspdoc est disponible un outil qui crée automatiquement un Winhelp pour fichiers LISP.


[2.2] Le style de programmation en AutoLISP

La plupart des exemples qui sont publiés par les magazines ou sur plusieurs des sites du web sont très mal écrits, c'est pourquoi AutoLISP est assez dur à apprendre pour les néophytes. Le Lisp est dur à lire à cause de sa forme compacte et de ses innombrables parenthèses. Par conséquent tout le monde est tenu d'écrire le code pour qu'il soit clair et lisible. Les exemples Autodesk sont assez bien écrits mais quelquefois ils exagèrent. :-)

Il existe des petits éditeurs automatiques, appelés 'beautifiers" (embellisseurs) (voir [6.3]) lesquels formattent automatiquement votre code selon le standard.

Il y a une excellente documentation Autodesk au sujet de la programmation, les commentaires et les standards d'indentation afin de conserver le code du Lisp lisible. On la trouve sur le CD-ROM version R12 dans les SDK2 ACG.DOC ou à l'adresse http://xarch.tugraz.ac.at/autocad/docs/acg.txt

Les points les plus importants sont :


[3] Comment déboguer des programmes AutoLISP ?

[3.1] Il y a trois débogueurs AutoLISP natifs :

Voir [5] Compilateurs AutoLISP

[3.2] Style modulaire, TRACE

Le meilleur support que vous pouvez avoir pour débogguer est d'écrire votre code bien conçu, en style modulaire, en distinguant les tâches dans des fonctions séparées et en utilisant alors librement les appels imbriqués de la fonction. Cela vous permettra d'utiliser la fonction TRACE suivant besoin pour localiser toute erreur.

[3.3] Vous pouvez inclure les fonctions BREAK et debug-print dans votre code source.

Les exemples :

  ;;; Fonctions de debogage : 
  (defun break (s) 
    (if *BREAK* 
      (progn 
        (princ "BREAK (stop avec )\nBREAK ")
	(princ s) 
        (while (/= (setq s (getstring "\nBREAK ")) "") 
          (print (eval (read s))) 	
        ) 
      ) 
    ) 
  ) 
  (defun dbg-print (s) ; accepte atome et listes 
    (if *DEBUG* 
      (if (listp s) 
        (MAPCAR 'print s) 
        (print s) 
      ) 
    ) 
  ) 
  (defun C:DEBUG () (setq *DEBUG* (not *DEBUG*))) ; bascule on et off 
  (defun C:BREAK () (setq *BREAK* (not *BREAK*))) 
  (defun CONT () (setq *BREAK* nil))              ; continue sans interruption 
  ;;; Exemple 
  (setq *BREAK* T *DEBUG* T)
  (defun C:TEST () 
    (foreach x '("1" "1.0" "1e-3") 
      (break "in foreach") 	; stoppe l'evaluation si *BREAK* est 'on', vous pouvez entrer x 
				; et la valeur de x est affichee jusqu'a ce que vous entriez Enter
      (setq x (atof x)) 	; ceci est le code qui manipule x 
      (dbg-print x) 		; ceci affiche la nouvelle valeur de x 
				; si *DEBUG* est 'on' 
    ) 
  ) 
  Command: TEST 
  BREAK>> (stoppez avec ) 

  BREAK>> in foreach 
  BREAK>> x 
  1.0 
  BREAK>> (CONT) 		; bascule 'off' l'interruption 
  nil 
  BREAK>> 
  1.0 
  1.0 
  0.001 
Vous pouvez également basculez en 'off' la sortie de débogage avec
  BREAK>> (setq *DEBUG* nil) 
Pour continuer en grandes boucles


[4] Comment est-ce que je peux protéger mes programmes AutoLISP ?

"Est-ce que vraiment vous devez le protéger ? Si vous voulez partager des routines juste avec vos amis, pourquoi ne pas leur donner le code ? Votre code est protégé par copyright, même implicitement. Travailler avec les autres peut être un bon moyen d'obtenir de nouvelles idées et vous guider vers une meilleure application.
Quelques-uns des meilleures utilitaires sont ceux que mes amis ont améliorés et j'ai amélioré quelques-uns des utilitaires de mes amis." (Dennis)
[4.1] Kelvinate
avec KELV.EXE (sur le CD-ROM R12, sur les sites AutoLISP [1]) ou sur le site Le Coin des AutoCADiens, rubrique Outils - Gratuit.
Pour 'dé-Kelvinater' des fichiers LISP utilisez un petit éditeur, ou Lisp Beautifier disponible sur le site Le Coin des AutoCADiens, rubrique Outils.
Mais les noms de symboles (fonctions et variables) resteront altérés et les commentaires seront perdus.
[4.2] Protect
Avec PROTECT.EXE ((sur le CD-ROM R12, sur les sites AutoLISP [1] ou sur le site Le Coin des AutoCADiens, rubrique Outils).
Notez qu'il existe des déplombeurs. Gratuits.
[4.3] Kelvinate et Protect
En premier lieu Kelvinate pour le rendre illisible, ensuite utilisez Protect. Gratuit
[4.4] Convert
Shareware LISP En-/Decryptor par Maciej Lukasiewicz de Suède.
Les Lisps cryptés par Convert ne peuvent pas être décryptés par les autres programmes, mais Convert peut le faire ...
[4.5] ACOMP
Compilateur AutoLISP ACOMP.EXE sur la version R12 internationale ou sur les sites AutoLISP. Gratuit. Davantage de documentation au sujet d'ACOMP sur http://xarch.tu-graz.ac.at/autocad/bi4/
Voir aussi [5.1] Compilateurs AutoLISP
[4.6] Vital LISP Professional
Autrefois à http://www.basissoftware.com/vill.htm Lien rompu.
appelé " ViLL ", périmé. Voir aussi . [5.2] Compilateurs AutoLISP.
[4.7] Lisp2C
Convertisseur LISP en C, pour R12,R13,R14 Dos, Win (Watcom, Metaware, MSVC Libs). Vous devons posséder un de ces compilateurs tel que C/C++ compiler.
http://www.basic.si
[4.8] Visual Lisp par Autodesk
Appelé "VLISP". Le futur ; Voir [5.3]

Sécurité des FAS :
Sur les 2 newsgroups, il y avait récemment une longue discussion au sujet de la sécurité des FAS. Apparamment les FAS peuvent être décompilés en code source lisible, mais cet outil n'est pas encore disponible sur le net.La compilation FAS/VLX avec l'option Optimised/Internal est semblable à la Kelvination. Les noms de symboles, les chaines et nombres sont moins sécurisés que les algorithmes.

En résumé :
Un cryptage sérieux est obtenu seulement par Vital LISP et ses successeurs.
En utilisant Kelvinate, vous rendez les fichiers LISP illisibles et ils se chargent plus vite.
Les fichiers lisp protégés peuvent être décryptés facilement.
Les autres ne sont pas décryptables.
Les fichiers LISP cryptés avec Convert -e$GUARD peuvent être déprotégés seulement avec Convert.


[5] Les compilateurs AutoLISP

Il y a trois compilateurs AutoLISP, mais de meilleurs pourront être utilisés dans le futur. Certains lisps acceptent déjà, ou accepteront, ActiveX ou juste un simple FFI)

[5.1] ACOMP
Acomp a été maintenu jusqu'à la version R12 pour les versions internationales seulement. Il est gratuit. Ne fonctionne pas avec R13 ni avec la version intérieure R12/Win
Produit des fichiers .BI4 et nécessite un ACADL.EXP spécial fourni sous forme de ACADLC.EXP. Pour en savoir plus http://xarch.tu-graz.ac.at/autocad/bi4/
Les messages d'erreur de compilation sont plus explicites qu'avec ViLL/Vital Lisp.
[5.2] Vital LISP Professional
par Basis Software Inc. USA. Les modules runtime sont en licence gratuite pour R12/R13/R14 DOS/Windows/NT
Basis ne continue plus à développer Vital Lisp. Voir aussi [6.1] et [4.6]
[5.3] Visual Lisp par Autodesk
Vlisp 4 (for R14), le successeur de Vital Lisp est pratiquement identique à Vill 3.2 ; Seuls le GUI, les noms de fonction et la documentation ont changé :
vill- => vlisp-, vlx- => vl- les préfixes vlx en vl et quelques fonctions vlax- ont davantage de traits d'union.
Avec AutoCAD 2000 VLISP remplace le vieux moteur AutoLISP. Voir [0.1] Les fichiers VLX files sont livrés en fichiers FAS avec des ressources optionnelles en DCL, utilisés par R14/R15.
Les fichiers R15 FAS/VLX sont incompatibles avec les versions précédentes (FAS2 -> FAS4) à cause de caractéristiques de langage ajoutées (espace de noms séparé).

[5.4] Les meilleurs : Common Lisp et Scheme
ARX Natif existe pour Corman Common Lisp (une simple console),
COM support pour Allegro Common Lisp 5, Lisp Works pour Windows et dans le futur pour GambitC.
Via un FFI ("Foreign Function Interface") la plupart des lisps ou combinaison peuvent communiquer avec AutoCAD.
Voir http://xarch.tu-graz.ac.at/autocad/lisp/ffis.html
Un petit travail est fait avec Corman Lisp et ACL5, actuellement un produit commercial utilise ACL5 ("Design++" by Design Power)
Voir http://xarch.tu-graz.ac.at/autocad/bi4/ pour plus de détails.

En résumé :
Les compilateurs AutoLISP sont des compilateurs du type bytecode, qui nécessitent un runtime. AutoCAD 2000 utilise maintenant VLISP, donc le runtime y est inclus. Vous ne pouvez pas créer de programmes autonomes, sauf avec ViLL et Vlisp où vous pouvez avoir des ARX autonomes. Les symboles sont codés.


[6] Editeurs AutoLISP et autres outils

[6.1] Editeurs AutoLISP

Visual Lisp par Autodesk

Voir [5.3] l'outil le meilleur et le plus recommandé. Il est inclus gratuitement dans AutoCAD 2000.

Emacs pour NT
Un éditeur énorme et très difficile à apprendre mais il est écrit et personnalisable en elisp, qui est très proche d'AutoLISP. Le père de tous les éditeurs. Gratuit, pour toutes les plates-formes. Vient en 2 variétés : XEmacs ou GNU ntemacs.
En mode AutoLISP sur http://xarch.tu-graz.ac.at/autocad/lsp_tools/ntemacs.html


Vital Lisp périmé par Visual Lisp. N'est plus disponible.
Voir la section [5.2] Compilateurs AutoLISP

LispLink 2000
Editeur commercial AutoLisp avec surlignement de syntaxe, vérification de parenthèses, gestion de projet, prévisualisation des boîtes de dialogue et documentation des fonctions Visual LISP et la compilation FAS.
http://www.caelink.com

CodeMagic
Editeur de texte en shareware avec surlignement de syntaxe AutoLISP.

Vieux trucs :

LispPad Editeur AutoLISP par Tony Tanzillo.
Visual Lisp par WSSW
Un vieux petit éditeur lisp sous Windows, la Version 1.0 était même gratuite. Ne pas confondre avec Visual Lisp, le nouvel AutoLISP. Ce n'est qu'un petit éditeur. Voir[1]
WCEDIT 2.02
Editeur ADS pour DOS R12, peut évaluer le code du Lisp, à l'intérieur de l'éditeur, gratuit.
Voir [1]
CODEKEY
Vieil IDE commercial sous DOS, avec éditeur interne, protect, unprotect, kelvinator, {disponibilité ?}
ALLY 3.0 et CADET
Analyseur et Editeur de LISP en shareware.
Voir [6.2]
pred
Gratuit, petit éditeur sous DOS qui fournit une mise en valeur des parenthèses.
Sur ftp://xarch.tu-graz.ac.at/pub/autocad/lsp_tools/pred.zip
ADE est un éditeur similaire.
LSPEDIT de xlisp-stat
Un éditeur simple de Lisp sous Windows qui accepte le contrôle des parenthèses et l'indentation du code-source.
Essayer à http://www.stat.umn.edu/~luke/xls/xslinfo/xslinfo.html


Les éditeurs généraux de programmation tels que MultiEDit Pro , WinEdit, E!, TextPad, UltraEdit ou PFE sont largement utilisés également. En général, ils ne fournissent pas de contrôle de syntaxe LISP, par contre sont très utiles pour des recherches/remplacements sur des fichiers multiples ou pour une personnalisation en surlignage de la syntaxe.

[6.2] Analyseurs, Packageurs et Contrôleurs de parenthèses

Ces contrôleurs de parenthèses ne devraient plus êre utilisés, les éditeurs effectuant ce travail. Les analyseurs génèrent une fonction de références croisées et l'arbre des appels de fonctions. Les packagers sont utilisés pour générer les bibliothèques à partir de fichiers sources variés, en copiant toutes les fonctions désirées. Il n'y a pas encore de programme pouvant internationaliser les chaînes de commandes, mais avec la R15 arrive un analyser de Lisp (LCA)

VLISP - Compilateur analyseur (compile entièrement avec messages) et contrôleur de parenthèses (Ctrl-Alt-C)

Reini's AutoLISP Packager
http://xarch.tu-graz.ac.at/autocad/lsp_tools/#Packager
Fonction de références croisées, arbre inversé des appels, création d'une bibliothèque à partir des fichiers sources. ("Packager ou fonction Shaker")

PEI's Findvars
Similaire aux packagers ci-dessus, mais pas seulement que des fonctions, détecte en plus les symboles à rechercher. http://www;perceptual-eng.com
Personnellement, j'utilise celui-là et mon empaqueteur.

RapidLisp v1.Oc
Analyseur de lisp en shareware pour R14. http://www.cps.de/cad/rapidlisp

AVC - AutoLISP Variable Collector [nouveau]
Freeware, retrouve par fonction toutes les variables devant être déclarées . http://users.actcom.co.il/sysoft/vc.htm

LCA - Analyser de compatibilité AutoLISP d'Autodesk [nouveau]
(sur le CD Migration) Détaille la compatibilité AutoCAD 2000 avec les programmes specifiés d'AutoLISP (LSP) ou avec les fichiers de Menu LISP (MNL).

ALLY30.ZIP (vieux)
Analyseur de lisp shareware. Vérifie la syntaxe et imprime des statistiques (l'arbre de dépendance des fonctions). Voir [1] Disponible sur Le Coin des AutoCADiens, rubrique Outils.
lck21b.zip(vieux)
LCK LISP Checker 2.1b (graphique)
paran.zip (vieux)
Simple
PARNCH.ZIP (vieux)
Simple

Il y a aussi quelques programmes AutoLISP qui comptent les parenthèses.

[6.3] Petits Editeurs

Externe:

FMT202S.ZIP
Formatte les codes source LISP, DCL et FRM.
LB.EXE
"L'embelliseur" de code source d'Autodesk
dans le SDK2 ou à [1]
Il y a des problèmes avec les longues chaînes, et les commentaires en ligne nouveau-style.
Disponible sur Le Coin des AutoCADiens, rubrique Outils.
PPRINT.LSP
dans le SDK2 ou à [1]

interne :
Visual Lisp, Vital LISP, Emacs et Codekey fournissent des "beautifiers" internes, si je suis bien informé.


[7] Problèmes et bugs avec AutoLisp

Pour AutoCAD 2000 et et pour les utilisateurs inexpérimentés de VLISP voir [0.1]

Il n'y a pas de bugs AutoLISP sérieux connus. L'interpréteur de langage lui-même (ACADL.EXE /.EXP, VLISP) travaille bien indubitablement.
Mais il y a quelques restrictions basées sur le moteur AutoCAD, ActiveX ou Proteus (DCL). Quelques programmes de lisp du SUPPORT sont parfois défectueux. (exemple DDMODIFY.LSP)

Pour Visual Lisp voir le fichier README.txt qui liste tous les bugs connus et les limites. Les crashes avec les reactors sont des bugs d'acad.

Deux listes de bogues non officielles se trouvent à :
http://www.cadonline.com/exclusive/bugs/bugwatchlist.htm (la plus grande)
http://www.dotsoft.com/buglist.htm (une liste privée plus courte)

LDATA par Tom Berger (VLISP pour R14 et A2000)
En bref : N'utilisez pas du tout LDATA. Il peut détruire les DXF et DWG dans A2000. Il est aussi TRES difficile de s'en débarasser.
Une liste d'arguments avec des PAIRES POINTEES
passées d'AutoLISP en Visual LISP, ou le contraire, peut perdre sa parenthèse fermante.
Voir le README de Visual LISP (non documenté dans Vital lisp
Des LISTES d'ATOMES SIMPLES retournées incorrectement depuis des Applications Externes.
Visual LISP ne peut pas distinguer entre une liste d'un atome simple (élément), et un atome simple retourné d'une application externe ObjetARX ou ADS.
ENTGET utilisé avec LWPOLYLINE, HATCH (R14 uniquement)
La coordonnée en Z (caddr (getval 10 ele)) est un nombre aléatoire et produit souvent une exception en virgule flottante parce qu'il peut être trop petit ou trop grand.
A ce sujet : Voir partie 2, [23.1]
ENTMAKE VERTEX par Terry Dotson (R14 seulement)
Un problème peut survenir durant le processus d'utilisation d'Entmake pour créer des polylignes ; Vous devez assigner le calque à chacune des définitions du VERTEX (sommet) (c'est ce que nous a dit Autodesk), mais vous devez aussi assigner le calque au SEQEND de fin. En l'absence de ceci, SEQEND se terminera sur le calque courant qui pourra être gelé plus tard. Des tentatives de déplacer cet élément géométrique provoqueront une erreur de REGEN et causeront alors un crash en R14 (seulement).
ACAD_STRLSORT : Commande de tri étrange sous Windows.
Les caractères sous Windows ne sont pas triés suivant leur représentation ASCII !
  Windows: (acad_strlsort '("-1" "+1")) -> ("-1" "+1"),
  DOS:     (acad_strlsort '("-1" "+1")) -> ("+1" "-1")
  Mais pour les 2 : (mapcar 'ascii ("-" "+"))    -> (45 43)
Pour en savoir plus http://xarch.tu-graz.ac.at/autocad/docs/strlsort-bug.html

AI_PROPCHK
(ai_propchk) a été renommé en (C:AI_PROP) dans le patch de mise à jour R13c3.
"La fonction AutoLISP ai_propchk a été changée en c:ai_prop pour devenir similaire aux autres commandes. Cela permet d'appuyer sur Entrée pour revenir à DDMODIFY si sélectionné à partir de la barre d'outils."

Des actions de rappels défectueux en code DCL version R13 font crasher AutoCAD
Il y a un bug en R13 où AutoCAD crashe avec une Erreur Fatale si une erreur se produit dans le code AutoLisp pendant un rappel de l'action à partir d'une barre de défilement dans une boîte du dialogue. Par exemple, si vous essayez d'évaluer une fonction nulle pendant le rappel, AutoCAD se crashe instantanément. Techniquement, ce n'est pas un bug dans l'interpréteur AutoLisp, mais nous l'appellerons un bug AutoLisp.

Vous ne pouvez plus compter sur le bit 64 dans le drapeau 70 dans les tables des symboles depuis la R13, comme c'était le cas dans toutes les précédentes versions. Les blocs insérés peuvent ne pas contenir le code 64.

Quoi d'autre ? Voir la liste de bugs AutoCAD officieuse compilée par Steve Johnson pour davantage de comportements et programmes AutoLISP défectueux à l'adresse http://www.cadonline.com/exclusive/bugs/bugwatchlist.htm

Les fichiers en LISP protégé

Dans la version pre-c4a R13 les fichiers en LISP protégé ne restent pas protégés dans la mémoire. Pour notre opinion, ce problème se doit d'être connu de tous, afin que les développeurs ne pensent pas, par inadvertance, que leur code protégé est à l'abri des yeux indiscrets. Ce sujet de faq a provoqué un problème majeur sur le forum AutoCAD sur Compuserve mais il y a de bonnes méthodes de sécurité. Voir [4].

Le nombre limité de jeux de sélection ouverts
Ils sont, par intermédiaires, stockés dans les fichiers temporaires. Se débarrasser des jeux de sélection inutiles en mettant les symboles à nil et lancer (gc), la purge mémoire (garbage collector) actuellement provoque la fermeture de ces fichiers.
Le nombre maximal dépend du système d'exploitation, c.-à-d. dans DOS la valeur dans CONFIG.SYS de FILES=
R13 a augmenté le nombre.

Nombres : étendue, exactitude, précision numérique
Les nombres entiers sont stockés en mémoire interne en 32-bit signés, mais la communication d'AutoLISP à AutoCAD n'accepte que les 16-bit seulement, dans l'intervalle -32768. +32767, parce qu'AutoCAD n'a besoin que des adresses courtes en 16 bits.
Les nombres en virgule flottante sont des doubles (64-bit IEEE). Tous les calculs numériques internes d'AutoLISP et AutoCAD travaillent avec ce format double qui devrait être suffisant. Au moins, les 14 premières décimales sont exactes.
Un problème habituel est la confusion entre le nombre actuel (exact) et la représentation en chaîne de l'arrondi. Le nombre qui est montré sur la ligne de commande est souvent la chaîne de l'arrondi qui tient compte de LUPREC et DIMZIN.

Cependant avec beaucoup de comparaisons géométriques, c'est là que surviennent souvent des arrondis non désirés, aussi il est prudent de comparer des points avec un facteur de précision très petit [1e-12 - 1e-6]. (equal pt1 pt2 1e-6) ; 0.000001 la tolérance de l'erreur de l'arrondi au lieu de (equal pt1 pt2), spécialement pour les angles.
Voir aussi http://www.autodesk.com/support/techdocs/td30/td301207.htm

VB : Il a été reporté récemment, qu'en chargeant certains contrôles automation, la précision numériques et les particularités locales (`,´ à la place de `.´) ont des effets secondaires indésirables. Une solution et une explication de ce problème est en suspens. (Principalement pour `,´ comme délimiteur décimal dans des pays comme la France ou l'Allemagne.)

ACOMP - exactitude de (eq)
Avec le code compilé [5.1] ACOMP vous devez tenir compte que le comportement de (eq) en BI4 est beaucoup plus strict que dans l'AutoLISP ordinaire. Dans AutoLISP (eq "1" "1") est T alors que dans le code compilé par ACOMP c'est nil

Ce qui suit ne concerne pas des vrais bugs qui font qu'AutoLISP se plante ou retourne des résultats faux. Ce sont seulement des mauvaises mises en œuvre du langage.

AND et ORdevraient retourner la valeur de l'argument non-NIL au lieu de T. Voir http://xarch.tu-graz.ac.at/autocad/docs/and-bug.html

MAX et MIN devrait manier les types chaîne également parce que < and > accepte les chaînes.

Voir ACAD_STRLSORT ci-dessus.

Pour les Débordements de pile , voir [14] .


[8] Trier avec AutoLISP

En abrégé : Utilisez VL-SORT (générique) ou ACAD_STRLSORT (pour chaînes uniquement).
Mais Attention : VL-SORT retire les entrées dupliquées (qui sont EQ ... uivalentes) !

Vous trouverez une vue d'ensemble de tri à http://xarch.tu-graz.ac.at/autocad/lisp/#sort

En Lisp la méthode de tri principalement utilisée est le tri fusionné (utilisé aussi dans (str-sort) dans l'exemple TABLES.LSP d'AutoDESK) parce que c'est une méthode naturelle pour les listes. Normalement (en C.) vous utilisez le tri en tas (pour toutes données) ou qsort (pour les données aléatoires) et tri par insertion pour les petites listes (< 7) ou les sous-listes ans l'algorithme.

Il y a du code de lisp pour les différentes sortes de tri (shell-sort, bubble-sort, insertion-sort, quick-sort) disponibles pour toutes données, listes de listes et indices de listes. Dans LISP vous pouvez passer la fonction pour faire le tri, lequel est évalué en runtime, (appelé dans ce cas method). C'est pourquoi vous n'avez besoin seulement que d'une fonction de tri pour les types de données multiples (c.-à-d. nombres, points en x ou y, chaînes,...)

  (tri donnees methode)    ; method: less-than-predicate
                           ; defaut pour les nombres: '<
Quelques exemples de durée tirés de http://xarch.tu-graz.ac.at/autocad/lisp/sort/ur_sort.lsp :
     Tri de 100 elements :  
      bubble sort   : 13.639008 sec/ 30.08%
      insertion sort: 13.368042 sec/ 29.48%  (rapide pour les tris de listes)  
      shell sort    : 13.478973 sec/ 29.73%  (mise en oeuvre pauvre)  
      merge sort    :  2.232971 sec/  4.92%
      quick sort    :  2.433960 sec/  5.37%
      vl-sort      :  0.099976 sec/  0.22%  (Visual/Vital Lisp interne)
      acad_strlsort :  0.089996 sec/  0.20%  (AutoLISP's interne, juste les chines)
Chronométrages en cours pour vl-sort, vl-isort, STDLIB std-fast-sort, std-sort, sts-stable-sort et le nouveau tri de Vladimir.


[9] Récursivité

Ce n'est pas une question souvent posée mais elle est très intéressante parce que le Lisp lui-même est défini récursivement et c'est souvent la façon la plus facile d'articuler les problèmes graves.

Il y a quelques bons documents au sujet de la récursivité à http://xarch.tu-graz.ac.at/autocad/lisp/ et spécialement le fichier http://xarch.tu-graz.ac.at/autocad/lisp/recursive.html Tutorial par Dennis Shinn.

Il explique en grand détail :

  (defun fact (n)
    (cond
      ((zerop n) 1)
      (T (* n (fact (1- n))))
     )
  )

Note: Il y a aussi un exemple auto-modifiable de cette fonction expliqué à http://xarch.tu-graz.ac.at/autocad/lisp/self-mod.lsp


[10] Itération avec MAPCAR,...

De même qu'avec la récursivité ce n'est pas une question souvent posée, mais c'est assez difficilement compréhensible également.
Les déclarations itératives dans AutoLISP sont : WHILE, REPEAT, FOREACH et MAPCAR. Nous les utilisons largement dans le code de cette FAQ parce qu'ils permettent un code compact.

Il y a une courte leçon sur LAMBDA, QUOTE, MAPCAR... par Vladimir Nesterowsky :

  >>         "Il y a 14 trajectoires et 12 cochons.  
  >>         Comment est-ce qu'il peut y avoir 24 canards ?"  
  >> Y a t-il une commande lisp qui me permettra de choisir ces  
  >> lignes de texte, et reconnaitre le(s) nombre(s) dans chaque ligne,  
  >> dans le but, disons, de multiplier chaque nombre par deux ? 
  >> En laissant la structure de la phrase, etc, intacte ?  
  Il y a un moyen. (Je suis certain qu'il y en a beaucoup d'autres)  
  (defun mult2 (strng)          ; par Vladimir Nesterowsky
    (strlgather
      (mapcar
        '(lambda (s / n)
          (if (zerop (setq n (atof s)))
            s
            (rtos (* n 2))
          )
        )
        (strlparse strng " ")   ; analyse par les espaces  
      )
      " "                       ; rajouter des espaces en arriere  
    )
  )

expliqué à http://members.tri pod.com/~vnestr/mapcar.txt

  ;;; intervertit rangees et colonnes dans une matrice
  (defun transpose(l)           ; par Doug Wilson
    (apply 'mapcar (cons 'list l))
  )

c'est expliqué à http://xarch.tu-graz.ac.at/autocad/lisp/transpose.002.html


[11] S//STARTUP, mes LISPs ne se chargent plus au lancement

Les fichiers LISP peuvent être chargés au lancement d'AutoCAD en utilisant LOAD dans ACAD.LSP. Quelques LISPs qui exigent de fonctionner avec un menu adapté doivent être chargé à partir du fichier menu.MNL correspondant. Le fichier menu.MNL - si différent - devrait charger ACAD.MNL .

Les fichiers lisp qui appellent des commandes au démarrage doivent être définis dans la fonction S::STARTUP d'ACAD.LSP. Cette fonction est appelée automatiquement au démarrage après l'initialisation. Autrement vous obtiendrez des erreurs "Command list interruption (6 . 2)".
Note: (command) peut être appelé avec sûreté de l'intérieur des fichiers MNL.
(S::STARTUP) est maintenant utilisé pour appeler des menus partiels.

Si le nom du fichier ne comporte pas d'extension, la fonction LOAD ajoute .LSP. Sans indication de chemin, le programme recherche dans le chemin de recherche habituel d'AutoCAD qui est :

1) le répertoire courant
2) le répertoire contenant le fichier du dessin en cours.
3) les répertoires qui ont été définis dans la variable d'environnement ACAD
(sous Windows, s'installe par la boîte des Préférences, chemins dans Support de l'onglet Environnement)
4) le répertoire contenant acad.exe

Si cependant votre programme ne se charge pas davantage, essayez peut-être de tester le chemin de recherche de votre AutoCAD.

Avec ACADLC (d'ACOMP) et la version non internationale d'AutoCAD R12 ACAD.LSP n'est pas chargé automatiquement. Par conséquent vous devez ajouter (load "ACAD" -1) dans votre ACAD.MNL.

Exemple d'ACAD.LSP :

  ;;;ACAD.LSP
  ;;; Fred the Beaver (le Castor), 12/12/94
  (load "init" -1)                ; cela charge quelques un de mes outils  
  (defun S::STARTUP ()
    (load "new-end" -1)           ; Redefinition de la commande FIN  
  )

L'argument -1 indique à la commande LOAD d'interrompre le processus de démarrage en cas d'erreur dans le chargement d'un fichier LISP.
Si une erreur pendant le chargement survient -1 est retourné, mais l'évaluation ne s'arrête pas. -1 peut être n'importe quelle expression.

Exemple de code qui améliore S::STARTUP dans votre code. Avec le code compilé par Visual LISP cela ne fonctionnera pas, à la place il doit être défini par DEFUN-Q. Désormais, les fonctions ne sont généralement plus des listes. Mieux que d'utiliser DEFUN-Q pour S::STARTUP, il est préférable de vérifier les appels connus, la liste des fonctions définies par l'utilisateur qui sont insérées et évaluées pendant l'exécution.

  (defun MY::STARTUP ()         ; votre code de demarrage commence ici  
    ;..
    (princ)
  )
  (setq S::STARTUP
    (if (and S::STARTUP (listp S::STARTUP))     ; deja defini dans ACAD.LSP ou ailleurs   
                                                
      (append S::STARTUP (cdr MY::STARTUP))     ; ajoute votre code  
      MY:STARTUP)                               ; juste votre code
    )

ou la manière simple :

  (if (and S::STARTUP (listp S::STARTUP))
     (setq S::STARTUP (append S::STARTUP (list func '(princ))))
     (setq S::STARTUP (list nil func '(princ))))

Voir aussi [12] Comment autocharger mes programmes ?


[12] Comment autocharger mes programmes ?

Comment charger mes programmes automatiquement ?
Vous pouvez aussi bien charger votre programme entier au démarrage (Voir [11] Mon Lisp ne se charge plus au lancement) lequel a besoin de plus de temps et de mémoire au moment du démarrage, ou bien vous pouvez les définir par le mécanisme de l'autochargement.
Avec les programmes R14 ARX, utilisez un nouveau schéma d'autochargement avec quelques réglages de registre et non plus par ACADRxx.LSP.

Regardez à la fin d'ACADRxx.LSP comment AutoCAD autocharge ses programmes.

  ;;;===== AutoLoad LISP Applications =====
  ...
  (autoload "dline" '("dline" "dl"))
  ...

Ceci définit les commandes DLINE et DL dans la liste qui doit être chargée depuis le fichier DLINE.LSP quand l'utilisateur appelle les commandes DLINE ou DL pour la première fois. Avant cela, la fonction est définie simplement comme suit :

  (defun C:DL () (load "DLINE")(C:DL)) 

En fait la définition est plus compliquée à cause de la gestion des erreurs : Ctrl-C, erreurs de chargements, mauvais fichier ou chemin.

Après le premier appel, la fonction est écrasée par la définition dans le programme.

Avantages de l'autochargement :
Le démarrage est plus rapide, parce que vous n'avez pas à charger tous vos fichiers Lisp. Vous définissez la définition toute simple d'emballage comme ci-dessus. Ce qui est fait par la fonction (autoload).
Vous avez besoin de moins de mémoire.

Les inconvénients :
S'il y a des erreurs dans vos programmes vous tomberez dans une boucle sans fin, qui ne s'arrêtera seulement qu'après un débordement de pile ou par Ctrl-C.
Note: avec du code compilé par ACOMP, même Ctrl-C est impossible. Insérez alors quelque part un appel à un (princ) non compilé.
Vous devez définir et maintenir tous les noms de commandes de votre programme dans la définition de l'autoloader. Tout changement dans le nom des fichiers lisp ou dans le nom des commandes provoquera l'erreur ci-dessus.

Où placer vos définitions (autoload) ?
Pas dans ACADR14.LSP. Nous vous recommandons instamment de les mettre dans votre fichier d'initialisation et non pas dans ACAD.LSP parce que celui-ci est souvent modifié par différentes applications et ACAD.LSP doit être maintenu plutôt petit.
C.-à-d. mettez-les dans un AUTOLOAD.LSP ou INIT.LSP qui sont chargés par ACAD.LSP. Voir [11] Mon Lisp ne se charge plus au démarrage


Il devrait être mentionné que les utilisateurs *ne doivent pas* modifier ACADRxx.LSP. Si ACAD.LSP n'est pas surchargé pendant les mises à jour, il est garanti de rester sain. De plus (comme nous avons vu avec le patch R13c4a) si le fichier ACADR13.LSP a été modifié, alors le processus du patch peut refuser la mise à jour, et donc provoquer des fonctionnements défectueux du programme.


[13] Comment passer un nombre variable d'arguments à une fonction Lisp ?

Avec du pur AutoLISP ce n'est pas possible.

Soit vous pouvez passer tous vos arguments dans une liste comme ceci :

  ;;; affiche un nombre variable d'arguments (de tout type)  
  (defun my-princ (x)
    ;; simple version, pour en savoir plus voir SDK2,: PRINTF.LLB  
    (if (listp x)
      (mapcar 'princ x)
      (princ x)
    )
  )

Soit vous devez définir la fonction en ADS et l'exporter dans AutoLISP. Alors vous êtes libre d'écrire :

   (ads-print "Hello " "Monde " 1 2 3) 
ou même
   (ads-printf "Hello %s %i %i" "Monde" 2 3) 

Regardez les exemples ADS de Reini Urban et de Vladimir Nesterovsky à http://xarch.tu-graz.ac.at/autocad/ads/ pour les mises en œuvre des exemples ci-dessus.

Des vœux officiels ont été formulés à Autodesk concernant &optional comme renchérissement du langage AutoLISP, mais cela n'a pas été implanté pour l'instant.


[14] Comment éviter des débordements de pile (stack overflows) ?

Dans le vieil AutoLISP la dimension de la pile était codée hard. Elle ne pouvait pas être étendue, mais sa dimension devait être suffisante dans la plupart des cas. Dans l'IDE (environnement de développement intégré) Visual Basic
le débordement de pile est simulé à 984 récursions ; sur la ligne de commande A2000 ou dans les programmes chargés en dehors de l'IDE, il n'y a plus de débordement de pile. Ceci est dangereux pour vos propres erreurs de récursivité - Voir [9]. La plupart des erreurs de débordements de pile apparaissent dans une erreur de vos programmes et préviennent le système qu'il va tomber dans une boucle sans fin, ou si vous utilisez des fonctions récursives sur des grandes listes. Par conséquent vous êtes limité aux listes courtes avec les fonctions récursives et les vieilles versions.

Vous ne pouvez pas diminuer votre dimension de pile utilisée en prenant moins de paramètres locaux dans votre fonction récursive. Cependant n'utilisez pas APPLY, EVAL ou MAPCAR pour appeler votre fonction récursivement, parce qu'ils mangent la pile. Utiliser la 'queue' de la récursivité n'aide pas non plus.

Vous devez convertir votre fonction récursive en fonction itérative. (Il y a un théorème mathématique qui dit, que chaque fonction récursive peut être convertie en une fonction itérative, et même automatiquement pour les 'queues' de récursivité.) Les versions itératives peuvent utiliser des fonctions du type pile comme (push) et (pop), mais ces versions stockent la pile sur le tas (espace nodal d'AutoLisp), laquelle dimension est limitée par la quantité de votre mémoire virtuelle disponible.

Vous pouvez tester le débordement de pile avec cette simple fonction :

  ;;; creez une liste de nombres n (base zero) 
  (defun intlst (l n)
    (cond ((zerop n) l)
          (T (intlst (cons (1- n) l) (1- n)))
    )
  )
  et essayez  : 
  (setq n 100)(while (intlst nil (setq n (+ 10 n)))(print n))

Avec l'AutoLISP de la version R12/DOS vous atteignez la limite de pile avec (intlst nil 138), avec la R13/Win il faut (intlst nil 240), avec les bi4 d'ACOMP on obtient (intlst nil 1240), et avec Vital Lisp IDE on aura (intlst nil 984).
Avec R10c10, les premières versions dos de lisp étendu, vous pouviez rehausser la dimension de la pile du lisp avec la variable d'environnement LISPSTACK et ACOMP pour R10 avait la variable COMPSTACK. Avec Vital LISP ou Visual LISP RTS ou A2000 (en dehors de l'IDE) la dimension de la pile est illimitée.

La conversion à une version itérative produit les résultats demandés :

(defun intlst (n / l)
  (repeat n
    (setq l (cons (setq n (1- n)) l)) ; ceci n'est pas tres beau mais ca fonctionne  
  )
)


[15] (command " ROTATE3D ") ne fonctionne pas ! Pourquoi ?

Quelques commandes ne sont pas des commandes internes à AutoCAD, ce sont de simples programmes AutoLISP commençant par C: même s'ils sont définis dans les programmes ADS. Seules les applications natives Rx (et maintenant vlax-add-cmd) exportent de vraies commandes.

Une liste de toutes ces commandes se trouve dans ACADR13.LSP dans la section AUTOLOAD (voir aussi "[12]")
Toutes ces commandes doivent être appelées avec (C:ROTATE3D) au lieu de (command "ROTATE3D").

Cependant les fonctions ADS peuvent prendre des arguments facultatifs. Voir le manuel de personnalisation pour plus de détails.
c.-à-d. (c:rotate3d ss p1 p2 angle) est également valide, même (rotate3d ...)


[16] Les programmes LISP qui opèrent sur de multiples dessins

"J'ai un problème à partir d'un fichier lisp qui doit ouvrir un dessin et continuer à tourner. Une fois que le nouveau dessin est ouvert le fichier lisp cesse d'exister dans la mémoire Autocad. Il doit être rechargé pour reconnaître les commandes."

La mémoire du Lisp est rechargée avec chaque dessin. Il y a plusieurs façons d'exécuter un Lisp sur des dessins multiples :

  1. par un script qui s'exécute sur des fichiers multiples.
         MYSCRIPT.SCR.
         (load "monlisp")
         _QSAVE _OPEN !nextdwg
         (load "monlisp")
         _QSAVE _OPEN !nextdwg
         ...
      
  2. Un logiciel externe tel que RunLisp ou DDSCRIPT qui automatisent la partie 1.
  3. R14 possède une nouvelle caractéristique, appelée 'LISP Persistant.'
    A installer par Préférences-Compatibilité-Lisp Persistant
  4. Vital Lisp possède une variable spéciale pour agir comme Lisp Persistant :
    (setq *VILL-NEW-FULL-INIT* nil) ; conserve les symboles entre les sessions
  5. VLISP le renomme en *VLISP-NEW-FULL-INIT*


[17] Comment exporter les fonctions Visual Lisp dans AutoLISP/AutoCAD ?

Les fonctions C: sont exportées dans AutoLISP automatiquement. Les fonctions ordinaires Vlisp/vill doivent être exportées aussi bien avec (vl-acad-defun funcname) que par leurs symboles qui peuvent être exportés avec un compilateur special pragma, définis dans le fichier LSP ou dans le fichier GLD (déclarations globales). Mieux vaut utiliser des préfixes spéciaux pour de telles fonctionns.

.GLD 
(AUTOEXPORT-to-ACAD-PREFIX  
  ; | prefixes de nom pour les fonctions qui doivent etre autoexportees dans AutoCAD: (chaines) |; 
  " myx- *"  
  )  
  
ou un par un
.LSP
(pragma '((export-to-acad myx-func1 myx-func2)))  
  
Note: Il peut exister des bugs connus dans vlisp et vill avec les listes de symboles d'atomes et listes de paires pointées dans de tels arguments de fonctions et dans les valeurs de retour. (Voir "[7]")

Les fonctions exportées par des applications externes et utilisées dans votre application doivent être définies via XDF.

Les symboles (variables) dont les valeurs sont mises à jour dans Visual Lisp et dont les valeurs sont également utilisées dans AutoLISP ou AutoCAD (le menu par exemple), doivent, en premier lieu été marqués par le compilateur comme devant être externes avec:

  (pragma ' ((not-localize myx:symbol)))   
mais la valeur doit être exportée avec
  (vlisp-export-symbol 'myx:symbol)  
Chaque fois que la valeur est changée dans Visual Lisp, le contrôle est rendu à AutoCAD pour pouvoir obtenir la dernière valeur dans AutoLISP ou dans AutoCAD avec !myx:symbol

Dans AutoCAD 2000, c'est plus simple. Cependant vous devez alors exporter votre fonction avec VL-DOC-SET.
Voir également http://www.autodesk.com/support/techdocs/td17/td175363.htm


2ème partie : Exemples, Code


[20] Aide générale sur les fonctions

Pour les fonctions AutoLISP les plus générales, prière de consulter la bibliothèque "the AutoLISP Standard Library" sur le site http://xarch.tu-graz.ac.at/autocad/stdlib/ D'autres codes sont disponibles sur certains sites AutoLISP[1] ou inclus dans les SDK's par AutoDESK [1.2]

J'ai inclus ici quelques aides très utiles sur les fonctions données pour de courts exemples dans des réponses sur le net.
Vous pouvez compter sur le fait que ces fonctions sont partie du domaine public tels que la célèbre fonction dxf qui est définie par
(defun dxf (grp ele) (cdr (assoc grp ele))) et le compteur spécifique (getval) qui fonctionne aussi bien avec un ename qu'avec une liste entget.

[20.1] Manipulation de liste (nouvelles fonctions)

Voir aussi http://xarch.tu-graz.ac.at/autocad/stdlib/stdlist.lsp

Exemples utiles de fonctions pour manipulation de liste :

  ;;; une liste non vide ?
  (defun consp (x) (and x (listp x)))

  ;;; Retourne l'index du premier element dans la liste,
  ;;; base 0, ou nil si non trouvé
  ;;;   (position 'x '(a b c)) -> nil, (position 'b '(a b c d)) -> 1
  (defun position (x lst / ret)
    (if (not (zerop (setq ret (length (member x lst)))))
      (- (length lst) ret))
  )

  ;;; Enlève un article d'une liste (les éléments en doubles sont permis)
  ;;;   (remove 0 '(0 1 2 3 0)) -> (1 2 3)
  (defun remove (ele lst)      ;  par Serge Volkov
    (apply 'append (subst nil (list ele) (mapcar 'list lst)))
  )

  ;;; Enlèvement conditionnel d'un article dans une liste simple
  ;;; fun demande exactement 1 argument
  ;;;   (remove-if 'zerop '(0 1 2 3 0)) -> (1 2 3)
  ;;;   (remove-if 'numberp '(0 (0 1) "")) -> ((0 1) "")
  (defun remove-if (fun from)
    (cond
      ((atom from) from)       ;nil or symbol (return that)
      ((apply fun (list (car from))) (remove-if fun (cdr from)))
      (t (cons (car from) (remove-if fun (cdr from))))
    )
  )

  ;;; Conserve tous les éléments auxquels l'attribut s'applique
  ;;; disons : " conserve si ", doit être défini récursivement, comme ceci.
  ;;; [deboggé, merci à Serge Pashkov. C'était bon dans FAQ-CODE.lsp]
  (defun remove-if-not (pred lst)        ; par Vladimir Nesterowsky
    (apply 'append 
              (mapcar '(lambda(e) 
                     (if (apply pred (list e)(list e))) lst)
              )
    )

  ;;; Ajoute un élément dans une liste s'il n'y est pas déjà 
  ;;; astuce : accepte des listes quotées aussi, tel que
  ;;;  (setq l '(1 2 3) (adjoin 0 'l)
  ;;;  -> !l (0 1 2 3)
  (defun adjoin (ele lst / tmp)
    (if (= (type lst) 'SYM) (setq tmp lst lst (eval tmp)))
    (setq lst (cond ((member ele lst) lst)
                    (t (cons ele lst))))
    (if tmp (set tmp lst) lst)
  )
  ;;;  ROT1 - mettre le premier élément à la fin, version simple,
  ;;;        (rotation par un)
  (defun rot1 (lst) (append (cdr lst) (list (car lst))))

  ;;;  BUTLAST - la liste sans le dernier élément
  (defun butlast (lst)
    (reverse (cdr (reverse lst)))
  )

[20.2] Manipulation de chaîne

SVP, essayez http://xarch.tu-graz.ac.at/autocad/stdlib/stdstr.lsp

Quelques fonctions de chaîne utiles :

(stringp expr)
- type chaîne, est-ce que expr est une chaîne ?
    (defun stringp (s) (= (type s) 'STR))
(string-not-emptyp str)
- est-ce que str est une chaîne non vide ?
  (defun string-not-emptyp (s) (and (stringp s) (/= s "")))
 
(str-trim string)
- str sans aucun espace, à droite, et à gauche, également défini dans AI_UTILS.LSP, comme :
(str-left-trim string), (str-right-trim string),
(str-left-trim-bag string bag), (str-right-trim-bag string bag)
- retire tous les caractères de bag (= STR)
(strpos string substr)
- position d'une sous-chaîne dans une chaîne (base 1)
(strtok str tokens)
- chaîne -> liste délimitée par tokens
(strlcat lst delim)
(string->list str)
- string -> liste de caracteres
-> liste de caractères
(list->string str)
- liste de caracteres -> chaine
-> liste de caractères
Quelques-unes des fonctions sont à http://xarch.tu-graz.ac.at/autocad/code/vnestr/strtok.lsp ou dans votre AI_UTILS.LSP. Vous aurez besoin d'elles spécialement pour les fonctions DCL.

[20.3] symbole - chaîne

La fonction inverse à (read) serait (symbol-name). Ce qui suit est la bonne voie générale à suivre, mais il existe des méthodes spéciales qui sont meilleures.
  ;;; SYMBOL-NAME - retourne le nom d'un symbole sous forme de chaine
  ;;; convertit toute expression  valide de lisp en representation affichable
  ;;; (symbol-name a) -> "a",  (symbol-name '(0 1 2 a)) -> "(0 1 2 A)"
  (defun symbol-name (sym / f str tmp)
    (setq tmp "$sym.tmp")      ; nom de fichier temporaire , devrait etre efface
    (setq f (open tmp "w"))(princ sym f) (close f)
    (setq f (open tmp "r") str (read-line f) f (close f))
    str
  )

Pour les symboles ordinaires une meilleure astuce expliquée par Christophe Candido existe à http://xarch.tu-graz.ac.at/autocad/news/symbol-string.txt
Vill/vlisp a amené une fonction rapide vl-symbol-name.
Voir aussi http://xarch.tu-graz.ac.at/autocad/stdlib/stdinit.lsp

[20.4] Accès aux entités AutoCAD [renommé SSAPPLY en SSMAP]

Voir aussi http://xarch.tu-graz.ac.at/autocad/stdlib/STDENT.LSP
  ;;; retourne la premiere valeur du groupe d'une entite.
  ;;; comme la fonction renommee (dxf)  mais accepte tous les genres de
  ;;; representations de l'entite (ename, les listes entget, les listes entsel)
  ;;; NOTE:  N'est pas utilisable pour obtenir 10 groupes dans LWPOLYLINE !
  (defun GETVAL (grp ele)                 ; " valeur dxf" de tout entite.
    (cond ((= (type ele) 'ENAME)          ; ENAME
            (cdr (assoc grp (entget ele))))
          ((not ele) nil)                 ; valeur vide
          ((not (listp ele)) nil)         ; element invalide
          ((= (type (car ele)) 'ENAME)    ; liste entsel
            (cdr (assoc grp (entget (car ele)))))
          (T (cdr (assoc grp ele)))       ; liste entget
    )
  )
  ;;; Ex: (gettyp pline) => "POLYLINE"
  (defun GETTYP (ele)                     ; retourne le type
    (getval 0 ele)
  )

  ;;; assurez ENAME
  ;;; convertit l'entite en type ENAME (pour ecrire du code plus compact)
  (defun ENTITY (ele)                     ; convertit en nom de l'element
    (cond                                 ; accepte les types suivants :
      ((= (type ele) 'ENAME) ele)             ; ENAME
      ((not (listp ele)) nil)                 ; erreur: aucune liste
      ((= (type (car ele)) 'ENAME) (car ele)) ; liste entsel
      ((cdr (assoc -1 ele)))                  ; liste entget ou nil
    )
  )
  ; et maintenant juste :
  (defun getval (grp ele) (cdr (assoc grp (entget (entity ele)))))

  ;;; Ex: (istypep ele "TEXT")
  ;;; est-ce que l'element est un "SOLID" ?
  (defun istypep (ele typ)                   ; teste le type
    (= (gettyp ele) typ)
  )

  ;;; Ex: (istypep ele '("TEXT" "ATTDEF"))
  ;;; is element a "TEXT" or a "ATTDEF"?
  (defun ISTYPEP (ele typ) ; meilleure implementation pour accepter des listes egalement
    (cond
      ((listp typ)   (member (gettyp ele) typ)) ; fige
      ((stringp typ) (= (gettyp ele) typ))      ; suppose typ en majuscules, wcmatch
      (T nil)                                   ; serait bien mais plus lent
    )
  )
  ;;; Ex: (getpt (entsel))  => ( 0.1 10.0 24)
  (defun GETPT (ele)    ; retourne le point de depart de tout element
    (getval 10 ele)     ; groupe 10
  )

  ;;; Ex: (getflag pline)  => 1 si fermé
  (defun GETFLAG (ele) (getval 70 ele)) ; idem avec le drapeau de l'entite;

  ;;; bitvalue val in flag of element set?
  ;;; Ex: (flagsetp 1 pline)   => T si fermee
  ;;; Ex: (flagsetp 16 vertex) => T si un point de controle spline
  (defun FLAGSETP (val ele)
    (bitsetp val (getflag ele))
  )

  ;;; Ex: (bitsetp 4 12) => T   ; met la valeur du bit 4 (=2.Bit) a 12 (=4+8) 
  (defun BITSETP (val flag)
    (= (logand val flag) val)
  )

  ;;; Convertit le jeu de selection en liste. Lent mais facile a ecrire.
  ;;; Note: Il est egalement sage d'utiliser ai_ssget, parce que quelques entites 
  ;;;       pourraient être sur des calques verrouilles.
  ;;; Ex: (sslist (ai_ssget (ssget))) => liste d'entites selectionnees et deverrouillees
  ;;; ou  (mapcar 'entupd (sslist (ssget "X" '((8 . "TEMP")))))
  ;;;       - regenere toutes les entites sur le calque TEMP
  (defun SSLIST (ss / n lst)
    (if (= 'PICKSET (type ss))
      (repeat (setq n (sslength ss))
        (setq n (1- n)
              lst (cons (ssname ss n) lst)
        )
      )
    )
  )

  ;;; appliquez une fonction a chaque entite de ss, dans un ordre renverse,
  ;;; Plus rapide, mais pas si facile a comprendre. Voir [22.2].
  ;;; [renommé de SSAPPLY en SSMAP pour se conformer au nom de stdlib]
  ;;; Ex: (ssmap 'entupd (ssget))  ; regenere seulement quelques entites
  (defun SSMAP (fun ss / n)
    (if (= 'PICKSET (type ss))
      (repeat (setq n (sslength ss))
        (apply fun (list (ssname ss (setq n (1- n)))))
      )
    )
  )


[21] Exemples de programmes en Lisp :

[21.1]Changement global de textes, polylignes, utilitaires de calques, dateur

Pour changer les attributs de texte globalement utilisez CHTEXT.LSP dans votre répertoire SAMPLE

Pour changer globalement les attributs d'une polyligne, geler les calques en cliquant et autres tâches semblables ou rechercher des outils lisp gratuits sur n'importe quel site AutoLISP. Voir [1] et quelques codes à [22], [23], et [24].

Pour mettre automatiquement un "tampon dateur" et autres sur vos sorties traceur, en premier lieu vérifier si votre traceur supporte HPGL/2. Ensuite utilisez le driver HPGL/2 interne et configurer le "tampon dateur" dans HPCONFIG.

DATESTAMP.LSP: Changez vous-même les attributs de l'en-tête du plot comme dans [22.2]. Une routine plotstamp se trouve à : http://ourworld.compuserve.com/homepages/tonyt/plotstmp.htm

[21.2] Dialogue pour sortie traceur dans le lisp. En utilisant DDE, ActiveX ou Initdia

Depuis la R14, utilisez INITDIA
(initdia)(command "_PLOT")

Avant la version R14, pour appeler la boîte de dialogue du TRACEUR, ce n'était seulement possible que sous Windows c.-à-d. avec LISPPLOT par Mike Dickason. Cela alimente le buffer du clavier avec les touches. Voir http://www.cadalog.com/cadalog/files/lispd-l/lspplw.zip ou aussi : ftp://ftp.mcwi.com/pub/mcwi/lisp/winplt.lsp
Autrement, créez un script et appelez-le à la fin de votre lisp, mais cela ne vous affichera pas la boîte de dialogue.

Xiang Zhu : Vous pouvez utiliser "ddelisp.exe" sous Windows en faisant quelque chose comme ce qui suit :
  ;;; [modifie pour toutes versions]
  (defun DDECMD (str / tmp acadver ddestr)
    (if (not (boundp 'initiate))
      (cond
        ((= 14 (setq acadver (atoi (getvar "ACADVER"))))
         (setq ddestr "AutoCAD.R14.DDE") (arxload "ddelisp"))
        ((= 13 acadver)
         (setq ddestr "autocad.r13.dde") (xload "ddelisp"))
        ((= 12 acadver)
         (setq ddestr "autocad.dde") (xload "ddelisp"))
        (T (princ "DDE not supported")(exit))
      )
    )
    (if (not (zerop (setq tmp (initiate ddestr "system"))))
        (progn
          (execute tmp (strcat "[" str "]"))
          (terminate tmp)
          str
        )
    )
  )
Pour R12 utilisez "autocad.dde" comme nom de serveur. Puis à l'intérieur de votre lisp ou script, vous pouvez faire (ddecmd "_plot "). La fonction DDECMD retournera nil si quelque chose ne va pas, ou la chaîne que vous avez passée en cas de succès. La chaîne est identique à ce vous écrivez au clavier en réponse aux messages de commande ; Vous devez donc mettre un espace ou un retour chariot qui est un "^13" dans ce cas, pour terminer la chaîne.

En plus, la fonction est très utile dans la situation suivante : Si dans un lisp, vous avez besoin d'appeler une commande transparente comme CALQUE, normalement vous utiliserez (command "_layer"), mais après utilisation de cette ligne, le lisp ne sera pas transparent. En utiliser la fonction, ceci résoudra ce problème.

Attention : Méfiez-vous car Acad n'accepte seulement que les commandes DDE si la ligne de commande est active, cela veut dire qu'aucune boîte de dialogue ne doit être ouverte.

Avec vlisp/ViLL les méthodes ActiveX peuvent être utilisées pour tracer mais la boîte de dialogue ne peut être appelée :

  ;;; syntaxe vlisp :
  (setq vlax:ActiveDocument (vla-get-ActiveDocument (vlax-get-Acad-Object)))
  (setq plt (vla-get-plot vlax:ActiveDocument))   ;=> objet plot 
  (vla-PlotWindow plt pt1 pt2)                    ; definition de la fenetre (pts dans le SCG)
  (vla-PlotPreview plt 1)                         ; 0 pour partiel, 1 pour total
  (vla-PlotToDevice plt "Default System Printer") ; s'il existe
Avec R14, INITDIA a été introduit et peut s'appliquer à presque toutes les boîtes de dialogues (mais pas à toutes) :
(initdia)(command "_PLOT") Avec A2000 utilisez OLE (les méthodes VLA-) au lieu de DDE.

[21.3] (entmod) et (entmake) pour les calques, sans (command " _LAYER "...)

ENTMOD un calque
J'essaie de changer une propriété d'un calque sans appeler la fonction COMMAND à l'intérieur d'une routine lisp.

Depuis R13, utiliser le lisp suivant
    (setq tbl_lst (entget (tblobjname "LAYER" ""CALQUE_QUELCONQUE"))
          clr_grp (assoc 62 tbl_lst)
    )
    (entmod (subst (cons 62 (- (cdr clr_grp))) clr_grp tbl_lst))
Vous pouvez intervertir "CALQUE_QUELCONQUE" On ou Off, même si c'est le calque courant.

Mais AutoCAD ne sait pas qu'une entrée de la table a été changée jusqu'à ce que vous cliquiez sur le Contrôle des Calques, sur la barre des outils ou sur quelque chose de semblable. En plus, vous pouvez effectuer 'DDLMODES pour voir si la propriété On/OFf de "CALQUE_QUELCONQUE" a changé.
Agissez de la même façon pour geler un calque, vous verrez encore des entités sur ce calque affiché à écran, mais vous ne pouvez pas les sélectionner, jusqu'à ce que vous fassiez quelque chose en relation avec le contrôle des calques, et alors, AutoCAD cachera ces entités.

ENTMAKE un calque
Vous devez obtenir votre modèle avec entget et utiliser le nom d'objet de la table comme argument. Ce nom d'objet de la table peut être retrouvé avec la fonction TBLOBJNAM :
    (entget (tblobjname "LAYER" "Un calque quelconque")) ; R2000 accepte les espaces !

  ;;; Cette routine créera une calque avec n'importe quel nom vous taperez  
  (defun c:mlay ()      		; par Reinaldo Togores 
    (setq laynam (getstring "\nNom du calque : "))
      (entmake
        (list
          '(0 . "LAYER")
          '(5 . "28")
          '(100 . "AcDbSymbolTableRecord")
          '(100 . "AcDbLayerTableRecord")
          (cons 2 laynam)
          '(70 . 64)
          '(62 . 7)
          '(6 . "CONTINUOUS")
      )
    )
  )
[21.4] Comment sélectionner de multiples fichiers en Lisp ? (comme dans Utilitaires de fichiers - Déverrouiller)

[21.5] Remplacer des blocs multiples

Une recherche dans les archives du lisp a donné :
Cadalyst: http://www.cadonline.com/search.phtml
=> 97code.htm et une question pour votre nom d'utilisateur qui peut être obtenu gratuitement et automatiquement
xarch: http://xarch.tu-graz.ac.at/autocad/code et cherchez "BLOCK;REPLACE"
=> http://xarch.tu-graz.ac.at/autocad/code/cadalyst/94-02/replace.lsp
également à Cadalog :
http://www.cadalog.com/find.htm Mot-clé :"Block Replace"
=> http://www.cadalog.com/cadalog/files/lispr-z/replace.zip (celui-ci est le meilleur)

[21.6] (vports), entité VIEWPORT, conversion de pixels
L'entité VIEWPORT :
La réponse à la remarque "Je peux faire un (entget) sur un VIEWPORT et obtenir son coin bas gauche (DXF groupe 10) et le coin haut droit (DXF groupe11). Mais il apparaît que ces coordonnées sont dans le système de l'espace papier. Ce qui m'intéresse c'est de trouver quelle est la portion du "vrai" dessin (dans l'espace objet) qui est actuellement montrée dans cette vue" se trouve à http://xarch.tu-graz.ac.at/autocad/news/vports.lsp

http://www.ez-sys.net/~coopfra/lisp.htm#view contient aussi quelques astuces.

Comment changer les viewports en AutoLISP ?
Avec (setvar "CVPORT" vport-id)
Voir http://xarch.tu-graz.ac.at/autocad/news/change_vports.html

Avec les fonctions suivantes vous convertissez les pixels <->unités dessin :
;;; Conversion  de pixel en unités dessin  
(defun PIX->UNITS (pix)
  (* pix (/ (getvar "VIEWSIZE") (cadr (getvar "SCREENSIZE"))))
)

;;; Conversion d'unités dessin en pixels  
(defun UNITS->PIX (units)
  (* units (/ (cadr (getvar "SCREENSIZE"))(getvar "VIEWSIZE")))
)

Notez aussi les erreurs "Pixel Off by One" dans AutoCAD, écrit par Vibrant :
http://xarch.tu-graz.ac.at/autocad/news/pixel-off-by-one-error.txt

[21.7] Sélectionner tous les objets visibles : les coordonnées du zoom
Méfiez-vous qu'avec (ssget) vous obtiendrez uniquement les objets visibles, parce que toutes les fonctions d'interface (entsel,ssget,osnap) travaillent avec les pixels, seul (ssget "X") sélectionnera des objets non visibles.
;;;retourne une liste des coins de la vue actuelle dans le SCG  
(defun zoompts ( / ctr h screen ratio size size_2)
  (setq ctr (xy-of (getvar "VIEWCTR")) ; 3D -> 2D
        h   (getvar "VIEWSIZE")        ; reel
        screen (getvar "SCREENSIZE")   ; 2D: Pixel x,y
        ratio (/ (float (car screen))  ; rapport aspect  
                 (cadr screen))
        size (list (* h ratio) h)      ; taille de l'ecran en coordonnees  
        size_2 (mapcar '/ size '(2.0 2.0)))
  (list (mapcar '- ctr size_2)
        (mapcar '+ ctr size_2)
  )
)

(defun xy-of (pt) (list (car pt)(cadr pt)))   ; assure coordonnées 2D  
Note: Les points retournés sont dans le système de coordonnées générales (SCG) mais c'est correct, parce que les options "CP", "WP" et "P" de ssget attendent des points du SCG. "W" et "C" exigent des points du SCU - Pourquoi cette différence ? va savoir !
;;; une facon de definir cette fonction  
(defun ssall-visible (/ l)
  (ssget "C" (car (setq l (maptrans0-1 (zoompts)))) (cadr l))
)
;;; et une autre  
(defun ssall-visible-1 ()      ; combine "C" et (p1 p2)  dans une liste  
  (apply 'ssget (append '("C") (maptrans0-1 (zoompts))))
)

;;; Etablit quelques points du SCG  dans le SCU, plus facile avec seulement un argument  
(defun maptrans0-1 (pts)(mapcar '(lambda (pt)(trans pt 0 1)) pts))

[21.8] Comment écrire des coordonnées XYZ d'objets sélectionnés dans un fichier ?
  ;;; CDF - la chaine est delimitee par une virgule  
  (defun cdf-point (pt)
    (strcat (car pt) ", " (cadr pt) ", " (caddr pt))
  )
  ;;; SDF - l'espace est le delimiteur, peut etre relu plus facilement dans AutoCAD   
  (defun sdf-point (pt)
    (strcat (car pt) " " (cadr pt) " " (caddr pt))
  )
  ;;; Reconvertir ces formats SDF en un point avec :  
  (defun str->point (s)
    (eval (read (strcat "(" s ")")))
  )

  ;;; Ecrire un fichier XYZ de tous les objets selectionnes ( voir ci-dessous SDF)  
  (defun C:XYZ (/ ss fname f)
    (if (and (setq ss (ssget))
          (setq fname (getfiled "Ecrire les coord. XYZ dans un fichier"
                  (strcat (getvar "DWGNAME") ".XYZ") "XYZ" 7))
          (setq f (open fname "w")))
      (foreach ele (sslist ss)          ; -> [20.4]
        (foreach pt (getpts ele)        ; -> [23.1]
          (write-line (cdf-point pt) f)
        )
      )
    )
    (if f (close f))
  )
  ;;; => .xyz
  ;;; 0.45, 12.3, -34.0

Pour un fichier ASC (format SDF) changer simplement tous les XYZ en ASC et les points cdf en points sdf ci-dessus.

Pour l'autre moyen, en créant des PLINES à partir d'un fichier ascii avec des x,y le mieux est de convertir le fichier en script comme ceci :
PLINE
300.2,10
350.4,10.4


[22] Attributs de bloc

[22.1] Comment accéder aux attributs d'un bloc ?
Testez toutes le sous-entités après l'INSERT jusqu'à ce que l'attribut soit trouvé. Voir à xarch.tu-graz.ac.at/autocad/stdlib/STDENT.LSP
;;; retourne la liste d'enget des attributs (chaine) dans l'element b (ENAME)
;;; ou nil si non trouve;  
(defun ATTELE (ele attname / rslt)
  (if (and (istypep ele "INSERT")
           (= (getval 66 ele) 1))
    (progn
      (setq ele (entnext (entity ele)))
      (while (and ele (istypep ele "ATTRIB"))
        (if (= (strcase (getval 2 ele)) (strcase attname))
          (setq rslt (entget ele) ele nil)      ;break the loop
          (setq ele (entnext ele))
        )
      )
    )
  )
  rslt
)

;; Exemple :
(attele (entsel) "TEST")   ; retourne la liste entget  de  
                           ; l'attribut "TEST" si le bloc le contient.  
BTW: Les mêmes fonctions plus astucieuses pour obtenir les codes DXF des entités sont GET and EDLGETENT par Vladimir Nesterowsky.
  ;;; Exemples d'appels :  
  ;;; retourne une liste des valeurs des groupes 2,1 et -1   
  (defun get-attribs-look-up (block-ename)
    (get '(2 1 -1) (cdr (edlgetent block-ename)))
  )

  (defun all-vertices-and-bulges (pline-ename)
    (get '(10 42) (cdr (edlgetent pline-ename)))
  )
disponible à http://members.tripod.com/~vnestr/

[22.2] Comment MODIFIER des attributs de bloc ? DATESTAMP [

Effectuez simplement entmod de la liste entget de l'attribut DATE de votre bloc tampon retournée par (attele) comme ci-dessus.
;;; change la valeur de l'attribute en new, groupe 1
(defun ATTCHG (ele attname new / b)
  (if (setq b (attele ele attname))
    (entmod (subst (cons 1 new) (getval 1 b) b)))
)

;;; Changer tous les attributs du "TAMPON DATEUR" dans tous les blocs PLOT* insérés  
(defun C:DATESTAMP ()
  (ssmap                         ; debugge et renommé
   '(lambda (ele)
      (attchg ele "DATESTAMP" (today))
      (entupd ele)
    )
    (ssget "X" '((0 . "INSERT")(2 . "PLOT*")))
  ) 
)

;;; Retourne la date d'aujourd'hui (today) ; pourrait être en DIESEL ou cette conversion de  chaîne  
(defun TODAY (/ s)
  (setq s (rtos (getvar "CDATE") 2))  ; obtient la date au format julian  
  (strcat (substr s 5 2) "-" (substr s 7 2)"-"(substr s 3 2))
)
Des 'tampons dateurs" automatiques sont effectués normallement aussi bien avec RTEXT} 
  (bonus/express tools) qu'avec un traceur HPGL/2 HPCONFIG (<a2000i). 

[22.3] Comment METTRE À JOUR des attributs de bloc ?

Il existe un fichier SUPPORT\ATTREDEF.LSP pour mettre à jour les propriétés des attributs (position, calques,...) pour les blocs déjà insérés.

Sur les entités complexes vous devez effectuer (entupd) sur l'en-tête de l'entité, pour voir la mise à jour sur l'écran (force la régénération d'un élément).
;;; Exemple:
(setq s (getstring "Changer l'attribute en : "))
(attchg (attele (setq b (entsel "of block: ")) s)))
(entupd (car b))        ; le bloc, pas l'attribut

  ;;; D'autres fonctions d'aide pour obtenir l'entite principale de tout attribut  
  ;;; ou sommet  
(defun MAIN-ENTITY (ele)
  (setq b (entity b))   		; force ENAME
  (while (istypep b '("ATTRIB" "ATTDEF" "VERTEX"))
    (setq b (entnext b)))               ; boucle tant qu'il y a des sous--entites  
  (if (istypep b '("SEQEND" "ENDBLK"))
    (getval -2 b)                       ; entite complexe -> en-tête (header)  
    b                                   ; entite normale  
  )
)

[22.4] Comment "ENTMAKE" une Entité Complexe Bloc dans AutoLISP ?

Voir xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP

Il y a un exemple montrant comment utiliser des appels multiples à (entmake) pour créer l'en-tête (header) du bloc, les entités, fermer le bloc et finalement (entmake) le "INSERT". Pour les blocs anonymes méfiez-vous car seul
(setq bn (entmake '((0 . "ENDBLK")))) retourne le nom de bloc pour (entmake (list '(0 . "INSERT")'(70 . 1)(cons 2 bn) ...))


[23] Polylignes

Etant donné que LWPOLYLINE de la version R14 stocke les sommets dans une entité avec de multiples groupes 10, (assoc) ne fonctionne pas.

[23.1] Comment accéder aux sommets (VERTICES) d'une polyligne ?
Un sommet (VERTEX) de polyligne est une sous-entité de POLYLIGNE (tout comme un ATTRIBUT est une sous-entité d'un élément INSERT ou un ATTDEF d'un BLOC). Par conséquent les mêmes fonctions comme dans [22.1]-[22.3] peuvent être utilisées.
;;; retourne seulement quelques valeurs associées dans la liste (pour LWPOLYLINE)  
(defun group-only (grp lst)
  (mapcar 'cdr (remove-if-not '(lambda(pair)(= grp (car pair))) lst))
)

;;; retourne la liste des sommets d'une polyligne ou de tout autre element  
(defun GETPTS (ele / pts)
  (setq ele (entity ele))               ; force le type ENAME
  (cond
    ((istypep ele "POLYLINE")
      (while (istypep (setq ele (entnext ele)) "VERTEX")
        ;; omettre les points spline (style conservateur)  
        (if (not (or (flagsetp 1 ele) (flagsetp 8 ele))) ;bugfix!
          (setq pts (cons (trans (getpt ele) ele 0) pts)))
        (reverse pts)))
      ;; Cas special: vous devez la tracer, assoc trouve uniquement le premier.  
      ;; Repare un bug LWPOLYLINE en R14: stocke en interne  comme point 2D,  
      ;; (entget) retourne des valeurs en Z fantaisistes.  
    ((istypep ele "LWPOLYLINE")
      (mapcar '(lambda(pt)(trans (list (car pt)(cadr pt) 0.0) ele 0))
               (group-only 10 (entget ele))))
    ;; inserez ici d'autres types possibles, tels que  
    ((istypep ele '("TEXT" "CIRCLE")) (list (getpt ele)))
    ;; davantage comme ceci (le style de Serge), code LWPOLYLINE ci-dessus.
    (T (apply 'append (mapcar
      '(lambda (n / p) (if (setq p (getval n ele)) (list p)))
      '(10 11 12 13)))
    )
    ;; ou comme ceci (style conservateur)  
    ;;(T (foreach n '(10 11 12 13)
    ;;     (if (setq p (getval n ele)) (setq pts (cons p pts))))
    ;;  pts
    ;;)
  )
)

Suggestions de Vladimir Nesteroswky pour une structure de sommet différente: Voir [22.1]
(defun vertices-and-bulges( pline-ename )
 (mapcar
   'cdr
   (remove-if-not '(lambda(ele) (bitsetp 9 x))
         (get '(70 10 42) (cdr (edlgetent pline-ename))
=> liste de paires (10 42) de la polyligne 

;;; qui peut egalement s'ecrire comme suit :
(defun flag9p (ele) (flagsetp 9 ele))) ; vrai si point spline 
  (mapcar
   '(lambda (ele)
    (remove-if-not 'flag9p (cdr (edlgetent pline-entname)))

Voir aussi [23.5] pour une forme de structure différente (segments) de polylignes.

[23.2] Comment JOINDRE de multiples lignes à des polylignes ? [figé]

Essayez simplement de joindre chaque élément en sélectionnant tout, mais méfiez-vous car sur une entité déjà jointe, on ne peut plus faire des entget, parce qu'elle est effacée.
  ;;; Cet exemple convertit tous les elements selectionnes en polylignes et  
  ;;; essaie d'en joindre le plus possible.  
 (defun C:JOINPOLY (/ ele ss)
  (foreach ele (sslist (setq ss (ssget)))     ; meilleur processus de listes  
    (if (entget ele)                          ; pas deja joint  
      (cond                                   ; (alors ce serait nil)  
        ((istypep ele '("ARC" "LINE"))
          ;; en fait vous devriez verifier ici les coordonnees en Z de lignes et le SCU egalement  
          (command "_PEDIT" ele "_y" "_j" ss "" "")   ; convertit et joint  
        )
        ((and (istypep ele '("POLYLINE" "LWPOLYLINE")) ; fige
              (not (flagsetp 1 ele))           ; non ferme  
              (< (rem (getflag ele) 128) 8))   ; ignore les mailles etc...  
          (command "_PEDIT" ele "_j" ss "" "") ; test SCU omis pour compacite 
        )
      )
    )
  )
)

[23.3] Changer la LARGEUR de multiple polylines

Avec l'aide de fonction d'aide précitée, il en est une courte :
  (defun C:POLYWID (/ wid ele)
    (initget 5)(setq wid (getdist "Nouvelle largeur des polylignes : ")) ; non negatif  
    (foreach ele (sslist (ssget '((0 . "*POLYLINE"))))     ;uniquement des Polylignes  
      (command "_PEDIT" ele "_W" wid "")
    )
  )
[23.4] Créer une polyligne ou un spline : avec (ENTMAKE) ou (COMMAND)

  1. Vous pouvez créer un fichier script avec un programme lisp et ensuite le lancer. Cela paraît être la voie la plus simple, mais des erreurs I/O (Entrées/Sorties) peuvent se produire en lisant ou écrivant le script. Si votre logiciel est commercial, il doit gérer de telles erreurs.
  2. Le deuxième moyen est de créer la liste des entités et d'utiliser ENTMAKE. Avantage: rapide, en SCG, indépendant des modes d'accrochage en cours.
    Voir xarch.tu-graz.ac.at/autocad/stdlib/ENTMAKE.LSP
  3. La troisième solution est basée sur command et mapcar. Cela fonctionne avec Polylignes, Splines ou Lignes. Les inconvénients : SCU, modes d'accrochage,
      ;;; Dessin d'une entite POLYLIGNE a partir d'une liste de points (idem avec SPLINE,  
      ;;; ou LIGNE), sur le SCU courant, avec les mode d'accrochage en cours,  
      (defun DRAW-PLINE (pts)
        (command "_PLINE")
        (mapcar 'command pts)
        (command "")
      )
      (defun DRAW-SPLINE (pts)
        (command "_SPLINE")
        (mapcar 'command pts)  
        (command "" "" "")
      )
    
    
[23.5] Comment calculer la LONGUEUR d'une polyligne ?
Il y a deux manières :
  1. l'évidente : utiliser la commande AIRE qui est assez ennuyeuse, (affichage du résultat), mais fonctionne même avec les splines.
      ;;; Additionne la LONGUEUR de tous les objets selectionnes, discutable, vous pouvez faire  
      ;;; de meme avec les simples AIRE en changeant la derniere ligne par (getvar "AREA")  
      (defun C:LEN-OF ()
        (command "_AREA" "_A" "_E")           ; additionne les objets (pour R12+R13) 
        (ssapply 'command (ssget))            ; passe tous les elements a AutoCAD  
        (command "" "")                       ; 2 fois "Entree"  
        (getvar "PERIMETER")                  ; c'est la longueur  
      )
    
  2. Faire un peu de maths, mais seulement pour les entités simples. Voici la meilleure méthode pour définir encore quelques fonctions d'aide. C'est aussi une introduction pour le prochain chapitre [24], un peu de trigonométrie de courbure pour les segments en arcs.
;;; calcul de la longueur d'une polyligne, tout simple 
(defun POLY-LENGTH (poly / seg)
  (apply '+             			; la somme de toutes les longueurs des segments  
    (mapcar
     '(lambda (seg)                             ; longueur d'un segment  
        (if (zerop (car seg))
          (distance (cadr seg) (caddr seg))     ; segment de  ligne ou  
          (abs (arclen seg seg))))              ; en courbe: -> [24]  
      (pline-segs poly)
    )
  )
)

;;; retourne tous les codes de groupe d'un élément complexe  
;;;  (sommets, attributs) comme liste, semblable à (edlgetent) 
(defun CPLX-LIST (grp ele / lst)
  (if (= 1 (getval 66 ele))
    (progn (setq ele (entnext (entity ele)))
      (while (and ele (not (istypep ele "SEQEND")))
        (setq lst (cons (getval grp ele) lst)
            ele (entnext ele)))
      (reverse lst)
    )
  )
)

;;; PLINE-SEGS - Crée une liste de segment pour le "pname" d'une polyligne  
;;; comme une liste '(courbure p1 p2). Une ligne droite a une courbure 0.0  
;;; Calcule les points dans le SCU de "pname". Accepte LWPOLYLINE  
(defun pline-segs (pname / pts segs)
  (setq segs
    (mapcar 'list
      (if (istypep pname "LWPOLYLINE")
        (group-only 42 (entget pname))
        (cplx-list 42 pname))
      (setq pts (getpts pname))
      (rot1 pts)))    ; ->[20.1]
  (if (flagsetp 1 pname)
    segs              ; ferme  
    (butlast segs)    ; ouvert: sans le dernier segment, -> [20.1]  
  )
)
;;; Exemple :   (un peu optimise pour la compacite :)  
;;; Additionne toutes les longueurs de toutes les polylignes, tranquillement,  
;;; Pour accepter aussi d'autres entites, ajoutez ceci a pline-segs  
(defun C:POLYLEN ()
  (apply '+ (ssmap 'poly-length (ssget '((0 . "*POLYLINE"))))) ; renommée
)

Pour la somme des surfaces, utilisez également la commande AIRE ou exécutez la formule de héron pour les surfaces polygonales (seulement pour les polygones simples et fermés).

[23.6] Comment INVERSER la direction d'une polyligne ?

Sergei Komarov a soumis REVPOLY.LSP qui tient compte également des courbures et des largeurs.
http://xarch.tu-graz.ac.at/autocad/news/lisp_progs/revpoly.lsp

Voici une version courte de stdlib :

;;; ignore toute information de largeur (defun POLY-REVERSE (segs) (reverse (mapcar '(lambda (seg) (std-make-seg (std-seg-p2 seg)(std-seg-p1 seg) (- (std-seg-bulge-num seg)))) segs))) (defun C:POLYREV (/ ele) (std-require "ENTMAKE") (if (setq ele (car (entsel "\nInverse Poly: "))) (std-entmake-pline (entget ele '("*")) ; conserve l'information EED (poly-reverse (std-pline-segs ele)))))
[23.7] Comment obtenir le CENTRE d'une polyligne ?

[nouveau]

Le centre de gravité d'un SOLIDE doit être extrait par PROPMECA (_MASSPROP). Vous pouvez le laisser l'écrire dans un fichier pour l'analyser ensuite. Le centre de gravité des polylignes est différent de la moyenne des vecteurs. La moyenne géométique 2D de quelques points est simple : (setq n (float (length pts))) (list (/ (apply '+ (mapcar 'car pts)) n) (/ (apply '+ (mapcar 'cadr pts)) n)) Le vrai centre de gravité est plus difficile. La version stdlib se trouve à http://xarch.tu-graz.ac.at/autocad/stdlib/STDPOINT.LSP STD-CENTROID-2D
Dans stdlib.arx ou à http://www.manusoft.com/Software/Freebies/ (sous freebies) il y a aussi une meilleure fonction lisp massprop (PROPMECA) pour les solides. Ensuite vous faites (command "_REGION" ele)...(massprop entlast)...(command "_UNDO" 1) Pour VLA il y a aussi une propriété massprop pour les objets Acis.



[24] Géométrie Cercle/Arc : Conversion de COURBURE, un peu de trigonométrie

Qu'est ce que la COURBURE (BULGE ) dans un polyligne ?

La courbure est la tangente de l'angle avant inclus d'un segment courbé. Une courbure 0.0 signifie un segment droit. Cependant avec les points de début et de fin, il y a suffisamment d'information pour calculer rapidement toute autre dimension exigée d'un segment en courbe.
Une courbure négative est une rotation en direction du sens horaire ("mathématiquement négatif").

  longueur de l'arc = rayon*angle
  courbure = +-tan( ang/4 )            (CCW: +, CW -)
  angle = 4 * atan( courbure )
  courbure = +/- ( 2*altitude ) / corde  (CCW: +, CW -)

voir aussi http://www.autodesk.com/support/techdocs/fax700/lisp/fax797.htm pour un programme d'exemple du livre "Maximizing AutoLISP" [2]

(débogué, formule fausse ! Remerciements à Sergei Komarov)

  ;;; Convertit un segment courbe (courbure pt1 pt2) d'une polyligne  
  ;;; en un cercle (ctr rad), les points de depart et de fin sont connus,  
  ;;; par consequent les angles aussi :  (angle ctr pt1)(angle ctr pt2)  
  ;;; retourne nil pour un segment rectiligne !  
  (defun SEG2CIR (seg / bulge p1 p2 cot x y rad dummy)
    (if (zerop (car seg))
      nil
      (setq bulge (car seg) p1 (cadr seg) p2 (caddr seg)
          cot (* 0.5 (- (/ 1.0 bf) bf))
          x (/ (- (+ (car  p1) (car  p2))
                  (* (- (cadr p2) (cadr p1)) cot)) 2.0)
          y (/ (+ (+ (cadr p1) (cadr p2))
                  (* (- (car  p2) (car  p1)) cot)) 2.0)
          rad (distance (list (car p1) (cadr p1)) (list x y))
          dummy (list (list x y) rad)   ; retourne ca, je deteste les progn  
      )
    )
  )

  ;;; Conversion inverse  
  ;;; calcule le segment (courbure p1 p2) d'un arc  
  ;;; avec cercle donne (ctr rad), angle de depart, angle de fin  
  (defun ARC2SEG (cir ang1 ang2 / p1 p2)
    (setq p1 (polar (car cir) ang1 (cadr cir))
          p2 (polar (car cir) ang2 (cadr cir)))
    (list (arc2bul p1 p2 cir) p1 p2)
  )

  ;;; Calcule la courbure d'un arc en ayant les points de l'arc  
  ;;; et le cercle (ctr rad)  (debogge par Serge Pashkov)
  (defun arc2bul (p1 p2 cir / ang)
    (setq ang (- (angle (car cir) p2) (angle (car cir) p1)))
    (if (minusp ang) (setq ang (+ (* 2.0 pi) ang)))
    (tan (/ ang 4.0))
  )

  ;;; Retourne l'angle de l'arc (courbure)  
  (defun bul2ang (seg / ctr)
    (- (angle (setq ctr (car (seg2cir seg))) (cadr seg))
       (angle ctr (caddr seg))
    )
  )

  ;;; ARC2ANG
  ;;; calcule angle de l'arc en donnant la longueur de la corde et le rayon 
  (defun arc2ang (chord rad)
    (* 2.0 (atan
             (/ chord 2.0
               (sqrt (- (expt rad 2)
                        (expt (/ chord 2.0) 2)
    )      ) ) )     )
  )

  ;;; Longueur d'arc = rayon*angle,  
  ;;; Note: +/-, vous aurez besoin de (abs (arclen seg)) pour la distance  
  (defun arclen (seg)
    (* (cadr (seg2cir seg))           ; rayon  
       4.0 (atan (car seg))           ; angle = 4*atan(courbure) 
    )
  )
  (setq *INFINITY* 1.7e308)                 ; largest double
  (defun tan (z / cosz)                     ; debogge
    (if (zerop (setq cosz (cos z))) *INFINITY*
      (/ (sin z) cosz)
    )
  )
  (defun dtr (ang)(* pi (/ ang 180.0)))     ; degres en radians  
  (defun rtd (ang)(/ (* ang 180.0) pi))     ; radians en degres  



[25] DCL : Boîtes de dialogue avec tabulation ou police de caractères monospace

Sous Windows c'est difficile de disposer les textes à cause des polices non-monospaces.

Essayez avec les attributs de tabulations dans la disposition de la list_box tel que :

    tabs = "0 20 40";
    (set_tile "listbox" "Layer:\t0\twhite")
ou essayez ce qui suit pour utiliser des caractères monospaces, avec l'attribut 'fixed_width_font' :
      : list_box {
          label = "Drawing";
          key = "dwglist";
          width = 50;
          fixed_width_font = true;   // <- monotexte
      }
Jetez aussi un coup d'oeil à la routine detab à xarch.tu-graz.ac.at/autocad/news/detab.lsp ou à STD-DETAB dans xarch.tu-graz.ac.at/autocad/stdlib/STDSTR.LSP pour convertir les tabulations en espaces.


[26] EED - Données d'Entité Étendue : Sélection, Obtention et Stockage

[26.1] Objets sélectionnés sur leur EED avec (ssget " X ")
  ;;; définit l'en-tête et le délimiteur de votre application  (4 caractères comme nom du regapp  
  ;;; suivant  AAIG, AutoDESK Application Interoperation Guidelines)  
  (setq appname "HUBU-")
  ;;; définit * pour tous sous-types   
  (setq allappnames (strcat appname "*"))  
  ;;; exemples : HUBU-LIST1, HUBU-LIST2,  

  ;;; Voici comment obtenir la première liste EED d'un élément  
  (defun geteed-lst (ele)
    (cdadr (assoc -3 (entget ele (list allappnames))))
  )

  ;;; avec ceci on obtient tous les éléments de l'application typ (les métacaractères sont permis)  
  (defun ssget-app (typ)
    (ssget "X" (list (list -3 (list typ)))
  )

  ;;; avec ceci vous obtenez seulement vos éléments  
  (defun ssget-hubu (typ)
    (ssget "X" (list (list -3 (list (strcat appname typ))))
  )

  (ssget-hubu "*")  ;  vous obtiendrez tous vos elements  

[26.2] Récupérer les EED d'un objet

Testez tous les XDATA avec : (entget (car (entsel)) '("*"))
Ces fonctions retournent toutes les XDATA correspondant au nom du regapp ou toutes les XDATA correspondant aux valeurs du code.
  ;;; Obtenir toutes les listes XDATA d'un element  
  ;;; c.a.d. avec XDATA :  
  ;;; (-3  ("HUBU-1" (1000 ."ASSHATCH")(1002 ."{")
  ;;;                (1070 . 1)(1002 ."}")))
  ;;; =>(("HUBU-1" (1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}")))
  (defun getxdata (e apnlst)
    (cdr (assoc -3 (entget e apnlst)))
  )

  ;;; Toutes les listes sans le nom regapp  
  ;;; => ((1000 ."ASSHATCH")(1002 ."{")(1070 . 1)(1002 ."}"))
  (defun getxdata-all (e apnlst)
    (apply 'append (mapcar 'cdr (getxdata e apnlst)))
  )

Le nom du regapp est retiré ici, parce qu'il est utilisé seulement pour un accès plus rapide à ssget. Les différentes applications sont divisées par différents groupes (1000 . name) tels qu'utilisés par AutoDESK.
Pour stocker les XDATA dans un élément, voir XDATA.LSP ou XED.LSP cependant ces exemples sont un peu dérangeants.
Pour les astuces EED avancées, spécialement pour convertir les "" "" ADS en listes Lisp et l'inverse, voir http://xarch.tu-graz.ac.at/autocad/news/eed_retrieval.txt


[27] Comment stopper une commande dans le Lisp ?

et aussi : "Comment est-ce que je tape sur Arrêt en AutoLISP ?"

(command) sans paramètres fonctionne juste comme si on tapait Ctrl-C sous DOS ou Esc sous Windows au message d'une commande. Mais il n'imite pas Esc dans un boîte de dialogue. Et ça ne fonctionne pas dans un script. (command nil) est identique à (COMMAND).

(command) interrompt uniquement la fonction command ; par exemple si vous utilisez la commande "_DIM" à l'intérieur d'AutoLisp, vous devez l'interrompre par (COMMAND) après la cotation.

Mais ça ne fonctionne pas, si vous essayez d'interrompre une boucle en lisp. Il y a une autre fonction (EXIT) ou (QUIT) - elles font la même chose -, laquelle interrompt immédiatement un programme lisp.

Exemple:
  (while T ; do         ; une boucle sans fin  
    (princ "\nTapez a=")
    (setq a (getint))
    (if (zerop a)(exit)) ; interromp le lisp et retourne au mode commande  
  )
Dans cet exemple (COMMAND) ne marche pas. (EXIT) fonctionne exactement comme Ctrl-C. Ca affiche "error: quit / exit abort" et sort de toutes les fonctions imbriquées. Pour fournir une interruption "silencieuse" vous devez inclure ce message d'erreur dans une fonction de gestion des erreurs, par exemple :
  (setq *olderr* *error* *error* my-error)
  (defun my-error (s)
    (if (not (member s            ; msgs de la version anglaise :   
       '("Function cancelled" "console break" "quit / exit abort")))
      (princ (strcat "\nError: " s))
    )
    (setq *error* *olderr*)
  )
Pour les scripts, utilisez cette combine toute simple qui définit (annuler) en lisp,
  (defun SCRIPT-ANNULER() 
    (command) 
    (command "resume") 
  ) 
et dans un SCRIPT.SCR:
.. 
[] 
 (SCRIPT-ANNULER) 
[d'autres commandes du script] 
.. 


[27.1] Comment faire un nombre illimité de messages utilisateur ?

[nouveau] Pour laisser l'utilisateur terminer la commande sans avoir à écrire du code pour chaque option possible, répétez simplement (command PAUSE) jusque la commande soit terminée. (command "_ARC") (while (= 1 (logand (getvar "CMDACTIVE") 1)) (command PAUSE))



[28] Comment décoder la géométrie interne ACIS avec lisp ?

Tous les objets ACIS (3DSOLID) ont été documentés par Spatial (Format de description SAT). Cependant la représentation interne par (ENTGET) est toujours cryptée, mais le principe du cryptage a été déplombé (XOR 95)
Des exemples et du code se trouvent à : http://xarch.tu-graz.ac.at/autocad/stlib/samples/ACIS-REGION.LSP [nouveau]



[A] Responsabilités, Notes des auteurs

Si vous pensez à des questions qui sont appropriées à cette FAQ, ou si vous voudriez améliorer une réponse, envoyez, s'il vous plaît, un e-mail à Reini Urban < rurban@x-ray.at> mais n'espérez pas avoir une réponse.

Cette FAQ AutoLISP est Copyright (c) 1996,97,98,99, 2000, 2001 par Reini Urban.
Les exemples de code sont, sauf indications contraires, (c) 1991,97 de Reini Urban et peuvent être utilisés, copiés, modifiés et distribués librement mais ne doivent pas être vendus.
Les fonctions de base sont, sauf indications contraires, (c) 1991-98 de Reini Urban et peuvent/doivent être utilisés, copiés, modifiés et distribués librement.

Cette FAQ peut être redistribuée librement dans son intégralité sans modification à condition que cet avis du copyright ne soit pas enlevé. Il ne peut pas être vendu avec profit ni incorporé dans des documents commerciaux ; (par exemple publié pour la vente sur CD-ROM, disquettes, livres, magazines, ou autre forme d'édition) sans l'obtention de l'autorisation écrite préalable du détenteur du copyright. L'autorisation est expressément allouée pour ce document à des installations qui en offre la disponibilité sans restriction par FTP anonyme sur Internet et spécialement pour être inclus dans la FAQ officielle d'AutoCAD.

Si cette FAQ est reproduite dans un média autonome (offline) (par exemple, CD-ROM, sous forme écrite, etc.), une copie gracieuse devra être envoyée à Reini Urban, X-RAY, Nibelungeng. 3, 8010 Graz, Austria

Cet article, le contenu et les exemples de code, sont fournis TEL QUELS sans aucune garantie expresse ou implicite.

[A.1] Emplacements de la FAQ et Traductions

Homepage de la version HTML :
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html
Version annotée AcadWiki : [nouveau]
xarch.tu-graz.ac.at/acadwiki/AutoLispFaq
Les versions ASCII postées (et toujours versions les plus récentes) sont à
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.1
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.2
La version Winhelp (zippée avec faq et code) est à
ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/autolisp.zip
L'archive usenet de la FAQ est à
http://www.faqs.org/faqs/CAD/autolisp-faq/ ou à ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/cad/autocad/
Le code du lisp de cette FAQ est à
ftp://xarch.tu-graz.ac.at/pub/autocad/news/faq/FAQ-CODE.LSP
Version française HTML traduite par Roger Rosec :
http://www.newz.net/acadplus/page5101.htm
Traduction japonaise par MASAMI Chikahiro
http://www.page.sannet.ne.jp/chesnutsburr/autolisp-j.html
Traduction russe par Igor Orellana
http://www.cad.dp.ua/stats/alfaq_ru.htm [modifié]
Traduction allemande par l'auteur (Reini Urban) également
http://xarch.tu-graz.ac.at/autocad/news/faq/autolisp.html.de
Traduction espagnole partielle en cours par Eduardo Magdalena emagdalena@ctv.es
FAQs AutoDesk significatives
AutoCAD Techsupport
[changé] Recherche AutoCAD+FAQ
Support Assistant 2000
Newsgroups AutoDesk [changé]
news://discussion.autodesk.com/autodesk.autocad.customization, à Deja ou le nouvel interface WebX sur le nouveau serveur de discussion d'Autodesk.


[B] Remerciements

Cette FAQ est fondée sur les efforts importants de la communauté comp.cad.autocad, en particulier :

Tom Berger, Adi Buturovic, Christoph Candido, Mike Clark, Miles Constable, Cara Denko, T.J. DiTullio, Chris Ehly, Jeff Foster, Rusty Gesner, William Kiernan, Paul Kohut, Sergei M. Komarov, Joseph M. Liston, Lu, Masami Chikahiro Georg Mischler, Desi Moreno, Vladimir Nesterovsky, Roger Rosec, Serge Pashkov, Dennis Shinn, Tony Tanzillo, Eugene Tenenbaum, Reinaldo Togores, Reini Urban, Serge Volkov, Morten Warankov, Owen Wengerd, Alan Williams, Doug Wilson, Ian A. White, David Whynot, Darren Young, Xiang Zhu et beaucoup d'autres.


[C] Changements récents

23 Avril 2001
Plusieurs liens rectifiés
v2.28 4 avril 2001
changé rurban@sbox en rurban@x-ray.at (expire l'année prochaine), toutes les parties de cette faq sont maintenant dans acadwiki.
v2.27 23 Sept 2000
ajouté [23.7] "Comment obtenir le centre d'une polyligne?"
15 Sept 2000
modifié la pile de débordement [14] pour une meilleure réflexion VL/VLIDE, A2000
nouveau livre [2]
1er Sept 2000
Avertissement concernant vl-sort avec des entrées dupliquées [8]
18 aout 2000
Changé Codemagic [6.1] de Freeware en Shareware, remerciements à Nir Sullam
1er aout 2000
Changé emplacement des url des faqs adesk
v2.26 6 Juin 2000
ajouté bug LDATA [7], rectifié DEFUN-Q [11], retiré plusieurs notes colorées [nouveau/changé]
v2.25 17 mai 2000
ajouté [27.1], ajouté C:POLYREV [23.6], versions texinfo
25 avril 2000
ajouté Point A [1.1], raccourci l'exemple DDE en [21.2]
24 avril 2000
Vladimir répare www.deja.com en deja.com/usenet [1.1]
v2.24 20 avril 2000
renommé cadsyst.com en caddepot.com [1], ajouté cadplugins.com [1], ajouté rapidlisp [6.2], (ajouté compléments emacs)
30 mars 2000
Nouveau nom du serveur de news Autodesk.
9 mars 2000
Ajouté l'éditeur Codemagic en [6.1] Merci à Mir Sullam
29 février 2000
Erreur de plage numérique rectifiée par Masami Chikahiro : [7] -32766 => -32768.
17 février 2000
Ajouté l'url de la liste des bogues de Dotsoft [7].
Correction de Mike Tuersley [11] pour les fichiers MNL.
v2.23 14 février 2000
Chris Ehly a corrigé tous les liens rompus.
v2.22 13 janvier 2000
additifs en précision numérique. les liens adesk techdocs sont encore interrompus. compilation S::STARTUP appels
v2.21 06 décembre 99
Lien de la Faq Autodesk - Changements mineurs
07 octobre 99
Modifications mineures en [0.1] - traduction allemande - Lien en [28]
v2.2 13.Juillet 99
Ajoutés les sujets [0.1] Qu'est ce qui a changé avec AutoCAD 2000?, [0.2] Pourquoi je ne peux plus créer d'ARX ?, [5.4]Les meilleurs: Common Lisp et Scheme.
Ajouts à [6.2] Analyseurs, Packagers..., [5.3] R15 VLISP info, [4] Securité FAS, [21.4], [20.4]: renommé SSAPPLY en SSMAP
13 avril 99
Un lien corrigé.
v 2.1 3 Janvier 99
Quelques liens ajoutés ou corrigés.
21 Décembre 98
Version russe trouvée.
16.Juillet 98
Changé la fréquence de postage et quelques rectifications mineures concernant, entre autres, la disponibilité de Visual Lisp.
6.Juin 98
changé l'email de Eugene
13.May 98
ajouté plotdialog R14[21.2]
11 mai 98
Déboggages de Serge Pashkov <xrs@aha.ru> en [24] arc2bul, [20.1] remove-if-not,[21.7] doc de maptrans0-1, [24] tan, [21.2] DDECMD et quelques boggues vlisp dans faq-code.lsp.
v2.0 7 mai 98
Nombreux changements concernant Visual Lisp [0],[4],[5], [6.1],[7],[17] nouveau, nouveaux livres [2], Exemple ActiveX [21.2], [A.1] meilleure FAQ R14.
30 mars 98
Changements d'URL d'Autodesk, [4] Sécurité des FAS, [A.1] Traductions
3 mars 98
Plusieurs modifications concernant Visual Lisp en tant qu'éditeur, compilateur et outil de protection.
27.Fev 98
[0] Avant-premiere du Visual lisp gratuit.
24.Fev 98
[6.1]lspedit.exe,[0]Nouvelles de Visual Lisp et [7]Entmake vertex
v1.12 12.Fev.98
Corrections mineures d'après une liste d'Eugene Tenenbaum <et119@columbia.edu> concernant principalement l'expression anglaise. Jusqu'à [11] pour cette fois.
21.Jan 98 [A.1] URL de la FAQ R14
15.Jan 98
[7] HATCH ajouté au problème entget ,
[0] plus spécifique maintenant, [22.4] changement d'URL [A.1] Traduction japonaise
12.Jan.98
[2] Le manuel lisp de la R13 est dans le manuel de personnalisation et pas seulement sur le cd. Désolé.
8.Jan.98
Nouvelle adresse URL du WEB de Vladimir Nesterowsky.
24.Nov 97 Corrections de quelques typos
v1.11 15.Nov.97
En-tête modifié.
URL des FAQ AutoDESK AutoCAD. Voir [A.1]
Editeur LispLink. Voir [6.1]
Les rumeurs sur Zoomer : [0]
2.Nov 97
Changement URL : http://www.ez-sys.net/~coopfra/
23.Oct.97
Roger Rosec a produit une traduction française de la FAQ entière. Voir [A.1]
13.Sep 97
Alan Williams a détecté une erreur stupide dans DATESTAMP en [22.2] mais dans FAQ-CODE.LSP, c'était bon.
28.Aout 97
Ajouté le bug (entget) LWPLOYLINE à [7],
changé mon adresse postale en rurban@xarch.tu-graz.ac.at en vue de ma période post-étudiantine. :)
v1.10 22.Juil 97
quelques améliorations LWPOLYLINE, R14 Lisp debugger Vital Lisp 3.0 arrivé, Mise à jour Convert 3.3[4.4], Fixation calendrier du postage bimensuel : chaque 2ème lundi, 11.30 MET
20.Juil 97
Vital Lisp 3.0 arrivé
12.Juil 97
Mise à jour Convert 3.3 [4.4], Fixation calendrier du postage bimensuel : chaque 2ème lundi, 18.00 MET
2.Juil 97
URL figé en [10],
30.Juin 97
(istypep) figé en [20.4], Titre changé en [16], léger changement dans (getpts) en [23.1]
v1.9 26.June 97
[5.2] confirme date de release Vill3, ajouté exemple DDE de Xiang Zhu en [21.2], fourniture de detab.lsp [25]
17.Juin 97
débogage en [20.4]: short (getval), [12] R14 ARX autochargement, [23.5] (pline-segs) sauve maintenant en R14 mais pas compatible, nouveau [23.6] revpoly.lsp, [A.1], [5.2] Vill 3 va avoir reactor support.
9.Juin 97
nouveau symbol-string trick par Christoph Candido [20.3]
21.Mai 97
quelques corrections mineures.
v1.8 15.Mai 97
ajouté [0] Futur d'AutoLISP ?
changé VERTECES en VERTICES, adresse de af.buturovic@berwanger.com, rectifiée
ajouté SSAPPLY :[20.4], [23.5],
commencé dans R14'ify un peu de code pour LWPOLYLINE's [23], pas encore finie, (pline-segs) est oubliée.
9.Mai 97
[2.1] R14 winhelps, [5.2]: nouveau basique url, Vill Lite [6.1]
ajouté [16] : Lisp avec mult. dwg's
ajouté quelques commentaires en [6.1](ntemacs), [14], [21.8]
21.Avril 97
ajouté [[28] ACIS décryptage
v1.7 9.April 97
ajouté[[21.8] C:XYZ,
ajouté [[15] (command "ROTATE3D") ne marche pas! Pourquoi ?
Les numéros de chapitre de la version HTML correspondent à ceux de la version postée,
ajouté[27]: (command) as ctrl-c, Sergei Komarov ajouté[27], Adi Buturovic ajouté [27] pour scripts.
v1.6 13.Fev 97
déplacé l'intro au tout début pour les curieux.
un autre lisp plot lisp [21.2], un 3ème lisp debugger [3.1], [A.1]: le gd.tuwien uunet mirror est plus rapide que l'officiel, cadence FAQ url figée, applique un format digest partiel, html sera créé automatiquement bientôt, (vielle) numérotation de chapitres fausse de la version v1.5, [7] 64 en flag 70 dans la table symboles,
v1.5 5.Fev 97
ajouté exemples get and edlgetent par Vladimir, retiré le code de tri,
changé [11] titre and ajouté les fonctions de chaîne,
debogage getpts [23.1], les fonctions de base devraient être gratuites [A],
ajouté DATESTAMP en [22.2], ajouté un "s" en [A] titre,
ajouté les exemples [20] DCL, [21] EED, [21.1-21.7],
Serguei Komarov trouve un bug dans seg2cir,arclen,arc2bul [24],
ajouté arc2ang et (corrigé) arclen,
débogué en sslist, getval, tous attributs avec "p" postfix now,
préparé une FAQ-CODE.LSP, Convert supercedes Decrypt [4.4], ajouté scripts et (command) en [23.4], AREA en [23.5],
v1.4 24.Jan 97
importante news avec Decrypt [4.4],
déplacé [11] "bugs" en [7] "problèmes",
ajouté [11] "How do I (sym, list)" instead,
ajouté le "Approved" header for news.answers processing,
ajouté [22]-[24]: some examples for subentities and bulge stuff,
Serge trouve un bug/feature dans acad_strlsort [7],
ajouté précision des nombres et limitation de ss en [7],
ajouté code break and exemples en [3.3],
ajouté un guide de style court lisp en [2.2], au lieu de [6.4]
v1.3 17.Jan 97
ajouté [16] stack overflow (merci Serge), [4.7] Lisp2C,
mise à jour [8] tri rapide (exemples, benches),
reçu l'approbation des news.anwsers.
v1.2 11.Jan 97
ajouté Phoaks à news archive
figé (break) en [3.3] (Merci Tony),
ajouté un exemple de tri en [8], augmenté (my-princ) en [15]
changé la fréquence de postage de semaine en bi-mensuel
v1.1 4.Jan 97
Bugs R13, code S::STARTUP par Owen Wengerd,
homepages au lieu des adresses e-mail si approprié, (les gens en ont assez des vieilleries...)
plus de liens, et quelques débogages
v1.0 22.Dec 96
Première version, postée le 28.Dec 96
comme base de discussion




Reini Urban