-
Compteur de contenus
1 113 -
Inscription
-
Dernière visite
-
Jours gagnés
42
Type de contenu
Profils
Forums
Calendrier
Blogs
Tout ce qui a été posté par Luna
-
As-tu essayé de simplement les charger manuellement, via APPLOAD, pour commencer ? Bisous, Luna
-
Salut, Il est en effet possible de passer par cette méthode, mais je me souviens avoir eut quelques soucis via cette méthode de temps en temps (peut-être que cela a été corrigé..) donc si tu as une erreur du type "Erreur: Demande ADS erronée", cela viendra sûrement de là mais pas de quoi s'affoler maintenant ! :3 La fonction (select-dyn-bloc) a pour vocation de filtrer les blocs dynamiques par rapport au nom de leur définition de bloc de référence, car pour un bloc standard, ce filtre peut s'effectuer directement via le code DXF 2 (le nom de la définition de bloc est directement visible et donc filtrable). Ainsi, si tu souhaites étendre le domaine d'application, je te conseille plutôt de modifier le filtre du code DXF 2 lors de l'utilisation du (ssget), au lieu de le supprimer : (setq jsel (ssget "_X" (list '(0 . "INSERT") (cons 2 (strcat "`*U*," nomdubloc))))) Je n'ai jamais eu ce soucis mais en effet cela peut survenir, un simple (command "_ZOOM" "ETendu") devrait faire l'affaire mais peut s'avérer dangereux (il faudrait donc faire en sorte de retrouver le zoom initial pour éviter d'avoir des ennuis :3) (setq h (getvar "VIEWSIZE")) (setq c (getvar "VIEWCTR")) (command "_ZOOM" "ET") [...] (command "_ZOOM" "C" c h) Bisous, Luna
-
Petite précision, les fonctions de Lee-Mac utilisent les entités sous forme de VLA-Object, et non via le nom d'entité.. il faudra donc faire la conversion avec (vlax-ename->vla-object name) :3
-
Salut, je ne comprend pas très bien à quoi cela correspond, d'autant plus que la variable sous-sel représente un jeu de sélection (et non un nom d'entité) donc en théorie ceci devrait créer un erreur... Je remarque que ton cartouche est dynamique, et cela par rapport à ton champs [matière] (si je comprend bien) donc tu peux regarder du côté de Lee-mac pour récupérer la liste des propriétés de visibilité et plus exactement la propriété active :3 Cependant je ne saisie pas très bien le rôle de ton cartouche car dans ton espace objet tu as un cartouche (bloc dynamique) et des textes multiples sous forme de champs. Pourquoi ne pas intégrer directement ces champs dans ton cartouches sous forme d'attributs ? Cela devrait t'éviter à devoir créer un groupe regroupant ton bloc cartouche et tes champs... (après il s'agit peut être d'une particularité de ZWCAD, je ne connais pas donc je m'avance peut être à tord..) Ainsi dans ton bloc nommé "sous-bloc cartouche" tu aurais le cadre, et à la place des MTEXT, tu insères des étiquettes d'attributs... Bisous, Luna
-
Tu pourrais en effet effectuer un premier filtre ainsi : (defun select-bloc-dyn (nomdubloc / jsel i name) (if (and (tblsearch "BLOCK" nomdubloc) (setq i 0 jsel (ssget "_X" '((0 . "INSERT") (2 . "`*U*"))) ) ) (while (< i (sslength jsel)) (setq name (ssname jsel i)) (if (and (= (getpropertyvalue name "ClassName") "") ;;Il semblerait que les bloc possèdent cette propriété mais vide (à vérifier) (wcmatch (getpropertyvalue name "BlockTableRecord/Name") nomdubloc) ) (setq i (1+ i)) (ssdel name jsel) ) ) (princ (strcat "Erreur : \"" nomdubloc "\" introuvable.")) ) jsel ) Je n'avais jamais remarqué que cette propriété était existante aussi bien pour les blocs que les réseaux, donc merci ! <3 après cette propriété "vide" reste une théorie à vérifier mais on peut prendre la chose dans l'autre sens : (not (wcmatch (getpropertyvalue name "ClassName") "AcDbAssociativeRectangularArray,AcDbAssociativePathArray,AcDbAssociativePolarArray")) En tout cas, très bonne remarque :3
-
Salut, On utilise habituellement les fonctions (entget), (assoc) et (cdr) car elles sont fonctionnelles tout le temps, et notamment parce que la suite des fonctions (-propertyvalue) sont très récentes contrairement à (entget). En clair pour n'importe quel objet, les coordonnées d'un point seront situées dans une paire pointée dont la "clé" est 10 ou 11. Alors que les propriétés Position/X, Position/Y, Position/Z ne sont existantes que pour certaines entités (elles peuvent avoir un nom différent par rapport au type d'entité). Donc le risque d'obtention d'une erreur est plus grande. Mais il s'agit de simples remarques sur les codes à venir, pas spécifiquement pour celui-ci. Ici il n'y a pas de raison qu'il y ait une erreur car le type d'entité est constant et connu (= "INSERT"). Pour les attributs, oui, ils sont accessibles via (entget), mais pas de manière aussi directe... c'est pour cela que j'ai pris l'habitude de passer par cette fonction, car elle est simple du point de vue de l'utilisation :3 Concernant les réseaux, il s'agit d'entités crées via la commande RESEAU (= "_ARRAY")... Il s'agit en réalité d'un bloc dynamique non nommé, mais si tu n'en connais pas l'existence, c'est que tu n'as pas de risque d'en avoir dans tes .dwg (tout dépend du secteur d'activité). Il n'existe pas de filtre (ou du moins, pas à ma connaissance) mais il y a un moyen de capter les erreurs induites par ces entités pour ne pas les prendre en compte. Mais pour être honnête, je pense que c'est pas les premières choses à comprendre à propos du LISP :3 Il est préférable de commencer par les bases. Et parfois le meilleur moyen c'est de passer du temps à tester les fonctions basiques pour ensuite étoffer son "vocabulaire" ^^ Autrement tu risques de vite être embrouillé avec toutes les nouvelles fonctions. Je pense que la plus simple à mettre en place serait celle-ci : déplacer, exporter, retablir (= "_OOPS"), déplacer -> uniquement dans le fichier en cours. (command "_MOVE" sous-sel "" (setq pt (cdr (assoc 10 (entget name)))) '(0.0 0.0 0.0)) (command "_.WBLOCK" file_name "" '(0.0 0.0 0.0) sous-sel "") (command "_.OOPS") (command "_MOVE" sous-sel "" '(0.0 0.0 0.0) pt) Et donc ici, plus besoin de Xmin et Ymin car ils sont remplacés par la variable pt :3 Bisous, Luna
-
Salut, Je viens de tester la commande -WBLOC et je n'arrive pas à saisir l'utilité du point d'insertion à ce niveau là... que l'on choisisse un point au hasard ou bien le point 0,0,0 le dessin est inséré au même endroit... Donc la solution serait de déplacer temporairement l'ensemble des objets avant lancement de la commande -WBLOC (pour éviter d'avoir à ouvrir le fichier .dwg après coup). Ensuite tu n'es pas obligé de passer par (getpropertyvalue) pour récupérer le point d'insertion du bloc. Chaque entité possède une liste DXF (si j'ai bien compris, un fichier DWG est défini en totalité par les listes DXF). Pour le point d'insertion, c'est facilement récupérable car il s'agit du code DXF 10. Voici un site qui peut s'avérer utile pour la compréhension de certains codes DXF. Pour la récupération des infos il faut passer par la fonction (entget) qui te permet de récupérer la liste DXF d'une entité et ensuite les fonctions (cdr) et (assoc). Pour leur utilisation, je te conseille d'aller jeter un œil sur les paires pointées et les listes DXF car c'est primordial :3 Ensuite, je ne sais pas la composition exacte de ton fichier DWG mais il faut se méfier de la fonction (select-bloc-dyn) car elle ne prévoit pas la présence de réseaux... j'ai préféré la simplifier pour la compréhension mais les réseaux sont quelque peu fourbes... car ils apparaissent comme des blocs (0 . "INSERT") dynamiques (2 . "`*U*") mais ils ne possèdent pas de propriété "BlockTableRecord/Name"... Donc pour une utilisation cadrée, elle ne posera pas de problème mais si ton fichier possède ce genre d'entité, la fonction (select-bloc-dyn) aura forcément une erreur et mettra fin à la commande ^^ Bisous, Luna
-
Salut, Je viens de trouver une solution avec la fonction (acet-ui-progress) qui semble fonctionner à peu près normalement. Il s'agit de la même barre qu'AutoCAD utilise lorsqu'il affiche une progression. Elle est située en bas à droite. Elle est assez particulière sur l'utilisation. (acet-ui-progress "Working" n) ;Retourne T (setq i 0) (repeat n (acet-ui-progress (setq i (1+ i))) ;Retourne i ) (acet-ui-progress) ;Retourne nil Voici l'aide associée que j'ai pu trouver : J'ai testé la version (acet-ui-progress -1) une fois la fonction initiée mais cela n'a pas fonctionné (la barre de progression était à 100% à chaque passage dans la boucle). Du coup pour la gestion des erreurs car il est préférable de supprimer la barre de chargement lorsqu'une erreur survient j'ai testé ceci (j'ai tout de même réussi à avoir une erreur random qui n'a pas activée la fonction *error*) : (defun try (n txt / i *error* msg acet) (defun *error* (msg) (if acet (acet-ui-progress)) (princ msg) ) (setq acet (acet-ui-progress txt n)) (setq i 0) (repeat n (acet-ui-progress (setq i (1+ i))) ) (setq acet (acet-ui-progress)) ) Je n'ai pas encore eu le temps de la tester correctement, mais par exemple dans cette utilisation, la barre de progression n'est pas update : (defun test (/ *error* msg acet i layer-list layer) (defun *error* (msg) (if acet (acet-ui-progress)) (princ msg) ) (setq layer-list '("Calque1" "Calque2" "Calque3" "Calque4" "Calque5" "Calque6" "Calque7" "Calque8" "Calque9") i 0 acet (acet-ui-progress "Working" (length layer-list)) ) (command "-SUPCALQUE") (foreach layer layer-list (acet-ui-progress (setq i (1+ i))) (command "N" layer) ) (command "" "O") (setq acet (acet-ui-progress)) ) Elle est vide à l'initialisation, AutoCAD exécute la commande et une fois la commande exécutée, il supprime la barre de progression... Bisous, Luna
-
[RESOLU] Sélectionner à travers une fenêtre
Luna a répondu à un(e) sujet de LElemurien dans Débuter en LISP
Salut, Si ton utilisateur se trouve dans l'espace de présentation, pourquoi ne pas activer la fenêtre (command "_MSPACE"), sélectionner l'objet (entsel), et désactiver la fenêtre (command "_PSPACE") ? Si ta présentation possède plusieurs fenêtres il faudrait trouver une méthode permettant d'activer automatiquement la bonne fenêtre pour éviter la sélection de la fenêtre. Autrement je ne connais pas de méthode le permettant sans activer l'espace objet de la fenêtre.... Bisous, Luna -
Une liste se présente sous la forme (1 2 3 4 5) tandis qu'un jeu de sélection se présente sous la forme <Selection set: b9c>. Ainsi il est assez simple de connaître la composition d'une liste puisqu'elle est directement lisible, en revanche un jeu de sélection n'est pas directement lisible. Une liste peut contenir de tout, par exemple la liste ci-dessus ne comporte que des integer (nombres entiers) mais elle peut également contenir toute sorte d'élément et également des listes. Un jeu de sélection, lui, ne peut contenir que des entités physiques. C'est l'équivalent du sac de bille, il ne peut contenir que des billes existantes mais on ne peut pas savoir qu'elles sont les billes présentes dans le sac sans l'ouvrir. La plupart des commandes utilise des jeux de sélection car plus simple à traiter. Si jamais tu as un doute sur les objets présents dans un jeu de sélection, tu peux "activer" ton jeu de sélection (= le met en surbrillance) via la fonction (sssetfirst nil jsel), avec jsel ton jeu de sélection (le premier argument est toujours nil car il fait référence à un ancien mode qui n'est plus utilisé aujourd'hui). Pour le désactiver, tu fais (sssetfirst nil nil) :3 il est possible de passer par une liste si tu le souhaites mais ici, un jeu de sélection me semble le plus adapté à la situation. En fonction de ce que tu as (une liste ou un jeu de sélection, la méthode diffère légèrement mais le principe est le même) mais étant donné que l'on part d'un jeu de sélection pour arriver à la liste, autant conserver le jeu de sélection. Ceci pourrait être un début de piste, mais encore une fois, je te conseille de te familiariser avec les bases du langage LISP via les sites de Didier et (gile) qui ont l'avantage d'être en français :3 (defun c:TEST (/ sel-to-list jsel sous-sel ssbounding designation i name lst) (defun sel-to-list (sel / i lst) (repeat (setq i (sslength sel)) (setq lst (cons (ssname sel (setq i (1- i))) lst)) ) lst ) (if (setq jsel (select-bloc-dyn "sous-bloc cartouche")) (repeat (setq i (sslength jsel)) (setq name (ssname jsel (setq i (1- i))) designation (getpropertyvalue name "DESIGNATION") ssbounding (LM:ssboundingbox (ssadd name)) sous-sel (ssget "_C" (car ssbounding) (cadr ssbounding)) lst (cons (cons designation (sel-to-list sous-sel)) lst) ) ;; Ajout de l'export en .dwg + .csv ) ) (princ (strcat "\nUn total de " (itoa i) " cartouches ont été traités.")) (princ) ) Bon comme je l'ai dit, je ne maîtrise pas le sujet sur la création de fichier .dwg donc je ne sais pas si un simple jeu de sélection peut être copié du document actif vers un nouveau fichier ou si c'est un peu plus élaboré que ça... Ici, tu pourras voir la différence entre un jeu de sélection et une liste (la variable sous-sel correspond au jeu de sélection pour un bloc de cartouche mais il est réinitialisé à chaque nouveau passage dans la boucle tandis que la variable lst correspond à la liste de l'ensemble de entités présentes dans le jeu de sélection sous-sel pour une designation précise - tu devrais regarder ce qu'on appelle les listes de paires pointées pour cela -) Ici, l'ensemble des variables sont déclarées localement pour éviter d'avoir des ennuis d'interactions avec d'autres programmes. Je pense que pour la création de fichier, les fonctions (getfiled), (open) (close) te seront utiles, mais comme j'ai dit, je ne maîtrise pas :3 Bisous, Luna
-
Je remarque également que tu as déjà consulté le site de Lee-Mac. Si tu cherches à apprendre, je pense que limiter au maximum l'utilisation de fonctions développées par d'autres est préférable, mais si tu cherches uniquement à créer un programme pour aller plus vite, alors il y aura toujours moyen de l'améliorer au mieux :3 Bisous, Luna
-
Salut, Si je prend dans l'ordre : Qu'entends-tu par là exactement ? il te faut la liste des nom d'entités (changent entre chaque sessions d'AutoCAD) de chaque cartouche présents dans le dessin, leur handle (similaires au nom d'entité, mais permanent), le nom de la définition de bloc (ce qui reviendrait à n'avoir qu'un unique élément dans la liste, ...? Si je comprend bien, il s'agit ici d'un jeu de sélection que tu souhaites faire, n'est-ce pas ? Si c'est le cas, je remarque que ton cartouche est un bloc dynamique donc il faudra faire un post-traitement à la sélection pour n'avoir que les blocs souhaités, comme ceci : (defun select-bloc-dyn (nomdubloc / jsel i name) (if (and (tblsearch "BLOCK" nomdubloc) (setq i 0 jsel (ssget "_X" '((0 . "INSERT") (2 . "`*U*"))) ) ) (while (< i (sslength jsel)) (setq name (ssname jsel i)) (if (wcmatch (getpropertyvalue name "BlockTableRecord/Name") nomdubloc) (setq i (1+ i)) (ssdel name jsel) ) ) (princ (strcat "Erreur : \"" nomdubloc "\" introuvable.")) ) jsel ) Cette fonction nécessite que l'on spécifie le nom du bloc complet pour pouvoir filtrer selon ce nom (ici il s'agit de "sous-bloc cartouche"). Elle renvoie le jeu de sélection (différent d'une liste car on ne peut pas le lire de manière directe) ou nil en cas d'échec. En partant de l'hypothèse ci-dessus, les jeux de sélection ne sont pas les plus simples à traiter lorsqu'on débute, pour être honnête.. Pour "parcourir" un jeu de sélection, il faut faire comme ci-dessus. Une boucle (while) ou bien (repeat) et récupérer le nom de l'entité à l'indice i (que l'on incrémente à chaque nouveau passage dans la boucle). L'idée étant d'écrire le programme au sein de cette boucle pour pouvoir traiter l'ensemble des cartouches un par un. je te conseille d'aller consulter le site de Didier Da-Code.fr ou bien le site de (gile) Introduction à AutoLisp (tu devrais également pouvoir trouver le site de (gile) sous format PDF si c'est plus simple pour toi) Les fonctions (while), (repeat), (sslength), (ssname), (1+), (1-) te seront utiles pour cela. Encore une fois, tu as un exemple de récupération simplifiée d'une valeur de propriété dans la fonction ci-dessus. Il s'agit de la fonction (getpropertyvalue). Pour les attributs de blocs, c'est assez simple car elle nécessite le nom du bloc (récupérer par exemple par (ssname) dans la boucle (while)) et le nom de l'attribut (donc pour toi c'est "designation"). Si tu veux essayer de comprendre exactement comment ça marche, je te conseille d'écrire ceci dans la ligne de commande (dumpallproperties (car (entsel))) et de sélectionner un bloc. Il te suffit d'afficher ton historique de commande (F2). Il s'agit de la liste des propriétés atteignables par la fonction (getpropertyvalue) et normalement à la lettre "D" tu devrais trouver ton attribut "DESIGNATION". donc (setq designation (getpropertyvalue name "DESIGNATION")) te renverra ce que tu cherches. Si tu as créer une polyligne au cours de la commande, alors ceci devrait suffire : (setq poly-name (entlast)) (cela renvoie le nom d'entité de la dernière entité créée) Il existe une méthode simplifiée (si jamais ça t'intéresse) du côté de la fonction (LM:ssboundingbox) développée par Lee-Mac qui te permettrais de ne pas avoir à dessiner de polylignes mais cela risque d'être un peu complexe, mais je te laisse le lien si besoin :3 Je n'ai pas bien saisie cette ligne-ci...désolée. Pour le coup, je n'ai jamais fait cela, et pour débuter, ce n'est vraiment pas le plus simple...Je pense que les grands gourous comme (gile), BonusCAD et bien d'autres auront quelques fonctions toutes faites à ce sujet... Mais je ne te conseille pas de "débuter" avec ce genre de programme :3 Fonction (entdel), tu la trouveras sur le site de Didier ou (gile) pour comprendre ses subtilités ^^ Comme je l'ai dit, le plus simple est une boucle qui te permet de faire les cartouches un par un. En espérant t'avoir aider un petit peu, et désolée si c'est un peu flou...c'est un sujet assez complexe pour débuter réellement. Bisous, Luna
-
DCL: Ajouter une tuile avec un bouton
Luna a répondu à un(e) sujet de Fraid dans Pour aller plus loin en LISP
pour l'écriture d'un nombre n d'edit_box, je pense que l'on peut utiliser (apply 'strcat) sur une liste d'edit_box du genre : (repeat n (setq lst (cons (strcat ":edit_box{label=" msg ";key=eb" (itoa (setq n (1- n))) ";}") lst)) ) (...) (write-line ... (apply 'strcat lst) ...) (...) tu combines ça avec un action_tile pour le bouton d'ajout qui ferme la bdl, save les valeurs existantes (check de la valeur actuelle de n pour déterminer la liste des key existantes et sauver tout le monde dans une liste), rouvrir le fichier et réécrire par dessus en incrémentant la valeur de n de 1, puis charger de nouveau le fichier et rouvrir la bdl en restaurant les valeurs sauvegardées... ça me semble jouable mais à voir si du point de vue de l'utilisation, c'est pas une perte de temps monstre avec le chargement/déchargement de la fenêtre... Peut-être qu'une simple edit_box pour entrer directement le nombre d'edit_box souhaitée serait plus simple... (pour éviter d'appuyer 15 fois sur le bouton ^^") Bisous, Luna -
DCL: Ajouter une tuile avec un bouton
Luna a répondu à un(e) sujet de Fraid dans Pour aller plus loin en LISP
Je m'étais déjà cassée le nez sur un problème similaire mais par manque de temps et de connaissances, je n'ai pas étudié la question de manière très poussée malheureusement. Donc heureuse de voir que je ne suis pas la seule à me poser ce genre de problème :3 Autrement, mais je ne connais pas du tout, peut être regarder du côté de ObjectDCL... Même si je doute que l'on puisse créer une boîte de dialogue dynamique. Pour moi ObjectDCL permet de faciliter l'écriture d'une boîte de dialogue en la rendant implicite (création d'une boîte de dialogue similaire à l'éditeur VBA sur Excel). Cependant, si je comprend bien, les paragraph{} ne permettent pas la saisie d'informations, uniquement des concaténation de textes en dur (donc différent d'une edit_box). Bisous, Luna -
DCL: Ajouter une tuile avec un bouton
Luna a répondu à un(e) sujet de Fraid dans Pour aller plus loin en LISP
Salut, La question est intéressante, malheureusement je doute que l'on puisse conserver la fenêtre de saisie ouverte en même temps que l'on ajoute des edit_box. Après tout, dans le fichier .lsp, on a dans l'ordre : 1. Création d'un fichier .dcl 2. Ouverture du fichier créé 3. Edition du fichier .dcl 4. Fermeture du fichier .dcl 5. Chargement du fichier .dcl 6. Définition des actions et paramètres par défaut de la bdl 7. Ouverture de la bdl 8. Récupération des donnés à traiter 9. Suppression de la bdl de la mémoire 10. Suppression du fichier .dcl Donc au final, une fois la bdl active et ouverte, elle est définie par le fichier .dcl chargé. Donc je ne vois pas comment réécrire le fichier .dcl, le charger de nouveau et ainsi modifier l'apparence de la bdl sans fermer la bdl initiale... Après on peut toujours faire comme tu proposes, c'est-à-dire que l'on ferme la boîte de dialogue en récupérant les données pré-rentrées, modification du fichier .dcl et rechargement de la bdl avec les données définies. Mais en terme de programmation ça me paraît quelque peu complexe (faisable mais avec de nombreuses conditions et vérifications + création de variables à nom variable). Bisous, Luna -
[RÉSOLU] comment utiliser la fonction getkword
Luna a répondu à un(e) sujet de LElemurien dans Débuter en LISP
Bonjour, Vouih en effet, j'ai souvent tendance à faire mes recherches en anglais donc le site de LeeMac ressort plus souvent. Pardon pour cet écart.. Bisous, Luna -
[RÉSOLU] comment utiliser la fonction getkword
Luna a répondu à un(e) sujet de LElemurien dans Débuter en LISP
Ah et petite précision, je vois que sur la ligne (if (= rep1 "Avec") (progn (command "_circle" '(0 0 0) "5" "") ) ;_ Fin de progn ) ;_ Fin de if tu n'as pas besoin d'utiliser la fonction (progn) ici... En effet la fonction (if) possède 3 arguments (if testexpr thenexpr [elseexpr]) auquel cas, chaque expression doit être bien distincte l'une de l'autre. Par exemple (if (= rep1 "Avec") ;; Correspond à la condition [= testexpr] (command "_circle" '(0 0 0) "5" "") ;; Correspond à l'expression si VRAI [= thenexpr] (princ "\nLigne sans cercle choisie") ;; Correspond à l'expression si FAUX [= elseexpr] ) ; Donc ici pas besoin de la fonction (progn) permettant de grouper un ensemble de fonctions en une seule expression (if (= rep1 "Avec") ;; Correspond à la condition [= testexpr] (progn (command "_circle" '(0 0 0) "5" "") ;; Correspond à l'expression si VRAI [= thenexpr] (princ "\nLigne sans cercle choisie") ;; Correspond à l'expression si VRAI [= thenexpr] ) ) ; Ici, la fonction (progn) permet de grouper les fonctions (command) et (princ) en une seule expression pour quelles soient toutes deux évaluées par la fonction (if) lorsque la condition est VRAI. Si la condition est FAUSSE, il ne se passe rien. Donc pour faire clair, ici, étant donné que tu n'as qu'une seule expression à faire rentrer dans l'argument thenexpr de la fonction (if), l'utilisation de la fonction (progn) n'est pas obligatoire. Cela n'impacte en rien ton programme mais autant faire au plus simple lorsqu'on en a l'occasion :3 Bisous, Luna -
[RÉSOLU] comment utiliser la fonction getkword
Luna a répondu à un(e) sujet de LElemurien dans Débuter en LISP
Hey, le getkword n'est pas capable de détecter une valeur par défaut dans la chaîne de caractères servant de message. Même si du point de vue d'AutoCAD la manière de l'afficher est la même cela ne fonctionne pas. Il est cependant capable de détecter les mots clés au sein de la chaîne de caractères pour la surbrillance. Donc pour pouvoir définir une valeur par défaut il faut dans un premier temps (comme tu l'as déjà fait) ne pas empêcher l'utilisateur d'appuyer sur ENTER (correspondant au bit 0, de valeur 1). Lorsque l'utilisateur fait une validation à vide, la fonction (getkword) renvoie nil. Donc une méthode simple pour définir une réponse par défaut serait celle-ci : (initget "Avec Sans") (if (null (setq rep1 (getkword "\nLigne avec ou sans cercle ? [Avec/Sans] <Avec>: "))) (setq rep1 "Avec") ) ;;il est possible également de passer par la fonction (cond) (setq rep1 (cond ((getkword "\nLigne avec ou sans cercle ? [Avec/Sans] <Avec>: ")) ("Avec"))) Si besoin tu peux voir le site de LeeMac, qui en parle justement (c'est en anglais mais pour la programmation on n'a pas vraiment le choix). PS : dans l'éditeur de texte, tu as un petit symbole comme celui-ci <> sur la seconde ligne à gauche (après les smiley&Co !) :3 Bisous, Luna -
Oki doki, merci beaucoup pour ces précisions :3 Bisous, Luna
-
Salut, En effet j'avais déjà penser à cette solution mais en effet ça demande d'avoir un cond assez complexe pour prendre en compte toutes les possibilités par rapport aux arguments Après dans mon cas, ça ne serait pas si complexe que ça puisque qu'il s'agit plutôt d'un argument optionnel et non un nombre d'argument indéfini.. Je trouve tout de même dommage que cela ne soit pas possible...Et dans ce cas, à quoi fait référence le document GNU Emacs Lisp Reference Manual ..? --" Merci de ta réponse en tout cas ! :3 Bisous, Luna
-
Compatibilité "{ACAD_REACTORS" + perimeter
Luna a répondu à un(e) sujet de Pirlouit dans Pour aller plus loin en LISP
Salut, Je peux te proposer ceci, qui ne se base pas sur l'existence d'une propriété longueur pour l'entité mais sur les paramètres géométrique de l'objet donc tu n'auras plus de problème avec les spline, arc, circle et ellipse (setq Lg (vlax-curve-getDistAtParam (vlax-ename->vla-object ename) (vlax-curve-getEndParam (vlax-ename->vla-object ename)))) Ahh bah coiffée au poteau par maître (gile) sur ce coup là :3 Bon par contre, il s'agit encore de visual lisp, désolé d'avance... :.( Le soucis c'est que si l'on ne souhaite pas utiliser les fonctions vl, vla, vlax, ... ça demande de passer par des commandes et des calculs et les sources d'erreurs sont plus grandes (du moins, il s'agit de mon avis perso' !) ainsi que le temps d'exécution. Je serais ravie de pouvoir t'aider si jamais tu as des questions sur les bases du LISP (à vrai dire je n'ai commencer la programmation il n'y a qu'un an, donc je suis loin de connaître le LISP et encore moins le visual LISP ! --"). Pour commencer, si tu souhaites enregistrer le fichier .txt dans le même dossier que ton dessin, tu peux utiliser la variable système DWGPREFIX (setq filepath (getvar "DWGPREFIX")). Celle-ci te renvoie le chemin d'accès de ton fichier DWG courant sous forme de chaîne de caractères. Ensuite pour faire cela, je n'ai pas encore vraiment de maîtrise dans le domaine de l'écriture de fichiers .txt donc je vais t'aider au mieux :3 (setq file (open (strcat (getvar "DWGPREFIX") "Résultats.txt") "w")) (write-line [expr...]) ;;Peut se situer dans un foreach ou une boucle en fonction de la manière dont tu conserves tes résultats (close file) ;;========================================================;; ;;Si tu préfères en effet passer par une boîte de dialogue pour contrôler la position de ton fichier .txt et changer le nom si besoin (existence de deux fichiers...) (setq file (open (getfiled Title "Résultats" "txt" 1) "w")) ;;Title correspond au nom de ta boîte de dialogue (= l'entête), cf. Aide AutoCAD sur (getfiled) (write-line [expr...]) ;;Peut se situer dans un foreach ou une boucle en fonction de la manière dont tu conserves tes résultats (close file) Tu as donc le choix entre prendre le chemin d'accès de ton .dwg (1ère méthode) ou en passant par une boîte de dialogue (2nde méthode). Voici l'aide associer pour (getfiled) si besoin :3 Car (getfiled) n'ouvre pas un fichier existant, elle renvoie le chemin d'accès pour le fichier spécifié :3 ici, le dernier argument signifie qu'il s'agit d'un nouveau document, mais pour ouvrir ce-dit document, il faut tout de même passer par (open) et (close). Je te suggère la variable système CTAB qui renvoie le nom de la présentation en cours d'utilisation, donc si tu te trouves en espace objet, (getvar "CTAB") renvoie "Model" (et vouih c'est en anglais :3) et si tu es en espace présentation, la variable système renvoie le nom de la présentation. Mais il existe également la variable système TILEMODE qui est un peu plus générale car elle définie uniquement si on est en espace objet ou papier (correspondant à la dernière présentation activée) Autrement dit, je peux te proposer une méthode semi-brutale mais si ton programme ne doit fonctionner qu'en espace objet : (setvar "TILEMODE" 1) Voici également un lien vers un document primordial pour démarrer avec AutoCAD : Liste des Variables systèmes AutoCAD (par rebcao) Un petit ctrl+F pour trouver ton bonheur et ensuite rechercher dans l'aide AutoCAD le détail sur le fonctionnement de la variable système :3 Du coup voici pour TILEMODEpour que tu comprennes sont fonctionnement. Je crois que je ne me suis pas égarée cette fois-ci ^^" Bisous, Luna -
Bonjour, Petite question (sûrement idiote), mais je me demandais si l'on avait la possibilité de créer une fonction avec un nombre d'argument non défini/non fixe. Par exemple la fonction '+ additionne l'ensemble des nombres spécifiés en argument, donc elle ne possède pas un nombre fixe d'argument comme la fonction 'car : (+ 1 2 3 4 5 ... n) J'ai trouvé ce post mais j'ai l'impression qu'il s'agit d'une version différente (à vrai dire je suis perdue entre les LISP, Visual LISP, ActiveX, Common LISP, ...) --" J'ai testé ceci : (defun test (a b &rest c) (if c a b ) ) commande:(test 0 1) ; erreur: nombre d'arguments insuffisants commande:(test 0 1 T) ; erreur: nombre d'arguments insuffisants commande:(test 0 1 T T) 0 commande:(test 0 1 T nil) 1 commande:(test 0 1 nil T) 0 Donc en clair, il ne reconnaît pas l'écriture &rest et le comprend comme un argument quelconque et non un keyword... J'ai essayé également avec le keyword &optional mais même résultat... Voici un extrait de la source de cette info (GNU Emacs Lisp Reference Manual) : Avez-vous déjà étudié cette question, est-ce seulement possible sur de la programmation basique avec AutoLISP 2018 ? L'idée derrière cette question c'est pour éviter d'avoir à écrire deux fonctions quasi identiques ou bien d'avoir à me trimbaler une variable nil dans l'utilisation de cette fonction.. ;; Définition deux deux fonctions quasi-identiques : (defun func1 (arg1 arg2 / ...) [expr...] jsel ) ;;Renvoie un jeu de sélection (defun func2 (arg1 arg2 / ...) [expr...] (princ rslt) ) ;;Renvoie le contenu du jeu de sélection ;;========================================================;; ;;Définition d'un argument prompteur (defun func (arg1 arg2 display / ...) [expr...] (if display (princ rslt) jsel ) ) ;; Donc à l'utilisation, il faudra obligatoirement écrire (func arg1 arg2 nil). ;;========================================================;; ;;Utilisation d'un argument optionnel (defun func (arg1 arg2 &rest display / ...) [expr...] (if display (princ rslt) jsel ) ) ;; Donc (func arg1 arg2) et (func arg1 arg2 nil) renverront le même résultat Bisous, Luna
-
Compatibilité "{ACAD_REACTORS" + perimeter
Luna a répondu à un(e) sujet de Pirlouit dans Pour aller plus loin en LISP
Oki, je comprend parfaitement que tu n'as pas eu le temps de te pencher sur les fonctions vl, vla et vlax. Il est préférable de commencer par les bases :3 Le fait que getpropertyvalue renvoit une erreur peut simplement venir de ta version AutoCAD (il me semble mais je ne suis pas sûre, que ces méthodes vanilla aient été ajoutées à partir des versions 2014) En effet, si ton but est de récupérer l'aire et le périmètre d'un objet linéaire, je te suggère ceci (je sais il s'agit de visual lisp donc on s'éloigne des bases mais ça reste le plus efficace) : ;;Récupération de l'aire d'un objet linéaire dont son nom d'entité vaut "ename" : (if (vl-catch-all-error-p (setq Area (vl-catch-all-apply 'vla-get-area (list (vlax-ename->vla-object ename))))) (setq Area 0.0) ;;Si (vl-catch-all-apply) retourne une erreur (dans le cas d'un bloc qui ne possède pas de propriété d'aire par exemple), permet de ne pas interrompre le programme et renvoie une aire nulle ) ;;Récupération du périmètre d'un objet linéaire dont son nom d'entité vaut "ename" : (if (vl-catch-all-error-p (setq Lg (vl-catch-all-apply 'vla-get-length (list (vlax-ename->vla-object ename))))) (setq Lg 0.0) ;;Si (vl-catch-all-apply) retourne une erreur (dans le cas d'un bloc qui ne possède pas de propriété de périmètre par exemple), permet de ne pas interrompre le programme et renvoie une longueur nulle ) Pour expliquer rapidement le fonctionnement : - l'utilisation du (if) permet de "capter" les erreurs lors de la récupération de données et de passer outre en définissant la variable d'aire ou de longueur à 0.0, ce qui ne perturbe pas l'exécution du programme. - les fonctions (vl-catch-all-apply) et (vl-catch-all-error-p) sont souvent utilisées ensemble car c'est justement grâce à elles que le programme est capable de "contenir" une erreur sans s'arrêter (voir aide AutoCAD (vl-catch-all-apply) et (vl-catch-all-error-p)) Pour vulgariser un peu leur utilisation, la fonction (vl-catch-all-apply) exécute la fonction qui lui est passée en premier argument (ici (vla-get-area) ou (vla-get-length) - Attention, il ne faut pas utiliser les parenthèses mais une ' -), le second argument correspond aux arguments de la fonction évaluée sous forme de liste. Si la fonction évaluée fonctionne correctement, alors (vl-catch-all-apply) retourne le résultat de la fonction (d'où le (setq) situé à ce niveau), sinon, renvoie un objet de type error. L'erreur ainsi rencontrée ne stoppe pas le programme, ce qui est très efficace. La fonction (vl-catch-all-error-p) se contente de retourner T s'il évalue un objet de type error, nil sinon. - les fonctions (vla-get-property), donc ici on recherche les propriétés nommée Area et Length, d'où (vla-get-area) et (vla-get-length), nécessite des VLA-OBJECT. Ce qu'il faut comprendre, c'est que les fonctions vanilla comme (entget) par exemple utilise l'ename d'un objet (qui n'est pas toujours identique selon la session) pour accéder à sa liste DXF. Liste DXF de ta polyligne gênante: Les VLA-OBJECT ne sont rien d'autre qu'une écriture différente de l'ename de ton entité. C'est d'ailleurs pour cela que l'on peut facilement switcher entre l'ename et le VLA-OBJECT d'une même entité. Ce qui change, c'est le codage. Le visual LISP, qui travaille avec les VLA-OBJECT fonctionne comme du VBA (si jamais tu as eu l'occassion d'en faire) donc c'est une écriture un peu complexe au début mais c'est comme le LISP, il suffit de s'entraîner... :3 La fonction (getpropertyvalue) a été ajouté assez récemment pour justement permettre d'accéder plus facilement aux propriétés d'un objet (propriétés semblables aux propriétés présentes dans la palette des propriétés) sans faire appel aux méthodes (vla-get-property) et ainsi conserver l'écriture "vanilla" (bon il y a d'autres raisons bien sûr ^^). Donc les deux méthodes fonctionnent mais ne font pas appel aux mêmes principe d'écriture... Pour ma part, je ne maîtrise pas non plus les méthodes Visual LISP et j'aurais tendance à préférer les fonctions vanilla mais si ta version d'AutoCAD ne te permet d'avoir accès à cet fonction, il est plus simple et juste de passer par les fonctions (vla-get-property). En effet, cela permet d'éviter l'utilisation du (cond) pour chaque type d'entité linéaire et t'évite le calcul des longueurs (arc par exemple) et l'utilisation des command+getvar dans le cas des entités linéaires complexes... Dans la liste DXF que tu as envoyée (cf ci-dessus), il existe un code 102 faisant référence à un réacteur. Ces réacteurs sont des liaisons entre des entités pour que, si une entité est modifiée par exemple, l'autre entité liée est modifiée également. Pour un exemple concret, une hachure associative correspond justement à une liaison directe entre ta hachure et ton contour. Si ton contour est modifié au niveau de sa géométrie, la hachure va suivre pour conserver le contour. Donc je suppose ici que c'est le cas de ta polyligne (elle doit être liée à un objet) mais encore une fois, je doute sincèrement que cette liaison interfère avec l'utilisation de la commande "AREA". Ce réacteur (situé au code DXF 102) fait référence à l'objet lié via le code 330 : ((-1 . <Nom d'entité: 7ffffbab150>) (0 . "LWPOLYLINE") (5 ."8C05") (102 . "{ACAD_REACTORS") (330 . <Nom d'entité: 7ffffbaef70>) (102 . "}") (330 . <Nom d'entité: 7ffffb119f0>) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 2) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 823989.0 270367.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (10 823988.0 270366.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (91 . 0) (210 0.0 0.0 1.0)) ;; on extrait uniquement la partie "réacteur" : ( (102 . "{ACAD_REACTORS") ;; Début du marqueur du réacteur (330 . <Nom d'entité: 7ffffbaef70>) ;; Nom d'entité liée à la polyligne (102 . "}") ;; Fin du marqueur du réacteur ) ;;Pour récupérer les informations sur l'objet lié, tu peux utiliser ceci dans la barre de commande AutoCAD et en cliquant sur la polyligne problématique ou bien remplacer le (car (entsel)) par ename et évaluer cette expression via l'espion avec un arrêt sur erreur : (entget (cdr (assoc 330 (entget (car (entsel "\nSélectionner la polyligne :")))))) Bon, je tiens à m'excuser d'avance... J'ai la fâcheuse manie de beaucoup blablater sans faire avancer le schmilblick... Bisous, Luna -
Compatibilité "{ACAD_REACTORS" + perimeter
Luna a répondu à un(e) sujet de Pirlouit dans Pour aller plus loin en LISP
Salut, Pourquoi ne pas passer par une fonction pour récupérer l'aire de la polyligne comme ceci par exemple pour éviter l'utilisation d'une commande : ;;version vanilla (vl-catch-all-error-p (setq Area (vl-catch-all-apply 'getpropertyvalue (list ename "AREA")))) ;; ou bien en visual (vl-catch-all-error-p (setq Area (vl-catch-all-apply 'vla-get-area (list (vlax-ename->vla-object ename))))) Serait-il possible de connaître l'objet auquel est rattachée la polyligne (les deux codes 330 sont différents) ? Je doute qu'une liaison reactor influe sur la lecture de l'aire de la polyligne cependant mais il y a forcément une explication :3 Bisous, Luna -
vouih, j'avais en effet testé le (command "cmd") pour vérifier.. Donc ça signifie que l'ensemble des fonctions/commandes développées via VLIDE ne sont pas "visibles" pour AutoCAD ? Bisous, Luna
