-
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
-
Bonjour, Selon l'aide AutoCAD sur la variable système CMDACTIVE, on a ceci : Donc au niveau de ma compréhension (limitée), ce que AutoCAD considère comme une commande "ordinaire" (bit 1) correspond aux commandes natives d'AutoCAD. Donc cela ne prend pas en compte les commandes custom (defun c:cmd () [...] ) si je comprend bien.. Mais dans ce cas, comment savoir si une commande custom est en cours d'exécution ? Car je n'arrive pas bien à comprendre les bit 16, 32 et 64... Car si je fait un code simple comme ceci : (defun fun () (getvar "CMDACTIVE") ) (defun c:cmd () (getvar "CMDACTIVE") ) command: (fun) 0 command: CMD 0 commande: POLYLIGN Spécifiez le point de départ: La largeur courante est de 0.000. Spécifiez le point suivant ou [Arc/Demi-larg/LOngueur/annUler/LArgeur]: (getvar "CMDACTIVE") 1 Spécifiez le point suivant ou [Arc/Clore/Demi-larg/LOngueur/annUler/LArgeur]: Du coup je n'arrive pas bien à saisir dans quel contexte on pourrait savoir si une commande (quelqu'elle soit) est active.. Merci pour vos éclaircissements :3 Bisous, Luna
-
Salut, Je ne connais pas ArchiCAD donc je vais peut-être t'aiguiller sur une mauvaise piste mais il me semble que le gestionnaire des états de calques correspond à ce principe... A vrai dire je ne l'utilise pas personnellement mais j'ai pu testé son efficacité :3 tu peux y accéder via le gestionnaire de calque (3ème icône en partant de la gauche au dessous de l'entête de la palette), ou via la commande LMAN L'idée de ce gestionnaire est d'enregistrer une "image" de ton gestionnaire de calque sous un état nommé... Ainsi tu peux lui définir un premier état avec le plan général et le calque éclairage, et un second état avec le plan général (couleur des calque en gris), le calque élec' et le calque éclairage. Du coup dans tes fenêtres au lieu de passer par le gestionnaire de calque, tu utilises LMAN (dans la fenêtre active) et tu restaures l'état de calque désiré. Bon après, je peux aussi être à côté de la plaque, désolé... Bisous, Luna
-
DCL: Insérer une tuile entre deux radio_button
Luna a répondu à un(e) sujet de Fraid dans Pour aller plus loin en LISP
Salut, Je peux te proposer ceci (fonctionnel) : (defun try (/ laylist dcl_id chx) (setq laylist (flt_tbl "LAYER" "*") dcl_id (load_dialog "Test.dcl") ) (if (not (new_dialog "DBtest" dcl_id)) (exit) ) (start_list "lst") (mapcar 'add_list laylist) (end_list) (set_tile "lst" (itoa (vl-position "0" laylist))) (mode_tile "lst" 1) (mode_tile "eb" 1) (action_tile "rb0" "(mode_tile \"lst\" 1) (mode_tile \"eb\" 1) (set_tile \"rb1\" \"0\") (set_tile \"rb2\" \"0\")") (action_tile "rb1" "(mode_tile \"lst\" 0) (mode_tile \"eb\" 1) (set_tile \"rb0\" \"0\") (set_tile \"rb2\" \"0\")") (action_tile "rb2" "(mode_tile \"lst\" 1) (mode_tile \"eb\" 0) (set_tile \"rb0\" \"0\") (set_tile \"rb1\" \"0\")") (action_tile "cancel" "(done_dialog 0)") (action_tile "accept" "(cond ((= (get_tile \"rb0\") \"1\") (setq chx (getvar \"CLAYER\"))) ((= (get_tile \"rb1\") \"1\") (setq chx (nth (atoi (get_tile \"lst\")) laylist))) ((= (get_tile \"rb2\") \"1\") (setq chx (get_tile \"eb\"))) ) (done_dialog 1) " ) (start_dialog) (unload_dialog dcl_id) chx ) A adapter pour le fichier .dcl temporaire mais c'est une simple piste de recherche ;) En fait en écrivant le code LISP, j'ai remarqué que le souci venait tout simplement du radio_button_column qui, normalement ne s'attend qu'à des radio_button (je rappelle que je maîtrise pas, alors arrêter moi si je dis des bêtises :3), or on a ici une pop-up_list qui sépare le radio_button n°1 et le radio_button n°2 (sachant que le premier correspond au n°0). Ainsi, il ne comprend pas que les 3 radio_button sont liés ! Donc il est voit en réalité deux rangées dans une seule box ... en clair, si le "rb2" est activé à un moment ou un autre, il ne se désactivera pas, cependant il y a bien un toggle qui est opéré entre le "rb0" et le "rb1" (comme on s'y attend venant des radio_button) C'est pour ça que j'ai ajouté les (set_tile "rb#" "0") pour être sûre qu'un seul des radio_button est bel est bien sélectionné ! Bisous, Luna -
DCL: Insérer une tuile entre deux radio_button
Luna a répondu à un(e) sujet de Fraid dans Pour aller plus loin en LISP
Hiya ! Je ne sais pas si cela pourra t'aider, mes compétences en DCL sont nulles, mais j'avais trouvé ce sujet il y a quelques temps sur un problème similaire : https://cadxp.com/topic/6776-dcl-et-lisp-desactiver-un-bouton/ Désolé, Luna -
Salut ! Merci GEGEMATIC :3 mais je manque cruellement d'expérience dans le domaine de la programmation malheureusement... Pour avoir déjà fait quelques recherches à ce sujet, une hachure associative se différencie d'une non associative via le code DXF 97 (0 si non associative, 1 sinon) ainsi que l'existence du code DXF 330 qui pointe vers l'objet associé (qui vient en plus du code DXF 330 pointant vers le "BLOCK_RECORD") et donc il faut également un code DXF 330 pointant vers l'objet hachure dans la liste de l'objet associé (ce qui est complexe, car cette référence-ci est indiquée de la manière suivante : (entget (car (entsel))) -> (... (102 . "{ACAD_REACTORS") (330 . <Hatchentityname>) (102 . "}") ...) Donc quelque peu complexe à gérer via entmake car cela requiert de modifier également les entités existantes, si tenté que ça fonctionne --") Voili voilou :) Ensuite pour ce qui est des codes obligatoires, de manière générale on aura toujours les codes DXF 0, 10 (et/ou 11 selon le type d'objet), 100 (référence plus précise du type d'objet) et à ceux-là s'ajouteront certains codes associés au type d'objet lui-même Bisous, Luna
-
Salut, Je n'ai jamais utiliser entmake pour les hachures, donc je risque de dire des bêtises, mais je pense que les codes DXF 10 (correspondant à la liste des points sont nécessaires. Tu peux essayer de voir ce post (en anglais) car il pourrait t'aider : https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/entmake-hatch-with-base-point-or-object-polyline-entity-name/td-p/8696712 Bisous, Luna
-
Nouveautés AutoLISP avec AutoCAD 2021
Luna a répondu à un(e) sujet de (gile) dans LISP et Visual LISP
Vouih sauf que le débogage est toujours possible (uniquement à partir d'AutoCAD 2021..) sur VS code comme tu l'as dit :) Après, j'ai beaucoup procédé en programmant sur VS code, et lorsque j'avais besoin de tester le programme, je lançais AutoCAD, VLIDE, un piti copier/coller entre VS code et VLIDE et le tour est joué, mais au moins, j'avais l'interface de VS code pour programmer.. ^^" Et si AutoCAD me claquais entre les doigts, je n'avais rien perdu puisque mon code était sur VS code (après seul bémol, c'est lorsque les modifications à apporter sont importantes, auquel cas, il faut faire la passerelle entre VLIDE et VS code ..) Mais pour info, j'utilise actuellement VLIDE uniquement, bien que je ne le supporte pas personnellement... Bisous, Luna -
Nouveautés AutoLISP avec AutoCAD 2021
Luna a répondu à un(e) sujet de (gile) dans LISP et Visual LISP
Je viens enfin de découvrir comment afficher le contenu d'une variable directement dans AutoCAD sans utiliser la fonction (princ) ... --" Merci Fraid ! <3 Encore une méthode inconnue... j'ai tellement de choses à apprendre moi..! Et dire qu'avant je copier coller les parties de code sous forme de fonction pour les tester jusqu'à trouver la ligne qui avait un bug... En effet VS code n'est pas encore au point sur toutes les fonctionnalités de VLIDE, mais c'est notamment dû au fait qu'il ne fait pas parti intégrante d'AutoCAD.. Cela vient aussi des différences d'encodage (Unicode / ASCII) mais d'après Fraid, ce souci peut-être réglé ! Le souci principal que je rencontre sur l'utilisation de VLIDE c'est justement son implantation dans AutoCAD ! Il faut absolument avoir un fichier de dessin ouvert pour pouvoir programmer, en clair, si votre AutoCAD plante, vous perdez tout votre travail (Dessin et programmation). Ce problème n'existe pas avec VS code car on peut très bien ouvrir un fichier .lsp sans même ouvrir AutoCAD (on peut très bien avoir à créer des programmes n'ayant pas besoin de tests approfondis et donc sans débogage nécessaires) ! De plus, l'interface VLIDE est assez "agressive" (contrairement à VLIDE, VS code peut avoir un thème applicable), alors que dans VS code, on a beaucoup plus d'options de réglage sur l'interface de travail (couleur d'arrière-plan, couleur des différents type de données, taille de texte, mip-map, ...) Le nombre de fois que j'ai des problèmes entre AutoCAD et VLIDE, comme par exemple, impossible de reprendre la main sur AutoCAD car VLIDE considère qu'il a une action de débogage en cours alors qu'aucun programme est en cours d'exécution --" Bref, VS code, malgré ses défauts de compatibilité avec l'interface directe d'AutoCAD possède de nombreux avantages sur le confort d'utilisation au quotidien. De plus, je trouve que le système de tabulation auto de VLIDE (équivalent à 2 espaces) n'est pas suffisamment aéré (mais il s'agit d'un avis purement personnel ! hihi), tandis que sur VS code, la gestion de la mip-map, de l'affichage/ masquage des fonctions et la sélection multiple de chaînes de caractères identiques (un régal lorsque l'on souhaite modifier une données répétitive au sein d'un programme) Après pour ce qui est des propriétés des objets accessible via une liste déroulante, je crois qu'on ne le verra jamais, malheureusement ! :.( mais je suis totalement d'accord pour dire que ça serait un rêve ! Cependant, VS code possède la liste déroulante pour les fonctions connues, ce qui permet par exemple, en tapant "(vl-" d'avoir accès à l'ensemble des fonctions qui possèdent cette chaîne de caractères (très pratique pour découvrir de nouvelles fonctions que l'on ne cherche pas par exemple) ça c'est parfait pour savoir si une fonction perso est écrite correctement, ce qui est assez agaçant parfois..^^" +1 avec Fraid ! Bisous, Luna -
Nouveautés AutoLISP avec AutoCAD 2021
Luna a répondu à un(e) sujet de (gile) dans LISP et Visual LISP
YAY !!!! La meilleure nouvelle de la journée ! C'est un outil bien plus puissant que l'éditeur natif d'AutoCAD ! J'avais commencé le LISP sur Visual Studio Code, mais malheureusement, lors de l'importation des codes via APPLOAD, les caractères non anglophones étaient remplacé par "@" (les accents par exemple) ce qui est assez gênant à la lecture... Autre bémol, Visual Studio Code ne possédait pas d'outils de débogage fonctionnels avec le langage LISP, ce qui nécessite la création de fonctions et de tester directement sur AutoCAD via la ligne de commande... Donc je suis comblée ! En espérant la plupart des défauts de compatibilité seront réglés ;) Au fait, question un peu à part.. : pour quelles raisons le site d'AutoCAD Knowledge à supprimer l'ensemble des pages d'aide sur les fonctions AutoLISP ? Nous sommes contraints de travailler avec l'aide directement accessible depuis AutoCAD (ce qui limite le nombre de page ouvertes à 1 --") et donc de ne plus pouvoir travailler avec AutoCAD d'un côté, et internet de l'autre ? Bref... bonne nouvelle pour ma part mais à suivre ! Bisous, Luna -
Modification d'un LISP "CHAMPSOLIDE" de Gilles
Luna a répondu à un(e) sujet de LElemurien dans LISP et Visual LISP
Ah vouih pardon !!! C'est ma faute, j'avais au départ ajouté une variable nommée jsel pour faire la différence entre le nom de l'entité et le jeu de sélection, mais j'avais moyen de ne pas le faire, du coup j'ai corrigé le code mais j'ai oublié de remplacer le "jsel" par "ent" pour la ligne (= (sslength jsel) 1) Le code est corrigé au-dessus ;) ça devrait être mieux en théorie :3 Bisous, Luna -
Modification d'un LISP "CHAMPSOLIDE" de Gilles
Luna a répondu à un(e) sujet de LElemurien dans LISP et Visual LISP
Chalut ! Pour qu'une commande/fonction puisse prendre en compte une pré-sélection tu peux essayer de regarder du côté de (last (ssgetfirst)). Cela te retourne un jeu de sélection si des entités sont actuellement sélectionnées (sous réserve que la variable PICKFIRST soit définie à 1), nil sinon. Auquel cas, je pourrais te proposer la forme suivante : (defun c:CHAMPSOLIDE (/ ent solidType str) (vl-load-com) (if (not (and (setq ent (last (ssgetfirst))) (= (sslength ent) 1) (= (cdr (assoc 0 (entget (setq ent (ssname ent 0))))) "3DSOLID" ) (not (vl-catch-all-error-p (setq SolidType (vl-catch-all-apply 'getpropertyvalue (list ent "SolidType") ) ) ) ) (member solidType '("Boîte" "Cylindre" "Cône" "Sphère" "Pyramide" "Biseau" "Tore" ) ) ) ) (while (not (and (setq ent (car (entsel "\nSélectionnez un solide (primitive uniquement): " ) ) ) (= (cdr (assoc 0 (entget ent))) "3DSOLID") (not (vl-catch-all-error-p (setq solidType (vl-catch-all-apply 'getpropertyvalue (list ent "SolidType") ) ) ) ) (member solidType '("Boîte" "Cylindre" "Cône" "Sphère" "Pyramide" "Biseau" "Tore" ) ) ) ) (prompt "\nSélection non valide.") ) ) (setq id (vla-GetObjectIdString (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object)) ) (vlax-ename->vla-object ent) 0 ) str (cond ((= solidType "Boîte") (strcat "Longueur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Length \\f \"%lu6\">%" "\\PLargeur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Width \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) ) ((= solidType "Cylindre") (if (zerop (getpropertyvalue (car (entsel)) "Elliptical")) (strcat "Rayon = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Radius \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) (strcat "Grand rayon = %<\\AcObjProp Object(%<\\_ObjId " id ">%).MajorRadius \\f \"%lu6\">%" "\\PPetit rayon = %<\\AcObjProp Object(%<\\_ObjId " id ">%).MinorRadius \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) ) ) ((= solidType "Cône") (if (zerop (getpropertyvalue (car (entsel)) "Elliptical")) (strcat "Rayon de base = %<\\AcObjProp Object(%<\\_ObjId " id ">%).BaseRadius \\f \"%lu6\">%" "\\PRayon supérieur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TopRadius \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) (strcat "Grand rayon de base = %<\\AcObjProp Object(%<\\_ObjId " id ">%).BaseMajorRadius \\f \"%lu6\">%" "\\PPetit rayon de base = %<\\AcObjProp Object(%<\\_ObjId " id ">%).BaseMinorRadius \\f \"%lu6\">%" "\\PGrand rayon supérieur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TopMajorRadius \\f \"%lu6\">%" "\\PPetit rayon supérieur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TopMinorRadius \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%") ) ) ((= solidType "Sphère") (strcat "Rayon = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Radius \\f \"%lu6\">%" ) ) ((= solidType "Pyramide") (strcat "Côtés = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Sides >%" "\\PRayon de base = %<\\AcObjProp Object(%<\\_ObjId " id ">%).BaseRadius \\f \"%lu6\">%" "\\PRayon supérieur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TopRadius \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) ) ((= solidType "Biseau") (strcat "Longueur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Length \\f \"%lu6\">%" "\\PLargeur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Width \\f \"%lu6\">%" "\\PHauteur = %<\\AcObjProp Object(%<\\_ObjId " id ">%).Height \\f \"%lu6\">%" ) ) ((= solidType "Tore") (strcat "Rayon de tore = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TorusRadius \\f \"%lu6\">%" "\\PRayon de tube = %<\\AcObjProp Object(%<\\_ObjId " id ">%).TubeRadius \\f \"%lu6\">%" ) ) ) ) (vl-cmdf "_.mtext" pause "_width" 0.0 str "") (princ) ) Non testé mais cela devrait vérifier l'existence d'une pré-sélection, et effectue les mêmes vérifications que la sélection prévue par (gile) ainsi que le fait qu'il n'y ait qu'un unique objet dans le jeu de sélection. En revanche, si ta demande requiert de prendre en compte un jeu de sélection (contenant plusieurs objets) cela va modifier le programme davantage ! En espérant avoir répondu à tes attentes :) Bisous, Luna -
Ah et euh... Il s'agit d'un avis purement personnel, mais pour les commandes j'ai pris l'habitude de renvoyer dans l'historique de commande les résultats car ça permet au développeur de vérifier les infos (dans un premier temps si la commande parvient jusqu'au bout, et ensuite de checker les infos directement dans AutoCAD et non l'espion) mais aussi à l'utilisateur lambda qui, en lançant une commande, aimerait bien être sûr que ça a marché :) C'est un moyen d'informer par exemple le nombre d'objets impactés, le calque, la couleur forcée et ce genre de choses (tout dépend des informations qui te semblent utile pour l'utilisateur pour faire un check lui aussi de son côté). Parce que les commandes fantômes, même si on voit un résultat visuel parfois, on n'a pas vu qu'on a modifié plus que prévu ou moins... ^^" Aller bisous, Luna
-
Salut ! Je n'ai pas tester ton code, mais dans un premier temps, es-tu sûr que le type de ligne que tu souhaites forcer est bien charger dans le dessin sur lequel tu travailles ? Cela pourrait être une source d'erreur car ton programme essaye de forcer un type de ligne qu'il ne connait pas. Normalement il ne devrait pas y avoir de problème si le calque n'existe pas, il se créé automatiquement. Tu peux également essayer de voir du côté des fonctions (setpropertyvalue), (getpropertyvalue) et (dumpallproperties) qui permettent d'accéder aux propriétés d'un objet (donc on a accès aux propriétés visible dans la palette de propriétés d'AutoCAD concrètement). Auquel cas, si jamais la couleur et le type de ligne ne fonctionne pas vraiment via (entmod), je rappelle que je n'ai pas tester ton programme (désolé), tu peux tenter de remplacer (if (= (assoc 62 e1p) nil) (setq e1p (append (list (cons 62 color)) e1p)) ;;insertion couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était en couleur "ducalque") (setq e1p (subst (cons 62 color) (assoc 62 e1p) e1p)) ;;modification de la couleur forcée dans les propriétés de l'entité du bloc CLIENT (cas où la pl était déja en couleur forcée) ) par (setpropertyvalue e1 "COLOR" color) En revanche pour les type de lignes c'est plus complexe, car les fonctions (-propertyvalue) requièrent l'ID du type de ligne, et non le nom... PS : il s'agit juste d'une remarque pour éviter les erreurs d'interactions entre tes différents LISP, mais je te conseille d'utiliser des variables locales, au lieu de variables globales. La fonction (defun) fonctionne de la manière suivante (defun sym ([arguments] [/ variables ...]) expr ...) Avec : - "sym" le nom de ta fonction (ou commande si précédée d'un "c:") - [arguments] pour les arguments, donc ici inutile car il s'agit d'une commande (à savoir que lorsque c'est écrit entre crochets, cela signifie que c'est optionnel) - [/ variables] pour déclarer des variables locales (elles sont placées dans la même parenthèse que les arguments mais séparées des arguments d'un unique slash) - expr correspond au code de ton programme Donc si tu veux, une fonction possédant 1 argument et 1 variable locale s'écrit (defun func (arg1 / var1) ...) 0 arguments et 2 variables locales (defun func (/ var1 var2) ...) 2 arguments et 0 variables locales (defun func (arg1 arg2) ...) Bref l'idée de déclarer des variables locales c'est qu'à chaque exécution du programme, une fois terminé, toutes les variables locales déclarées sont vidées de la mémoire (= nil) ce qui évite par exemple que dans un programme qui construit une liste via la fonction (cons) dans une boucle du genre (defun func (n) (repeat n (setq lst (cons (setq n (1- n)) lst)) ) ) Au premier lancement lst = nil, puis pour n=4, tu obtiens lst = (0 1 2 3) Au second lancement lst = (0 1 2 3) puis pour n = 7, tu obtiens lst = (0 1 2 3 4 5 6 0 1 2 3) etc Mais en regardant, tu insères dans ta boucle un (setq ss (ssadd)) pour tes jeux de sélection donc tu les remets à 0 manuellement donc tu ne dois pas avoir de soucis pour ce programme à ce niveau là, mais c'est un confort supplémentaire et ça limite les erreurs :) Bref je ne t'aide pas des masses...
-
Salut, En effet c'est une optimisation fort intéressante ! je connaissais déjà les fonctions vl-string-right-trim et vl-string-left-trim (que j'utilise dans une fonction récurrente) mais j'avais pour ainsi dire, complètement oublié la possibilité de spécifier l'ensemble des caractères numériques de la sorte.. Bravo à toi, ta fonction me semble parfaite ;) En tout cas, je comprend mieux pourquoi j'aime tant la programmation, il n'existe pas un unique chemin pour parvenir au résultat escompté ! Certains sont plus sinueux que d'autres mais chaque chemin mérite d'être tracé car ils reflètent tous à leur manière la logique et l'ingéniosité de chacun donc merci à toi pour ce partage ! <3 Pour info (gile) l'idée de cette fonction est d'être utilisable sur toute forme de liste (bien sûr sur les listes composées elles-mêmes de listes, vaut mieux passer par un (mapcar) + (lambda) adapté à la situation) et notamment : la liste des calques ! Car vouih la liste des calques et une zone de guerre, où chacun nomme comme il veut, par des chaînes de caractères en minuscule, majuscule, majuscule au début, avec des chiffres, ... bref on connaît le type de chaque élément (des strings) mais leur contenu est une inconnue (surtout en partant déjà avec par défaut le calque "0" hihi) du coup il me fallait une fonction un peu touche à tout ! ;) Voili voilou ! Bisous, Luna
-
C'est que la fonction (grread) a du renvoyer un code 12 (voir Aide), que renvoie un espion sur ta variable gr au moment de l'erreur ? Donc peut être ajouter une vérification plus poussée pour filtrer les codes non utiles à ta fonction ? Bisous, Luna
-
Toutes les options de SSGET
Luna a répondu à un(e) sujet de bonuscad dans Pour aller plus loin en LISP
La couleur 0 correspond à DuBloc, pour DuCalque il s'agit de la couleur 256 :) Donc un truc du genre : (sslength (ssget "_X" '((-4 . "<NOT")(62 . 256)(-4 . "NOT>")))) (sslength (ssget "_X" '((-4 . "<NOT")(-4 . "<OR")(62 . 0)(62 . 256)(-4 . "OR>")(-4 . "NOT>")))) Fonctionne en effet mieux !!^^ Pourquoi faire compliqué quand on peut faire simple et propre !^^' Bisous, Luna -
Toutes les options de SSGET
Luna a répondu à un(e) sujet de bonuscad dans Pour aller plus loin en LISP
Salut ! Tu peux essayer de faire des tests via l'opérande "&". Je n'ai pas vraiment de connaissance dans ce sujet mais avec les quelques tests effectués, j'ai pu obtenir des résultats : (sssetfirst nil (ssget "_X")) ; Retourne A, B, C, D, E, F, G, H (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 0)))) ; Retourne nil (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 1)))) ; Retourne C, G, H (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 2)))) ; Retourne C, D, F, G (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 3)))) ; Retourne C, D, F, G, H (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 4)))) ; Retourne D, E, F (sssetfirst nil (ssget "_X" '((-4 . "&") (62 . 5)))) ; Retourne C, D, E, F, G, H ... Je ne trouve pas vraiment d'aide sur le code DXF 62 particulièrement est donc notamment sur cet opérande "&" et son fonctionnement (bit de validation), je pense que (gile) ou tout autre lispeur sachant lispé avec les codes DXF et les filtres (ssget) seront plus à même de t'aider.. Il me semble que le problème vient du fait que les couleurs ont différents nom et format (de 0 à 256 ; R,V,B ; carnet de couleur ; ...) et donc il est possible que l'on soit obliger de parler en binaire ou hexadécimale pour l'opérande "*" mais encore une fois, je ne suis pas une sachante donc ce ne sont que des spéculations ^^' Bisous, Luna -
Bonjour, J'avais en effet pas penser à la fonction (grread) dans une boucle (while) pour reconstituer la chaîne de caractère, c'est très ingénieux !! Cependant, je ne comprend pas très bien pourquoi définir le premier argument de (grread) sur t (enfin VRAI quoi) parce que du coup, l'utilisateur n'a aucune saisi possible !--" Il renvoie automatiquement la localisation du pointeur avec une paire pointée suivant le code 5, alors qu'en désactivant l'argument track (= nil), l'utilisateur a la main et peux rentrer une chaîne de caractères, valider ou cliquer sur un point (en gros, il peut bouger la souris et accéder à son clavier) Après je n'ai pas tester ton programme personnellement, c'est uniquement sur l'utilisation isolée de (grread) dont je me souviens... Bisous, Luna
-
Salut, En effet, auquel cas, le problème pourrait être "esquiver" via une boîte de dialogue (je sais que ça peut sembler lourd mais au final, ça l'est beaucoup moins que de devoir se taper le nom entier du bloc à la mano !^^') Pour cela, j'ai pris l'habitude d'utiliser la fonction ListBox de BonusCAD (qui je viens de l'apprendre, serait de (gile) hihi) qui est super géniale !! (voir le post #6) Après pour être honnête, je l'ai modifiée légèrement car je l'utilise avec des listes d'atomes simples (pas de (key . label)) donc si veux voici ma version (1 argument supplémentaire pour une valeur par défaut) : ;--- LISP de bonusCAD publié sur CADXP.com le 11/01/2016 11:34 ;--- Version modifiée de la fonction (ListBox), possède 5 arguments ;--- title correspond à l'entête de la boîte de dialogue ;--- msg correspond au message affiché au dessus de la liste ;--- lst correspond à la liste à afficher ;--- value correspond à la valeur définie par défaut ;--- flag correspond au type de liste souhaitée ; flag = 0 -> liste déroulante (choix unique) ; flag = 1 -> liste avec barre de défilement (choix unique) ; flag = 2 -> liste avec barre de défilement (choix multiple) ; Renvoie la liste des éléments ayant été sélectionnés (defun ListBox (title msg lst value flag / tmp file DCL_ID choice) (setq tmp (vl-filename-mktemp "tmp.dcl") file (open tmp "w") ) (write-line (strcat "ListBox:dialog{width=" (itoa (+ (apply 'max (mapcar 'strlen (mapcar 'vl-princ-to-string lst))) 5)) ";label=\"" title "\";") file ) (if (and msg (/= msg "")) (write-line (strcat ":text{label=\"" msg "\";}") file) ) (write-line (cond ((= 0 flag) "spacer;:popup_list{key=\"lst\";") ((= 1 flag) "spacer;:list_box{height=15;key=\"lst\";") (t "spacer;:list_box{height=15;key=\"lst\";multiple_select=true;") ) file ) (write-line "}spacer;ok_cancel;}" file) (close file) (setq DCL_ID (load_dialog tmp)) (if (not (new_dialog "ListBox" DCL_ID)) (exit) ) (start_list "lst") (mapcar 'add_list lst) (end_list) (set_tile "lst" (if (member value lst) (itoa (vl-position value lst)) (itoa 0))) (action_tile "accept" "(or (= (get_tile \"lst\") \"\") (if (= 2 flag) (progn (foreach n (str2lst (get_tile \"lst\") \" \") (setq choice (cons (nth (atoi n) lst) choice)) ) (setq choice (reverse choice)) ) (setq choice (nth (atoi (get_tile \"lst\")) lst)) ) ) (done_dialog)" ) (start_dialog) (unload_dialog DCL_ID) (vl-file-delete tmp) choice ) ;--- LISP de bonusCAD publié sur CADXP.com le 11/01/2016 11:34 ;--- Nécessaire au bon fonctionnement de la fonction (ListBox) ci-dessus (defun str2lst (str sep / pos) (if (setq pos (vl-string-search sep str)) (cons (substr str 1 pos) (str2lst (substr str (+ (strlen sep) pos 1)) sep) ) (list str) ) ) Ainsi tu pourrais ne pas faire de validation après le (getstring) mais plutôt à la place du (getstring), du tout-en-un quoi ^^' On pourrait donc avoir ceci : (defun try (/ bloclist name chx) (setq name (cdr (assoc 2 (tblnext "BLOCK" t)))) (while name (setq bloclist (cons name bloclist) name (cdr (assoc 2 (tblnext "BLOCK"))) ) ) (initget "Texte") (if (or (null (setq chx (getpoint "\nChoisir une entité ou [Texte] <Texte> : "))) (= chx "Texte")) (setq chx (ListBox "Sélection du bloc" "Choisir le nom d'un bloc" (vl-sort (vl-remove-if '(lambda (B) (wcmatch b "`*U*,`*D*")) bloclist) '<) nil 1)) (setq chx (getpropertyvalue (ssname (ssget chx '((0 . "INSERT"))) 0) "BlockTableRecord/Name")) ) ) ça retourne le nom de la définition de bloc sélectionnée via la boîte de dialogue ou via un (getpoint)+(ssget). C'est pas parfait, et notamment au niveau du ssget, qui retourne une erreur si aucun objet de type bloc n'est sélectionné, donc c'est préférable de mettre un boucle pour s'assurer de la validation de l'utilisateur, mais ça reste une piste je pense :) En espérant que ça puisse t'aider en tout cas ! Bisous, Luna
-
Salut ! Malheureusement nan, mais fana de la culture Jap' :) Après quelques tests, la fonction (entsel) me retourne toujours l'entité dernièrement créée si le point cliqué fait référence à plusieurs entités différentes situées sur un plan différent (élévation pour "LWPOLYLINE" et coordonnées Z pour les sommets de "POLYLINE" 3D) sans tenir compte de l'altitude la plus élevée ou de la plus proche au-dessous de Z=0. Je travaille jamais/rarement en 3D donc mon expérience dans ce domaine est limitée mais si je teste rapidement les fonctions on a : (entsel "\nCliquez sur l'écran") ; Sélection vide nil (entsel "\nCliquez sur l'écran") ; Sélection d'un objet (<Nom d'entité: 500a9570> (403.995 -302.801 0.0)) ; On remarque donc que (entsel) reprend le format d'un retour de getpoint pour le (cadr) puisqu'on a un point 3D avec Z = 0.0 (getpoint "\nCliquez sur l'écran") ; Ne clique pas et appuis sur ENTER ou SPACE nil (getpoint "\nCliquez sur l'écran") ; Clic sur écran (403.995 -302.801 0.0) ; Retour d'un point 3D systématique (Z = 0.0 si le point n'appartient à aucun objet dont la valeur du Z est différente de 0.0) Du coup quel est le soucis exactement au niveau de la saisie 3D car (ssname (ssget pt) 0) retourne le même résultat qu'un (car (entsel)) par rapport à ma configuration d'AutoCAD... Donc si je prend : (defun Test (/ chx) (initget "Texte") (if (or (null (setq chx (getpoint "\nChoisir une entité ou [Texte] <Texte> : "))) (= chx "Texte")) (setq chx (getstring "\nEntrez le texte : ")) (setq chx (ssname (ssget chx) 0)) ) ) Commande: (test) Commande: Choisir une entité ou [Texte] <Texte> : ; Appui sur ENTER ou SPACE Commande: Entrez le texte : Essai Commande: "Essai" Commande: (test) Commande: Choisir une entité ou [Texte] <Texte> : (403.995 -302.801 0.0) ; Clic sur l'écran Commande: <Nom d'entité: 500a9570> Commande: (test) Commande: Choisir une entité ou [Texte] <Texte> : T Commande: Entrez le texte : Essai Commande: "Essai" Donc je pense que je n'ai pas compris votre demande ^^' Bisous, Luna
-
Bonjour, La fonction (entsel) possède déjà un argument pour afficher un message personnalisé :) Il est vrai qu'on ne le spécifie que rarement mais il est bien présent (si j'ai bien compris ta demande ^^') Voir aide AutoCAD Sumimasen, après relecture, je me suis levée du pied gauche ! Le problème d'initget c'est qu'il n'est pas compatible avec la fonction (getstring) cependant, tu peux tricher ! Si l'utilisateur diot retourner des chaînes de caractères spécifique (similaire à (getkword)), tu peux voir un (initget) avec les mots clés auquel tu associe un (getpoint) (et via le (getpoint), tu récupères l'entité située à ce point - mais il faudra passer par une sélection relative ou via un fuzz - ) Peut-être voir du côté de (nentselp) si (ssget) ne fonctionne pas correctement mais attention car (entsel) est différent de (nentsel) donc à voir selon tes besoins : https://documentation.help/AutoLISP-Functions/WS1a9193826455f5ff1a32d8d10ebc6b7ccc-699b.htm Si tu as une entrée de chaînes libres, je n'ai pas d'autres solutions que de te proposer un (getpoint) associer avec un (getkword), de ce genre là (non testé, notamment au niveau de la récupération de l'entité) : (initget "Texte") (if (null (setq chx (getpoint "\nChoisir une entité ou <Texte> : "))) (setq chx (getstring "\nEntrez le texte : ")) (setq chx (ssname (ssget chx) 0)) ) Bisous, Luna
-
Salut ! Encore merci à toi (gile), j'ai dû corriger mes erreurs sur mes fonctions car ma fonction permettant d'identifier les pattern était...loin d'être utile car j'avais des risques importants de perte d'informations. Mais en suivant la logique (de manière simplifiée bien sûr car je n'ai pas tout bien compris encore sur tes fonctions régulières et leur fonctionnement) j'ai pu obtenir ceci pour trier une liste random (tout type confondu) : ; Permet de trier une liste en ignorant la la casse et en évitant les erreurs de numérotations induites par la fonction (vl-sort) : ;--- La fonction (sort-list) possède 2 arguments ;--- lst correspond à la liste devant être triée, pouvant contenir tout type d'élément (chaînes de caractères à conseiller) ;--- flag défini si l'on souhaite trier la liste dans l'ordre croissant, ou décroissant ; flag = 0 -> Trie dans l'ordre croissant ; flag = 1 -> Trie dans l'ordre décroissant ;--- Renvoie la liste une fois triée (defun Sort-list (lst flag / a B) (if (not (member flag '(0 1))) (setq flag 0) ) (mapcar 'car (vl-sort (get-pattern-list lst) '(lambda (a B) (if (= (caadr a) (caadr B)) ((cond ((= flag 0) <) ((= flag 1) >)) (atoi (cdadr a)) (atoi (cdadr B))) ((cond ((= flag 0) <) ((= flag 1) >)) (caadr a) (caadr B)) ) ) ) ) ) ; Permet de décomposer chaque membre d'une liste sous forme de sous-liste composée de l'élément original, puis de sa racine (ou pattern) et de son incrément : ;--- La fonction (get-pattern-list) possède 1 argument ;--- lst correspond à la liste que l'on souhaite étudier ;--- Renvoie une liste avec la décomposition des membres sous la forme (str . (pattern . num)) avec : ; - str l'élément (avec conservation du type) qui sera décomposer ; - pattern correspond à une chaîne de caractères majuscule correspondant à l'élément str dont on a retiré les chiffres situés en fin de chaîne uniquement (hypothèse) ; - num correspond à une châine de caractères correspondant à l'incrément du pattern, soit l'ensemble des chiffres situés en fin de chaîne (hypothèse) ; Ex. : Avec str = "Calque1", on a pattern = "CALQUE" et num = "1" ; Avec str = "Test", on a pattern = "TEST" et num = "" ; Avec str = 15, on a pattern = "" et num = "15" ; ... (defun get-pattern-list (lst / str pattern) (mapcar '(lambda (str / pattern) (if (distof (vl-princ-to-string str) 2) (cons str (list (cons "" (vl-princ-to-string str)))) (progn (setq pattern (vl-princ-to-string str)) (while (wcmatch pattern "*#") (setq pattern (substr pattern 1 (1- (strlen pattern)))) ) (cons str (list (cons (strcase pattern) (substr (vl-princ-to-string str) (1+ (strlen pattern)))))) ) ) ) lst ) ) En revanche j'aime beaucoup la possibilité d'appliquer une fonction au choix pour se permettre d'avoir un spectre plus large sur son utilisation ! Après pour la prise en compte des majuscules ou non je trouve cela étrange de trier et d'avoir les "a" après les "P" par exemple donc c'est pour cela que je me le suis imposé. (setq lst '("Calque10" "Bloc" 8 "Calque1" "calque3" "Bloc5" 4 88 "90" "Bloc30" "Calque7")) ("Calque10" "Bloc" 8 "Calque1" "calque3" "Bloc5" 4 88 "90" "Bloc30" "Calque7") (get-pattern-list lst) (("Calque10" ("CALQUE" . "10")) ("Bloc" ("BLOC" . "")) (8 ("" . "8")) ("Calque1" ("CALQUE" . "1")) ("calque3" ("CALQUE" . "3")) ("Bloc5" ("BLOC" . "5")) (4 ("" . "4")) (88 ("" . "88")) ("90" ("" . "90")) ("Bloc30" ("BLOC" . "30")) ("Calque7" ("CALQUE" . "7"))) (sort-list lst 0) (4 8 88 "90" "Bloc" "Bloc5" "Bloc30" "Calque1" "calque3" "Calque7" "Calque10") (sort-list lst 1) ("Calque10" "Calque7" "calque3" "Calque1" "Bloc30" "Bloc5" "Bloc" "90" 88 8 4) En tout cas merci beaucoup, cela m'a été très formateur, notamment sur l'utilisation réelle de (lambda). J'avais encore du mal à la voir comme une fonction (defun) non nommée..^^" Bisous, Luna
-
Bon du coup, comme prévu, les limites ont été très rapides à trouver car si l'on prend des listes de nombres cela ne fonctionne plus (pour les deux fonctions) mais de toutes façons je ne devrais pas avoir uniquement des nombres au sein de mes chaînes de caractères donc ça devrait le faire ^^" Je me suis permise de modifier légèrement ton code pour faire correspondre le même résultat (il semblerait que les deux méthodes possèdent des limites identiques donc il suffit juste de contrôler la liste en entrée pour éviter d'arriver à une erreur !) (defun sort-list (lst flag) (mapcar '(lambda (i) (nth i lst)) (vl-sort-i (mapcar '(lambda (s / m) (if (setq m (RegExpExecute s "(^.+\\D)(\\d+$)" nil nil)) (caddar m) (list s s) ) ) (mapcar 'vl-princ-to-string lst) ) '(lambda (a B) (if (= (strcase (car a)) (strcase (car B))) ((cond (flag <) ((null flag) >)) (atoi (cadr a)) (atoi (cadr B))) ((cond (flag <) ((null flag) >)) (strcase (car a)) (strcase (car B))) ) ) ) ) ) Donc merci encore !! Je ne pensais pas que mon problème serait réglé aussi vite donc c'est super, comme toujours ! Bisous, Luna
-
Oh well... Tes connaissances sont sans limites !!! J'étais arrivé à un résultat concluant (du moins uniquement pour la liste donnée en exemple, je n'ai pas vraiment eu le temps de la tester encore vraiment...) avec ceci pour ma part : (setq lst '("P_1" "PT_5" "P_4" "P_10" "PT3" "TCPOINT_89" "P_89" "p_2" "Calque1" "Test" "Calque2" "00-Calque3" "00-Calque30" "00-Calque4" "02-Calque6" "P_1000" "PT25" "TCPOINT_889")) (defun Sort-list (lst flag / pattern-list sort sort-lst) (setq sort '() pattern-list (get-pattern lst) ) (foreach pattern (cond ((null flag) (reverse pattern-list)) (flag pattern-list)) (setq sort-lst (vl-remove-if-not '(lambda (x) (wcmatch (strcase x) (strcase (strcat pattern "#*," pattern)))) lst) sort-lst (mapcar '(lambda (i) (nth i sort-lst)) (vl-sort-i (mapcar '(lambda (x) (atoi (substr x (1+ (strlen pattern))))) sort-lst ) (cond ((null flag) '>) (flag '<)) ) ) ) (setq sort (append sort sort-lst)) ) sort ) (defun get-pattern (lst / str pattern-list) (setq lst (mapcar 'vl-princ-to-string lst)) (while lst (setq str (strcase (car lst))) (while (wcmatch str "*#") (setq str (substr str 1 (1- (strlen str)))) ) (setq pattern-list (cons str pattern-list) lst (vl-remove-if '(lambda (x) (wcmatch (strcase x) (strcase (strcat str "*")))) lst) ) ) (if pattern-list (setq pattern-list (vl-sort pattern-list '(lambda (e1 e2) (< (strcase e1) (strcase e2))))) (princ) ) ) ;;--- (Sort-list lst flag) Renvoie ainsi : ;;--- flag = t -> ("00-Calque3" "00-Calque4" "00-Calque30" "02-Calque6" "Calque1" "Calque2" "PT3" "PT25" "PT_5" "P_1" "p_2" "P_4" "P_10" "P_89" "P_1000" "TCPOINT_89" "TCPOINT_889" "Test") ;;--- flag = nil -> ("Test" "TCPOINT_889" "TCPOINT_89" "P_1000" "P_89" "P_10" "P_4" "p_2" "P_1" "PT_5" "PT25" "PT3" "Calque2" "Calque1" "02-Calque6" "00-Calque30" "00-Calque4" "00-Calque3") Mais comme je l'ai dit, je ne l'ai pas vraiment poussée dans ses retranchements (des listes de 500 atomes, voire plus) donc il m'est difficile de savoir jusqu'où elle fonctionne vraiment... Ce qui est sûr, ce que comparé à ton code (bien trop propre à mes yeux !!! <3), j'ai encore du boulot avant de d'optimiser au mieux mes fonctions (et éviter de lancer 150 boucles avec des (while), (foreach) et (mapcar) imbriqués !! ce qui ralenti l'exécution) En tout encore merci !! Et puis je ne connaissais pas non plus tes fonctions régulières, je regarderais tout ça plus en détail car cela risque de mettre très utile et une source d'inspiration ! Bisous, Luna
-
Merci (gile) ! J'avais déjà exploré cette solution mais elle fonctionne uniquement sur des cas particuliers (ici l'argument "Start" de (substr) est défini en dur à 3)... Mon but est un peu..chiant je l'avoue, mais ce n'est que de la lecture de données, donc je ne peux pas vraiment savoir à quelle genre de données je dois m'attendre... D'où la complexité de ma demande ^^' En revanche je dois avoir moyen de récupérer un système de pattern sous forme de liste si je prend comme hypothèse qu'un pattern est défini par une chaîne de caractères dont j'exclue les valeurs numériques en fin de chaîne uniquement, par exemple : Cela devrait être possible via (wcmatch) je pense, et ensuite trier cette liste de pattern pour pouvoir créer des sublist avec l'ensemble des valeurs ayant un pattern commun et ensuite, lui appliquer ta solution via un (substr) et (strlen) du pattern pour trier les valeurs numériques au sein des sous-listes... Un petit coup de (append) des sublists et le tour est joué ! Bon bah, je vais commencer à potasser tout ça pour voir ce que ça me donne mais au moins j'ai une piste !! Arigato !
