Aller au contenu

Luna

Membres
  • Compteur de contenus

    1 113
  • Inscription

  • Dernière visite

  • Jours gagnés

    42

Tout ce qui a été posté par Luna

  1. Coucou, J'avais déjà une fonction en stock pour chat 🙂 ; []-----------------------[] Wildcard-trim []-----------------------[] ; ;--- Date of creation > 10/12/2021 ; ;--- Last modification date > 10/12/2021 ; ;--- Author > Luna ; ;--- Version > 1.0.0 ; ;--- Class > "BaStr" ; ;--- Goal and utility of the main function ; ; When used for functions (vl-string-*-trim), lists all the characters corresponding to the specified pattern in the form of a list from the 256 ; ; characters present in the ASCII table. ; ; ; ;--- Declaration of the arguments ; ; The function (Wildcard-trim) have 1 argument(s) : ; ; --• w > correspond to the pattern that each character needs to match ; ; (type w) = 'STR | Ex. : "#", "@", "~#", ".,#", ... ; ; ; ;--- Return ; ; The function (Wildcard-trim) returns a list of characters (1 single character per string) whose characteristics correspond to the wildcard ; ; specified in argument (see wcmatch for the Wild-Card Characters). ; ; Ex. : (Wildcard-trim "#") returns ("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "²" "³" "¹") ; ; (Wildcard-trim "@") returns ("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" ; ; "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" ; ; "ƒ" "Š" "Œ" "Ž" "š" "œ" "ž" "Ÿ" "ª" "µ" "º" "À" "Á" "Â" "Ã" "Ä" "Å" "Æ" "Ç" "È" "É" "Ê" "Ë" "Ì" "Í" "Î" ; ; "Ï" "Ð" "Ñ" "Ò" "Ó" "Ô" "Õ" "Ö" "Ø" "Ù" "Ú" "Û" "Ü" "Ý" "Þ" "ß" "à" "á" "â" "ã" "ä" "å" "æ" "ç" "è" "é" ; ; "ê" "ë" "ì" "í" "î" "ï" "ð" "ñ" "ò" "ó" "ô" "õ" "ö" "ø" "ù" "ú" "û" "ü" "ý" "þ" "ÿ") ; ; ; ;--- Historic list of the version with their modification status ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; | v1.0.0 | Creation of the function | ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; ; (defun wildcard-trim (w / i lst a) (repeat (setq i 256) (if (wcmatch (setq a (chr (setq i (1- i)))) w) (setq lst (cons a lst)) ) ) lst ) Du coup pour répondre au challenge, je donnerai cette version : (vl-string-trim (apply 'strcat (wildcard-trim "~#")) str) Évidemment, avec la fonction (vl-string-trim) cela permet uniquement de supprimer les caractères en partant de la gauche et de la droite, jusqu'à ce qu'un caractère autorisé soit trouvé. Autrement dit, pour une chaîne de caractère telle que (setq str "ma80cm") ;; ou (setq str "Surface = 42.23m (+NGF)") ;; etc... On obtient respectivement les résultats : "80" ;; ou "42.23" Mais comme le souligne @bonuscad, dans le cas d'un nombre négatif, le moins est supprimé donc il y a une perte d'information dans ce cas-ci. Autre limite : dans le cas où il y a deux valeurs numériques dans une même chaîne de caractères, comme par exemple (setq str "Value = -543.1530054 (equals to 2u)") (vl-string-trim (apply 'strcat (wildcard-trim "~#")) str) returns "543.1530054 (equals to 2" Bref, cela réponds à un problème simple dans les conditions établies, mais cela possède ses propres limites tout de même si l'on étend son utilisation en dehors des conditions actuelles. Par contre, les nombres décimaux sont conservés correctement 😉 Bisous, Luna
  2. Denis, Pour être honnête, je ne maîtrise pas du tout le langage binaire, j'avais juste eut 1 petite heure de cours dessus pour le principe mais c'est tout. Après je me suis simplement penchée sur la compréhension de l'écriture binaire justement à cause du LISP et parce que je refuse d'utiliser une fonction si je ne comprends pas comment et/ou pourquoi elle fonctionne. Donc lorsque j'ai du comprendre les fonctions de LeeMac sur la conversion des couleurs (cf. >>ici<<), j'ai été un forcée de comprendre les fonctions (lsh) pour les left shift et right shift. Puis j'ai trouvé chat intéressant donc j'ai essayé de mieux comprendre les changements de base (de base 10 en base 2 et/ou 16 notamment). Bref, ce n'est pas par simplicité de compréhension que je m'y suis intéressée mais juste parce qu'en LISP je devait passer par là donc j'ai essayé d'apprendre. Et pour le coup, ce post est très intéressant, même si je n'en comprend qu'une infime partie et que je n'ai pas encore acquis la logique automatique 🙂 Tout chat pour dire que c'est pas une histoire d'âge, juste de tempérament je suppose 😉 (et de temps pour étudier le sujet !) Bisous, Luna
  3. Coucou, Ce n'est que récemment que je me suis confronté à la programmation french/english et je n'ai pas trouvé mieux que développer la fonction (LgT), en PJ. (defun LgT (en fr flag) (cond ((= flag 1) en) ((= flag 2) fr) (T (LgT en fr (if (= (getvar "LOCALE") "FR") 2 1))) ) ) Du coup désormais lorsque j'écris mes programmes, j'écris la version anglaise et la version française des textes et selon la valeur du 'flag', la commande fonctionne en anglais ou en français. Autrement, concernant les fichiers DCL je te conseille de ne jamais écrire directement de fichier DCL (justement en raison du fait que l'on ne peut pas jouer sur certains paramètres. Perso, je créer toujours des fichiers DCL via (vl-filename-mktemp) et (open ... "W"). Du coup je créé le fichier DCL directement depuis un programme LISP et donc on peut y affecter des variables ou modifier sa structure plus facilement. Mais en effet lorsqu'il faut qu'un programme fonctionne avec plusieurs langages, il faut travailler plusieurs fois pour écrire en dur les différentes traductions ! J'avais également essayé de voir avec la fonction (showhtmlmodalwindow) mais je n'arrive pas à ouvrir une page web, intervenir sur cette page et la refermer, le tout de manière transparente... Le mieux que j'ai pu faire c'est le programme OpenDeepL : (defun c:OpenDeepL (/ URLencode AutoCAD-string _GetClipBoardText mode name str) (defun URLencode (URL / dec->hex f xpt) (defun dec->hex (n) (cond ( (< 15 n) (strcat (dec->hex (lsh n -4)) (dec->hex (rem n 16))) ) ( (< n 10) (itoa n) ) (T (chr (+ n 55)) ) ) ) (defun f (l / d) (if l (strcat (cond ( (or (< 47 (car l) 58) ; [0-9] (< 64 (car l) 91) ; [A-Z] (< 96 (car l) 123) ; [a-z] (member (car l) xpt) ; non-encoded special characters ) (chr (car l)) ) ( (< (car l) 128) (strcat "%" (if (= 1 (strlen (setq d (dec->hex (car l))))) (strcat "0" d) d)) ) ( (< (car l) 192) (strcat "%C2%" (if (= 1 (strlen (setq d (dec->hex (car l))))) (strcat "0" d) d)) ) ( (< (car l) 256) (strcat "%C3%" (if (= 1 (strlen (setq d (dec->hex (- (car l) 64))))) (strcat "0" d) d)) ) ) (f (cdr l)) ) "" ) ) (setq xpt (vl-string->list "-_.!~*'()") ; JScript ;;(vl-string->list "-._~") ; the Internet Society ;;(vl-string->list "-_.!*()") ; .NET ) (f (vl-string->list URL)) ) (defun AutoCAD-string (str new old / len pos) (setq len (- (strlen (vl-prin1-to-string old)) 2)) (while (setq pos (vl-string-search old str)) (setq str (strcat (substr str 1 pos) new (substr str (+ pos len)) ) ) ) str ) (defun _GetClipBoardText( / h r) (setq r (vlax-invoke (vlax-get (vlax-get (setq h (vlax-create-object "htmlfile")) 'ParentWindow ) 'ClipBoardData ) 'GetData "Text" ) ) (vlax-release-object h) r ) (initget "ObjectSelection Text") (cond ( (= "Text" (setq mode (getkword "\nSpecifie what you want to translate [ObjectSelection/Text] <ObjectSelection> : "))) (setq str (getstring T "\nEnter the text : ")) ) ( (null (while (not (and (setq name (nentsel "\nSelect an object with a text : ")) (setq name (car name)) (assoc 1 (entget name)) (wcmatch (cdr (assoc 1 (entget name))) "*") ) ) ) ) (setq mode "ObjectSelection" str (cdr (assoc 1 (entget name))) ) ) ) (showhtmlmodalwindow (strcat "https://www.deepl.com/translator#fr/en/" (progn (setq str (ACAD-string str "\n" "\\P")) (URLencode str) ) ) ) (if name (entmod (subst (cons 1 (_GetClipBoardText)) (assoc 1 (entget name)) (entget name))) ) (princ) ) Le principe permet de traduire des textes sans mise en forme complexe en ouvrant une page DeepL, l'utilisateur doit ensuite copier le texte traduit dans le presse-papier et fermer la fenêtre pour que le texte soit traduit "approximativement" automatiquement (à partir du presse-papier du moins). Bisous, Luna UtWin . LgT.lsp
  4. Serait-il possible d'avoir un .dwg d'exemple de ce que tu peux avoir, pour voir ce qu'il est possible de faire ? Je n'ai pas d'AutoCAD Electrical cependant, mais je suppose que le soucis que tu soulèves est un problème AutoCAD basique et pas typique d'Electrical 😉 Bisous, Luna
  5. Coucou, La réponse à ta question est non, que le bloc parent soit dynamique ou non. Je n'ai pas non plus l'impression que la sélection de sous-objets (maintenir la touche CTRL enfoncée lors de la sélection des objets) fonctionne car elle refuse de sélectionner les blocs contenus dans un autre bloc. Ma question est cependant la suivante : Dans ton bloc parent, tu as X blocs enfants, n'est-ce pas ? A quel point tes blocs enfants sont-ils différents entre-eux ? Autrement dit, es-tu obligé que tes blocs enfants soient des blocs au lieu de simples objets ? Combien de références de blocs enfants possèdes-tu ? (les blocs enfants sont-ils uniquement utilisés dans une seule définition de bloc parent ou bien plusieurs ou bien sont-ils également présents dans ton .dwg ?) Les attributs de tes blocs enfants sont-ils les mêmes entre plusieurs blocs enfants ou bien sont-ils tous différents ? En clair, la réponse à ta question est non, mais si tu changes ta manière de faire, on pourra sûrement trouver une solution qui te convient. Bisous, Luna
  6. Luna

    Onglet qui a disparu

    Coucou, Question bête mais...ne faut-il pas enregistrer l'espace de travail courant une fois le fichier de personnalisation partiel chargé ? Peut-être qu'AutoCAD considère simplement le chargement de ces fichiers comme un paramètre enregistré dans l'espace de travail...? Évidemment je ne suis sûre de rien, hein, j'ai un peu du mal avec les fichiers de personnalisation partiel ^^" Bisous, Luna
  7. Ya le bloc note ou Word. xD Nan sérieusement il n'y a pas besoin d'un logiciel ou d'une formation en particulier pour apprendre. Le plus simple c'est de s'entraîner à chaque fois que tu écris. Alors vui au début tu feras plein de fautes et tu ne trouveras pas naturellement les touches du clavier mais chat viendra au fil du temps. C'est juste une histoire de mémoire musculaire après donc tu ne réfléchis presque plus et tu te contente de lire ce que tu écris 😉 Bisous, Luna
  8. Coucou, Chat me rappelle un truc : Bisous, Luna
  9. Ah bon bah parfait dans ce cas @ssalle et @stefD ! C'est en effet un peu plus clair avec les bonnes explications 😉 Du coup s'il y a éventuellement besoin de modifier la valeur par défaut, il n'y a pas de soucis, il suffit de demander ce que vous souhaiteriez. Actuellement la nouvelle valeur spécifiée est une variable globale et est utilisée comme valeur par défaut pour la fois suivante (dans le cas où l'on a modifié une chaîne mais finalement on s'est trompé, on peut reprendre la nouvelle sans devoir la retaper). Bisous, Luna
  10. La solution pourrait éventuelle être de se relire avant de publier le message xD Ou sinon de changer de doigts pour s'entraîner à écrire "pas" et non "aps" ^^ Bisous, Luna
  11. @stefD, Comment cela peut-il solutionner ton problème ?! Mon programme permet uniquement de remplacer les chaînes de caractères similaires, par une autre chaîne de caractères unique (donc commune à tout le monde !). Or toi tu veux remplacer les chaînes de caractères similaires, par différentes chaînes de caractères pour chaque calque. Personnellement je ne vois pas vraiment comment faire cela en programmation car le programme ne peux pas prendre une décision à ta place. D'autant plus que je ne vois pas comment tu peux avoir plusieurs calques portant strictement le même nom pour le moment... Donc essaye plutôt de regarder du côté du convertisseur de calques comme je disais précédemment car c'est un travail qui nécessite une intervention utilisateur pour chaque référence de calque. Pourquoi avoir créé une chaîne de caractère commune si tu savais que tu devrais les remplacer par des chaînes de caractères différentes ? J'ai du mal à comprendre la démarche.. Bisous, Luna
  12. Coucou, Le but est-il de remplacer une même chaîne de caractères présente dans tous les calques par une nouvelle et même chaîne de caractères ? Si c'est le cas, alors essaye ceci : (defun c:RNL (/ vla-collection->list layer pattern) (defun vla-collection->list (doc col flag / lst item i) (if (null (vl-catch-all-error-p (setq i 0 col (vl-catch-all-apply 'vlax-get (list (if doc doc (vla-get-activedocument (vlax-get-acad-object))) col))))) (vlax-for item col (setq lst (cons (cons (if (vlax-property-available-p item 'Name) (vla-get-name item) (strcat "Unnamed_" (itoa (setq i (1+ i)))) ) (cond ((= flag 0) (vlax-vla-object->ename item) ) (t item ) ) ) lst ) ) ) ) (reverse lst) ) (if $str$ (if (= "" (setq pattern (getstring T (strcat "\nSpécifier la chaîne à remplacer <" $str$ "> : ")))) (setq pattern $str$) ) (setq pattern (getstring T "\nSpécifier la chaîne à remplacer : ")) ) (setq $str$ (getstring T "\nSpécifier la chaîne de remplacement : ")) (mapcar '(lambda (x / layer name) (setq layer (cdr x) name (car x) ) (if (wcmatch name (strcat "*" pattern "*")) (entmod (subst (cons 2 (vl-string-subst $str$ pattern name)) (assoc 2 (entget layer)) (entget layer))) ) ) (vla-collection->list nil 'layers 0) ) (princ) ) Sinon, alors c'est plus complexe et il faudrait peut-être regarder du côté du Convertisseur de calques ? (Outils > Normes CAO > Convertisseur de calques) Bisous, Luna
  13. Coucou, F8 est actuellement grisée parce que tu n'as pas défini de point d'arrêt dans le programme. Il s'agit du bouton en forme de main (à gauche de la paire de lunettes). Je te conseille de placer le point de coupure au niveau de la parenthèse ouvrante de la fonction (vl-vbaload) et d'ajouter "Consulter dernière interprétation" dans la fenêtre espion. Ainsi en lançant la commande GAZ tu verras ce qui ne fonctionne pas avec F8. En regardant l'aide AutoCAD concernant la fonction (vl-vbaload), elle est supposée retourner le chemin du fichier .dvb normalement. Or cela ne semble pas être le cas d'après ta première capture.. Es-tu sûr que ton fichier a pu être trouvé ? Essaye de taper la ligne suivante dans la ligne AutoCAD et voir ce qu'elle retourne : (findfile "C:\\K2M\\ACAD\\GAZ.dvb") Bisous, Luna
  14. Luna

    fichier verrouillé?

    Coucou, Normalement cela signifie que tu es en lecture seule, donc si tu fais "ENREGISTRER", AutoCAD va refuser et demandera de faire "ENREGISTRER SOUS" ou "QUITTER SANS ENREGISTRER". En effet, cela arrive en fonction de l'emplacement du fichier. Perso, on utilise une GED qui demande à l'ouverture si l'on souhaite ouvrir pour modification ou en lecture seule donc j'ai très souvent affaire à ce cadenas 😉 Bisous, Luna
  15. Coucou, Pour ton 4 qui sort à la fin c'est normal, il faut juste que tu mettes ton (princ) avant de clore ton (defun), comme ci-dessous, car sinon ton programme renvoie la valeur de 'OLDAUPREC' : );defun (princ) ;; Remplace le par : (princ) );defun Désolée, pour le moment je n'ai pas vraiment de temps pour travailler sur ma fonction (princ-a-list-properties) mais je ne l'ai pas oubliée ! Je suis incapable de laisser une question en suspend comme chat, c'est bien trop frustrant donc cela me prendra le temps qu'il faudra pour sortir une version clean et pouvoir ainsi avoir une liste de fonctions connexes pour pouvoir générer un quantitatif d'objets selon un ordre précis de propriétés. (donc cela devrait solutionner plusieurs problèmes à la fois, espérons-le !) Évidemment le plus dur sera de comprendre l'étendu d'utilisation des fonctions xD Bisous, Luna
  16. Luna

    Aide code VBA

    Coucou, Le problème est récurrent et tu trouveras un nombre incalculable de sujets qui traite de ce soucis ! Un bloc dynamique possède un nom du style "*U146" alors que la définition de bloc est "Test" par exemple. Pour cela il faut utiliser la fonction 'EffectiveName (en VBA je n'ai pas idée de comment tu l'écris) lorsque tu veux comparer le nom de ton bloc avec le filtre. Il faut également penser à ajouter le pattern "`*U*" dans le filtre de sélection si jamais tu as défini un filtre sur le code DXF 2 ! Edit: (gile) est plus efficace et concis, j'ai encore du travail sur la simplification et la clarté des explications 🙂 Bisous, Luna
  17. Luna

    Nouveau Site Perso

    @(gile), Pour le coup, j'ai tendance à tirer parti du meilleur des deux mondes (même si c'est pas le plus efficient, c'est pas si mal) : J'utilise VS Code pour écrire mes programmes avec toutes les fonctionnalités d'écriture de VS Code et lorsque je veux tester son fonctionnement, je fais un copier/coller du code en question dans l'IDE d'AutoCAD, je mes les variables/expressions que je souhaite dans la fenêtre espion et je fais mon debugging via l'IDE AutoCAD. Et si je dois faire une modification, soit elle est infime et je corrige directement sous l'IDE pour tester (si chat marche je répercute la correction sur VS Code) sinon je reprends VS Code et je re-copie/colle le programme corrigé sur l'IDE. Cela fonctionne plutôt bien en soit, même si je me doute bien que ce n'est pas vraiment le plus optimisé.. PS: j'ai lu tes explications @didier sur le debugging via VS Code, je testerais cela la prochaine fois. Personnellement, ce que j'apprécie le plus dans VS Code c'est la personnalisation des couleurs via les thèmes (l'écran blanc de VLIDE me détruit les yeux si je l'utilise un peu trop longtemps), l'intellisense que l'on peut personnaliser me semble-t-il (il faudrait que je creuse un peu mais si certaines fonctions persos sont très souvent utilisées, on peut les ajouter à la listes des fonctions détectées par VS Code) et les multi-curseurs (ALT+Clic gauche pour les placer à des endroits spécifiques, sélection d'une chaîne de caractères puis clic droit > "Change all occurrences" ou clic molette pour en placer un à chaque ligne suivant la position du curseur de la souris). La mip-map peut également être utile et les mini-repères sur la barre de défilement qui permettent de dire où se situe chaque occurrence de la chaîne de caractères sélectionnée. Bisous, Luna
  18. Luna

    Nouveau Site Perso

    Coucou didier, Pour commencer, encore un grand merci pour tout le temps que tu passes à confectionner ce site qui nous sert au quotidien ! C'est d'ores et déjà une référence francophone et il y a de quoi en être fier :3 Concernant VS Code, je trouve qu'il s'agit d'un outil extrêmement puissant et bien que je ne le maîtrise pas encore complètement (notamment le debugging et la conversion UTF-8 / ASCII sur AutoCAD), cela fait déjà plusieurs mois que je code uniquement sur VS Code. Ne serait-ce que pour la modification des multiples des occurrences et l'utilisation de curseurs multiples ! Bref c'est un outil que j'affectionne et qui se prête parfaitement au métier de développeur donc je trouve cela génial qu'il y ait enfin une reconnaissance du langage AutoLISP par ce logiciel. Je vais de ce pas consulter ton site afin de mieux comprendre les parties que je ne maîtrise pas encore afin de pouvoir utiliser tout le potentiel de cet outil. Bisous, Luna
  19. Coucou, Bon j'obtiens un résultat mais certainement pas celui que je désire... Ci-dessous les fonctions (make-a-list-properties) et (loop-a-list-properties) qui sont fonctionnelles (du moins elles ne me font pas défaut dans les limites d'utilisation que j'ai testé) : ; []-----------------------[] make-a-list-properties []-----------------------[] ; ;--- Date of creation > 06/01/2022 ; ;--- Last modification date > 06/01/2022 ; ;--- Author > Luna ; ;--- Version > 1.0.0 ; ;--- Class > "BaLst" ; ;--- Goal and utility of the main function ; ; When used in a loop function and by defining the 'lst' variable with the result of this function, it creates an association list with different ; ; levels. The main idea is to set value (like a counter, the object's length, etc.) and creates a new list of keys if not existant or applies a ; ; function (like '+, '-, 'strcat) between the old and the new value with the same list of keys. For that, it will considered for each key a new ; ; level of association list. In fine, each similar objects by the value of their properties name, will be match together. ; ; ; ;--- Declaration of the arguments ; ; The function (make-a-list-properties) have 4 argument(s) : ; ; --• lst > corresponds to the existing list you want to build withing a loop. The common use will be, for example, see below ; ; (setq lst (make-a-list-properties lst ...)) ; ; (type lst) = 'LST | Ex. : a variable name to build the list within a loop ; ; --• k-lst > corresponds to the list of property value that will be used to determine the number of level of association list. ; ; Each property value will be used as the key for each association list. ; ; (type k-lst) = 'LST | Ex. : '("Layer1" "LWPOLYLINE"), '("BlockName2" "63,115,69" "23.42"), '("Layer0"), ... ; ; --• value > corresponds to the new value for the list of keys. If the 'lst' already contain a value for that list of keys, it ; ; will be add to the old one (depending of 'fun' value), otherwise it will be add to the list with the list of keys ; ; (type value) = '... | Ex. : 1 (to count the entity units), (getpropertyvalue name "LENGTH"), "63,115,69", ... ; ; --• fun > corresponds to the function that will be used to connect the old value with the new one. The most common value of ; ; 'fun' is '+, to add the new value with the old one ; ; (type fun) = 'SYM | Ex. : '+, '-, 'strcat, ... ; ; ; ;--- Return ; ; The function (make-a-list-properties) returns the new value of the list, with the new value substitute to the old one if existing, or add it to ; ; the list. ; ; Ex. : (make-a-list-properties lst (list Layer ObjectName) 1 '+) returns after the loop from a selection set ; ; ( ("Layer1" ("LWPOLYLINE" . 13) ("CIRCLE" . 4) ("INSERT" . 1)) ; ; ("Layer3" ("CIRCLE" . 1) ("LINE" . 14) ("LWPOLYLINE" . 42)) ; ; ("Layer2" ("INSERT" . 69)) ; ; ("Layer9" ("LINE" . 3) ("ARC" . 11)) ; ; ) ; ; ; ;--- Historic list of the version with their modification status ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; | v1.0.0 | Creation of the function | ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; ; (defun make-a-list-properties (lst k-lst value fun / key search) (if (null (cdr k-lst)) (if (setq search (assoc (setq key (car k-lst)) lst)) (subst (cons key (apply fun (list (cdr search) value))) search lst) (append lst (list (cons key value))) ) (if (setq search (assoc (setq key (car k-lst)) lst)) (subst (cons key (make-a-list-properties (cdr search) (cdr k-lst) value fun)) search lst) (append lst (list (cons key (make-a-list-properties (cdr search) (cdr k-lst) value fun)))) ) ) ) ; []-----------------------[] loop-a-list-properties []-----------------------[] ; ;--- Date of creation > 07/01/2022 ; ;--- Last modification date > 07/01/2022 ; ;--- Author > Luna ; ;--- Version > 1.0.0 ; ;--- Class > "BaLst" ; ;--- Goal and utility of the main function ; ; To facilitate the automatic creation of a list of associations of different levels via (make-a-list-properties) from a selection set. ; ; ; ;--- Declaration of the arguments ; ; The function (loop-a-list-properties) have 4 argument(s) : ; ; --• jsel > is the selection set used to create the (make-a-list-properties) ; ; (type jsel) = 'PICKSET | Ex. : (ssget), ... ; ; --• PropertyList > corresponds to the list of property name that will be used to determine the number of level of association list. ; ; Each property name will inquire the property value of the objects with (GetAnyProperty) function ; ; (type PropertyList) = 'LST | Ex. : '(8 'ObjectName "COLOR"), '("LineTypeScale" 0), ... ; ; --• value > corresponds to the new value for the list of keys. If the 'lst' already contain a value for that list of keys, it ; ; will be add to the old one (depending of 'fun' value), otherwise it will be add to the list with the list of keys ; ; (type value) = '... | Ex. : 1 (to count the entity units), (quote (getpropertyvalue name "LENGTH")), ... ; ; --• fun > corresponds to the function that will be used to connect the old value with the new one. The most common value of ; ; 'fun' is '+, to add the new value with the old one ; ; (type fun) = 'SYM | Ex. : '+, '-, 'strcat, ... ; ; ; ;--- List of dependent's functions ; ; --• "BaLst" ---> make-a-list-properties | v1.0.0 - 06/01/2022 (Luna) ; ; --• "DtObj" ---> GetAnyProperty | v1.0.0 - 30/12/2021 (Luna) ; ; ; ;--- Return ; ; The function (loop-a-list-properties) returns the association list after the loop for each object in the selection set. ; ; Ex. : (loop-a-list-properties (ssget) (list 8 0) 1 '+) returns ; ; ( ("Layer1" ("LWPOLYLINE" . 13) ("CIRCLE" . 4) ("INSERT" . 1)) ; ; ("Layer3" ("CIRCLE" . 1) ("LINE" . 14) ("LWPOLYLINE" . 42)) ; ; ("Layer2" ("INSERT" . 69)) ; ; ("Layer9" ("LINE" . 3) ("ARC" . 11)) ; ; ) ; ; ; ;--- Historic list of the version with their modification status ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; | v1.0.0 | Creation of the function | ; ; +------------+----------------------------------------------------------------------------------------------------------------------------------+ ; ; ; (defun loop-a-list-properties (jsel PropertyList value fun / i name lst) (if jsel (repeat (setq i (sslength jsel)) (setq name (ssname jsel (setq i (1- i))) lst (make-a-list-properties lst (mapcar '(lambda (pp / ppType) (setq ppType (type pp)) (cdr (GetAnyProperty name "*" (cond ((= ppType 'INT) 0) ((= ppType 'STR) 1) ((= ppType 'SYM) 2)) pp ) ) ) PropertyList ) (eval value) fun ) ) ) ) ) Par contre ma maîtrise des fonctions récurrente ne me permet pas de d'imprimer sur la même ligne les propriétés amonts avec la somme des propriétés avals... Ci-dessous la version semi-fonctionnelle (le total n'est pas imprimé sur la ligne désirée...mais chat marche...à moitié) : (defun princ-a-list-properties (lst msg p-lst fun / r p s u c) (setq r (car p-lst) p (car r) s (cadr r) u (caddr r) c (cadddr r) ) (if msg (princ msg)) (mapcar '(lambda (l / k v) (setq k (car l) v (cdr l) ) (princ (strcat (cond (p) ("")) (vl-princ-to-string k) (cond (s) ("")) ) ) (princ (strcat (vl-princ-to-string (if (null (cdr p-lst)) v (setq v (apply c (princ-a-list-properties v nil (cdr p-lst) fun))) ) ) (cond (u) ("")) ) ) v ) (if fun (vl-sort lst '(lambda (kp1 kp2) ((eval fun) (car kp1) (car kp2)))) lst ) ) ) Le soucis c'est que je (princ) au fur et à mesure que le programme avance donc au final, les sommes cumulées ne seront imprimées qu'à la toute fin... Ci-dessous la commande SCP qui consiste uniquement à laisser l'utilisateur définir ses filtres comme il le souhaite (donc le premier (setq ...) est un exemple d'utilisation parmi tant d'autres) : (defun c:SCP (/ m-lst value msg fun v-fun filter) (setq m-lst (list (cons 8 (list "\nLayer name : \"" "\" :" "u" '+)) (cons 'ObjectName (list "\n - ObjectName <" "> :" nil '+)) (cons "COLOR" (list "\n > Color " " : " "u" '+)) ) value 1 msg "" fun '+ v-fun '< filter (list '((0 . "*POLYLINE,LINE,ARC,CIRCLE"))) ) (setq lst (loop-a-list-properties (apply 'ssget filter) (mapcar 'car m-lst) value fun)) (princ-a-list-properties lst msg (mapcar 'cdr m-lst) v-fun ) (princ) ) Le problème du retour ci-dessous : For layer "0" : - ObjectName <AcDbPolyline> : > Color 2 : 1u > Color 256 : 1u > Color 62,193,123 : 1u > Color DIC COLOR GUIDE(R),DIC 634 : 1u44u Le "44u" situé à la toute fin est en réalité "4" qui doit être affiché comme le total de <AcDbPolyline> et "4u" qui doit être affiché comme le total de 'For layer "0" :'. Donc j'ai essayé de prendre le problème à l'envers : utiliser la fonction (princ-a-list-properties) pour regrouper tout le beau monde sous forme de liste de chaînes de caractères et imprimer le résultat avec (princ (apply 'strcat (princ-a-list-properties))) mais pour le moment je commence à me perdre dans la logique des récurrences de fonctions pour construire une liste cohérente (et surtout réussir à conserver ce fichu total à chaque remontée !!!!). Bref j'en ai pas encore terminé mais je ne compte pas abandonner xD Au moins le fonctionnement de SCP me semble relativement simple (une fois qu'il y aura des commentaires chat le sera encore plus !) pour quiconque fait un peu d'AutoLISP. Bisous, Luna
  20. En effet, seul les couleurs sont définies par les codes 62, 420 et 430 mais cela ne pose pas vraiment soucis car le sujet se posera en amont de la fonction d'association. Donc il faudra simplement que je définisse une liste qui puisse prendre en compte ce genre de subtilité pour prendre la valeur du code 430 si existant, sinon 420 si existant puis 62 si existant sinon "DuCalque". Mais chat devrait pouvoir se faire via une liste (apply) sur un (lambda) pour le choix des valeurs de clés. Avec la fonction (GetAnyProperty), cela me permettra de fonctionner aussi bien avec les propriétés DXF, ActiveX ou Visual normalement. Bref, je vais décortiquer un peu tout chat ce we en espérant d'avoir une solution clean et je reviendrais vers vous si tout se passe bien ! Cela me permettra de travailler un peu les fonctions récurrentes qui plus est donc c'est tout bénef' pour moi 🙂 Bisous, Luna
  21. Luna

    Halte au SPAM

    Coucou didier, En effet j'ai également une très forte latence (certains messages arrivent également en double sûrement provoqué par l'impatience de l'expéditeur 🙂 ) ! Cependant j'ai remarqué qu'au lieu d'attendre 5min pour que le message soit posté, il suffisait de rafraîchir la page pour que le message soit posté direct. Par contre l'éditeur de texte conserve en mémoire le message qu'on vient d'envoyer mais il suffit de faire CTRL+A, SUPPR et le tour est joué. Affaire à suivre en tous cas, mais je suppose qu'il y a justement eut des modifications pour contrer les spams qui ont créé ces problèmes de latence. Bisous, Luna
  22. Coucou @lecrabe, Etrangement j'ai senti venir une adaptation de la commande 😉 Du coup j'essaye d'adapter le fonctionnement de (make-list) pour pouvoir gérer n niveaux d'association et pouvoir adapter la commande à autant de propriétés que l'on souhaite dans l'ordre qu'on veut (une commande gérée par une liste principale, cf. >>ce sujet<< en clair). Pour l'instant je manque un peu de temps mais je verrais chat dans le we sûrement. Cela devrait pouvoir répondre à ton besoin (quel qu’il soit ^^"). Mais sinon dans l'immédiat, il suffit de remplacer le code DXF 6 par le code DXF 370 ici : ltp (if (assoc 6 (entget name)) (cdr (assoc 6 (entget name))) "ByLayer") Bisous, Luna
  23. Coucou, Premièrement tu peux simplifier ton filtre ssget (list '(-4 . "<OR") '(0 . "LWPOLYLINE") '(0 . "ARC") '(0 . "LINE") '(0 . "MLINE") '(-4 . "OR>") ) ) a une liste plus simple '((0 . "LWPOLYLINE,ARC,LINE,MLINE)) Ensuite, lorsqu'on supprime des entités d'un jeu de sélection, on préfère parcourir le jeu de sélection en partant de la fin et non du début. Cela permet d'éviter les erreurs du genre l'entité à l'indice i est supprimée donc l'entité i+1 devient l'entité à l'indice i, mais dans ta boucle tu passeras à l'indice i+1 (donc cela correspond à l'entité i+2 avant la suppression). Pour cela on favorise une écriture du genre (repeat (setq i (sslength selline)) (setq enti (ssname selline (setq i (1- i)))) ... Je pense que la seconde boucle (while) est en trop. Il faut plutôt que tu arrives à comprendre le principe des listes, et plus précisément des listes d'association. On construit une liste avec les fonctions (list), (append) et/ou (cons). Le plus courant c'est la fonction (cons) dans une boucle, comme par exemple (while ... (setq lst (cons value lst)) ) Où 'value' correspond à la valeur que l'on veut ajouter à la liste. Cela va construire une liste basique, en revanche une liste d'association c'est plutôt quelque chose que l'on va construire comme ceci : (while ... (setq lst (cons (cons key value) lst)) ) Ici 'key' correspond à la clé de recherche, donc pour toi il pourrait s'agir du nom du calque ou du type de ligne et 'value' correspond à la valeur que l'on souhaite associer à la clé. Par exemple une liste (0 1 2 3 4 5 6 7 8 9) correspond à la première version, il s'agit d'une liste normale. Par contre un exemple de liste d'association c'est le résultat de (entget) ( (-1 . <Nom d'entité: 26841854c60>) (0 . "INSERT") (5 . "7F6") (102 . "{ACAD_XDICTIONARY") (360 . <Nom d'entité: 26841854ce0>) (102 . "}") (330 . <Nom d'entité: 268420f11f0>) (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbBlockReference") (2 . "Flower") (10 0.0 0.0 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0) ) Avec une liste d'association on peut très facilement récupérer une valeur 'value' associée à une clé en recherchant justement la clé. Tu dois récupérer le nom du calque de l'objet ? Et bien tu fais (cdr (assoc 8 (entget enti))) Donc pour faire le tri dont tu parles, il te faut utiliser ce principe en créant une liste d'association de deux niveaux ! Le premier niveau sera une liste d'association dont les clés de recherche correspondent au nom des calques, et leur valeur correspondra à une liste d'association dont les clés de recherche correspondent au nom du type de lignes et leur valeur correspondra à la longueur correspondante (= la longueur cumulée des objets possédant un calque identique et un type de ligne identique). Voici un exemple de programme qui pourrait répondre à ta demande : (defun c:LONGTOT (/ make-list jsel i name lst lng lay ltp) (defun make-list (lst layer ltype long / ltlst) (if (setq ltlst (assoc layer lst)) (subst (cons layer (if (assoc ltype (cdr ltlst)) (subst (cons ltype (+ long (cdr (assoc ltype (cdr ltlst))))) (assoc ltype (cdr ltlst)) (cdr ltlst) ) (append (cdr ltlst) (list (cons ltype long))) ) ) ltlst lst ) (append lst (list (cons layer (list (cons ltype long))))) ) ) (if (setq jsel (ssget '((0 . "*LINE,ARC")))) (progn (repeat (setq i (sslength jsel)) (setq name (ssname jsel (setq i (1- i))) lng (getpropertyvalue name "LENGTH") lay (cdr (assoc 8 (entget name))) ltp (if (assoc 6 (entget name)) (cdr (assoc 6 (entget name))) "ByLayer") lst (make-list lst lay ltp lng) ) ) (mapcar '(lambda (x / lay ltp lng) (princ (strcat "\nLongueur du calque \"" (setq lay (car x)) "\" = " (rtos (apply '+ (mapcar 'cdr (cdr x))) 2 2) (apply 'strcat (mapcar '(lambda (l) (strcat "\n - " (car l) " = " (rtos (cdr l) 2 2) ) ) (vl-sort (cdr x) '(lambda (e1 e2) (< (car e1) (car e2)))) ) ) ) ) ) (vl-sort lst '(lambda (e1 e2) (< (car e1) (car e2)))) ) ) ) (princ) ) Tu peux simplement t'en inspirer, l'utiliser, l'adapter, etc... Il me sort un résultat de ce style-là par exemple : Longueur du calque "Calque1" = 328.29 - ByBlock = 46.61 - ByLayer = 25.69 - Continuous = 228.38 - DASHED = 27.62 Longueur du calque "Calque2" = 108.92 - ByLayer = 58.20 - DASHED = 50.72 Longueur du calque "Calque3" = 186.88 - ByLayer = 99.01 - Continuous = 87.87 Longueur du calque "Calque4" = 102.75 - ByLayer = 102.75 Longueur du calque "Calque5" = 217.55 - ByLayer = 146.46 - Continuous = 71.09 Longueur du calque "Calque6" = 87.67 - ByLayer = 45.55 - DASHED = 42.12 Longueur du calque "Calque8" = 327.99 - ByBlock = 103.88 - ByLayer = 157.14 - Continuous = 35.83 - DASHED = 31.13 Bisous, Luna
  24. J'ai testé vite fait, et vui les données étendues sont copiées avec l'entité. Cela est cohérent en soit. Pour esquiver cela, les dictionnaires peuvent probablement palier à ce soucis mais encore une fois, je m'avance dans un domaine inconnu pour moi (pour le moment 🙂 ). Bisous, Luna
  25. Vui bien sûr tu peux lier des objets entre eux (enfin juste créer une relation de l'un vers l'autre). Donc vui tu peux mettre un nom à ta polyligne via (vlax-ldata-put) et pour chaque bloc qui doivent être "lier" à cette polyligne tu ajoutes l'EntityName de ta polyligne via (vlax-ldata-put). Comme chat tu peux, même depuis un bloc basique, récupérer le nom (vlax-ldata-get) de la polyligne via son EntityName. C'est pas clair mes explications, mon dieu...! Tu pourrais très bien par exemple utiliser ce principe pour faire de la post-sélection en sélectionnant tous les blocs et tu regardes lesquels sont liés à la Polyligne nommée "section 1 voie 1" par exemple. C'est pour cela que je pense sincèrement que cette méthode sera la plus simple sur le long terme car tu auras une fonction/commande qui va créer ces liaisons entre objets ou les mettre à jour, et une fois la première passe faite, tu pourras tout gérer sans aucune intervention utilisateur. Tout ce qu'il faut c'est prévoir les fonctions/commandes pour associer l'ancien au nouveau. En effet, dans ce principe de données étendues il est logique de créer les objets directement depuis une commande pour créer en auto les liaisons de données étendues sans que l'utilisateur soit au courant. Mais il faut aussi prendre en compte l'existant qui nécessite de demander à l'utilisateur de créer les liaisons de données sur les objets déjà crées sans liaisons. Mais après une fois que le principe est en place, cela facilite grandement les lectures de fichier et traitement d'objets. Bisous, Luna
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité