chris_mtp Posté(e) le 21 juin 2009 Posté(e) le 21 juin 2009 Bonjour, Je souhaiterai modifier le fameux lisp de Gile Instopo pour l'adapter à mes besoins.Je vous explique. J'ai un fichier texte de points du type N X Y Z Code Att1 à insérer dans Autocad sous forme de blocs comprenant 4 attributs à savoir le numéro du point, le Z, le code et la valeur de l'attribut. Je ne vois pas dans le lisp de Gile comment sont lues les valeurs de chaque attribut et ce qui en détermine la position dans la liste crée après chaque ligne de texte lu à partir du fichier initial. La modif serait de pouvoir dire par exemple le 1er élément de la chaine de caractères correspond au numéro qui doit s'inscrire dans l'attribut MATRICULE du bloc.le 3eme élément de la chaine de caractères correspond au Z qui doit s'inscrire dans l'attribut ALTITUDE du bloc.le 4eme élément de la chaine de caractères correspond au Code qui doit s'inscrire dans l'attribut Code du bloc.le 5eme ..... et ainsi de suite pour chaque attribut qui constitue le bloc. Mon fichier est toujours formaté de la même manière et il n(y a pas de chaine vide ou d'attribut manquant. Merci par avance de votre aide.John.John.
(gile) Posté(e) le 22 juin 2009 Posté(e) le 22 juin 2009 Salut, InsTopo se voulait un LISP polyvalent pour ce genre de choses mais les fichiers point et les demandes pour les traiter semblent être tellement différents qu'il est difficile de faire quelque chose qui marcherait pour tous. Je te propose plutôt de ré-écrire un truc spécifique à tes besoins. Tout d'abord, tu crées ton bloc à ta convenance Puis tu fais ton LISP : 1) tu sélectionnes le fichier : (setq filename (getfiled "Sélectionner un fichier point" "" "txt;csv;*" 0))2) tu ouvres le fichier en lecture : (setq file (open filename "r"))3) tu lis le fichier ligne par ligne dans une boucle while et tu convertit la ligne en liste avec la routine str2lst (voir ci-dessous)(while (setq line (read-line file)) ...4) tu convertis la ligne en liste avec la routine str2lst (voir plu bas) en spécifiant le séparateur utilisé dans le fichier.(setq lst (str2lst line ",")5) tu as maintenant une liste du type (N X Y Z Code Att1) dont il est facile de récupérer les éléments. Tu insères ton bloc avec command (ATTREQ à 1) ou vla-InsertBlock et tu renseignes les attributs. 6) Après la boucle, tu refermes le fichier :(close file) ;; str2lst ;; Transforme un chaine avec séparateur en liste de chaines ;; ;; Arguments ;; str : la chaine à transformer en liste ;; sep : le séparateur ;; ;; Exemples ;; (str2lst "a b c" " ") -> ("a" "b" "c") ;; (str2lst "1,2,3" ",") -> ("1" "2" "3") ;; (mapcar 'read (str2lst "1,2,3" ",")) -> (1 2 3) (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) ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Bonjour Gile Je viens tout juste de rentrer de déplacement désolé pour le retard dans la réponse et merci de ton aide. Voila ce que j'ai pu faire mais apparemment, il y a un souci avec les nth ou autre chose car j'ai le retour d'erreur ; erreur: type d'argument incorrect: numberp: "8.2695" Mon fichier est du type 1 9610.7280 4069.5719 8.2695 100 TEXT Et voici le code (defun c:inspts(/ filename file line lst) (setq filename (getfiled "Sélectionner un fichier point" "" "txt;csv;*" 0)) (setq file (open filename "r")) (while (setq line (read-line file)) (setq lst (str2lst line " ")) (traitement_points lst) (close file) ) (prin1) ) (defun traitement_points (lst / lez cod att1) (setq lez (rtos (nth 3 lst) 2 2)) (setq cod (nth 4 lst)) (setq att1 (nth 5 lst)) (command "_.insert" "PT" (list ((nth 1 lst) (nth 2 lst) (nth 3 lst))) lez cod att1) ) (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) ) ) Merci par avance de ton aide.John.
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Bonjour Gile J'ai pu m'en sortir sur les coordonnées de point d'insertion avec la fonction atof et la fonction rtos pou l'attribut alt. Par contre, mes points s"insérent correctement mais j'ai à la fin une erreur du type Commande: ; erreur: type d'argument incorrect: stringp nil N'est il pas possible de connaître à l'avance le nombre de ligne à traiter pour sortir du programme en douceur ? Merci par avance de ton aide.John.
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Gile, c'est bon en fait, l'erreur string nil venait de la valeur d'un attribut qui n'était pas dans la liste. Maintenant, j'ai un autre souci pour lequel je ne trouve pas de solution.Je dois insérer un bloc avec attribut en 3 points et donc récupérer les valeurs des coordonnées des points des deux lignes qui suivent mon point d'insertion de mon bloc. Exemple : 25 378.749 805.8548 25.242326 377.8199 806.6664 25.1894 27 377.4779 806.3038 25.2085 Je dois insérer mon bloc sur le point 25 avec échelle en x égale à ma distance 25-26 et échelle en y égal à distance 26-27 puis valeur de l'angle de rotation égal à l'angle 25-26 par rapport au nord. Comment faire pour les valeurs des points 26 et 27 pour calculer les paramètres d'insertion de mon bloc echelle en x et y puis valeur de la rotation ? Merci par avance de ton aide.John.
(gile) Posté(e) le 27 juin 2009 Posté(e) le 27 juin 2009 Salut, Tout d'abord, c'est très bien que tu aies trouvé et corrigé les erreurs par toi même, c'est comme ça qu'on progresse. Bravo. La fonction read-line ne permet de traiter les lignes du fichier qu'une par une. Il faut donc récupérer les données du fichier sous une forme plus facile à traiter en LISP, par exemple une liste : (setq file (open filename "r")) (while (setq line (read-line file)) (setq lst (cons (str2lst line " ") lst)) ) (close file) (setq lst (reverse lst)) lst est maintenant une liste contenant toutes les sous listes des données de chaque point du type :((N1 X1 Y1 Z1 Code1 Att1) (N2 X2 Y2 Z2 Code2 Att2) ... (Nn Xn Yn Zn Coden Attn)) On peut alors traiter la liste avec les nombreuses fonctions LISP de traitement des listes.On peut utiliser nth avec un compteur incrémenté pour accéder à chacun des éléments, ou encore (plus efficace) en vidant la liste au fur et à mesure que les trois premiers points sont traités : (while (cddr lst) ; tant que la liste contient au moins 3 éléments (setq l1 (car lst)) ; 1er élément (setq l2 (car lst)) ; 2ème élément (setq l3 (car lst)) ; 3ème élément (setq lst (cdddr lst)) ; la liste moins les 3 premiers éléments (setq pt1 (list ; 1er point (atof (cadr l1)) (atof (caddr l1)) (atof (cadddr l1)) ) ) (setq pt2 (list ; 2ème point (atof (cadr l2)) (atof (caddr l2)) (atof (cadddr l2)) ) ) (setq pt3 (list ; 3ème point (atof (cadr l3)) (atof (caddr l3)) (atof (cadddr l3)) ) ) (setq echX (distance pt1 pt2)) ; échelle X (setq echY (distance pt2 pt3)) ; échelle Y (setq rot (if (= 1 (getvar "ANGDIR")) ; rotation (- (angle pt1 pt2) (getvar "ANGBASE")) (+ (angle pt1 pt2) (getvar "ANGBASE")) ) ) (setq lez (rtos (caddr pt1) 2 2)) (setq cod (nth 4 l1)) (setq att1 (nth 5 l1)) (setq echo (getvar "CMDECHO")) (setvar "CMDECHO" 0) ; désactiver les echos sur la ligne de commande (command "_.insert" "PT" pt1 "_x" echX echY 1.0 rot lez cod att1) (setvar "CMDECHO" echo) ) Tout ça pourrait être écrit de manière plus concise, mais je cherche à âtre le plus explicite possible. NOTA : quand on utilise la fonction LISP command, la ligne de commande affiche toutes les invites de la commande.Ceci peut être utile pour déboguer le programme mais ça ralentit son exécution, ce qui n'a que peut d'importance si la fonction n'est appelée qu'une fois, mais peut devenir notable dans une boucle comme ici.On désactive ces "échos" en jouant avec la variable CMDECHO Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 C'est bon pour les blocs en 3 points, j'ai pu m'en sortir en lisant les deux lignes avec : (setq lst1 (str2lst (read-line file) " ")) (setq pt1 (list (atof (nth 1 lst1)) (atof (nth 2 lst1)) (atof (nth 3 lst1)))) (setq lst2 (str2lst (read-line file) " ")) (setq pt2 (list (atof (nth 1 lst2)) (atof (nth 2 lst2)) (atof (nth 3 lst2)))) Dernière question et après ce sera complet, Comment faire pour tracer une polyligne 3D en une succession de points ayant les 3 premiers caractères du code identique ? Voici un exemple : 25 378.749 805.8548 25.2423 20326 377.8199 806.6664 25.1894 203.327 377.4779 806.3038 25.2085 203.8 Les trois points ont le même code 203 comme préfixe. Le suffixe du code du dernier point est un code de fermeture de la polyligne 3D alors que le .5 indique que la poly ne doit pas être fermée. Et donc la polyligne doit se tracer de 25 à 26 puis à 27.La je pense que ta méthode serait plus simple mais comment intégrer les conditions ? C'est là que je bloque.Merci de ton aide.John.
(gile) Posté(e) le 27 juin 2009 Posté(e) le 27 juin 2009 Re, Pour comparer les données (qui sont de chaînes) regarde la fonction substr :(substr "203.3" 1 3) retourne "203"(substr "203.8" 5) retourne "8" Tu peux ensuite comparer les chaînes avec l'opérateur = Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Mais quand il y a par exemple dix points qui ont le même code,je ne vois pas comment comparer les chines de caractères ??? Merci de ton aide.John.
(gile) Posté(e) le 27 juin 2009 Posté(e) le 27 juin 2009 Si tu utilises la méthode que je donnais plus haut qui vide la liste au fur et à mesure qu'elle la traite, il faut faire une "copie" de cette liste pour pouvoir faire ce nouveau traitement (setq new-list lst) et on traite new-list avec la même méthode :Tant qu'elle n'est pas vide, pour son premier élément, on stocke le code dans la variable code et les coordonnées du point dans la liste pts.Si new-list ne contient pas de deuxième élément ou que le code de cet élément n'a pas les mêmes 3 premiers caractères que code, on dessine la polyligne 3d et on vide pts. Dans tous les cas, on supprime le premier élément de la new-list et on re boucle. (while new-list (setq first (car new-list) code (nth 4 first) pts (cons (list (atof (nth 1 first)) (atof (nth 2 first)) (atof (nth 3 first)) ) pts ) ) (if (or (null (setq second (cadr new-list))) (/= (substr code 1 3) (substr (nth 4 second) 1 3)) ) (progn (if ( (progn (command "_.3dpoly") (foreach p (reverse pts) (command "_non" p) ) (if (= (substr code 4) ".5") (command) (command "_c") ) ) ) (setq pts nil) ) ) (setq new-list (cdr new-list)) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Gile, j'ai essayé de modifier ton code selon mes besoins mais je ny arrive pas ya un bug et je sais pas ou.JE veux utiliser ton code en temps que sous routine pour l'utiliser qu'en cas de présence d'un code particulier. Certains codes de mes points doivent être utilisés pour des blocs par un point ou 3 points et d'autres pour le tracé des polylignes 3D or dans ton code, ca ne me trace que des poly 3D donc si on pourrait y mettre en condition un truc du style (if (= (atof cod) 203) (bt lst)) De plus, j'ai l'impression de ta routine reprend la liste depuis le début à chaque fois alors que je voudrais seulement qu'il traite la suite des points les uns après les autres.Si ca peut se servir, j'utilise un préfixe du type .5 pour indiquer que ma poly 3D s'arrête et un suffixe du type .8 pour dire qu'elle s'arrête et qu'elle doit se fermer en son premier point. Merci par avance de ton aide.John. Speedy, regarde tes unités d'insertion à mon avis.
(gile) Posté(e) le 27 juin 2009 Posté(e) le 27 juin 2009 Speedy, S'il te plait, ouvre un nouveau sujet pour ton problème qui semble-t-il n'a pas grand chose à voir avec celui de chris_mtp chris_mtp J'ai toujours autant de mal à comprendre tes demandes. À chaque réponse, tu ajoutes une nouvelle demande et tu distilles les informations au compte goutte. Si tu pouvais donner un exemple représentatif du type de fichier que tu as à traiter et dire précisément, de manière claire et logique ce que tu voudrais obtenir, ça aiderait ceux qui veulent bien t'aider et ça t'aiderait aussi à structurer ton programme. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 27 juin 2009 Auteur Posté(e) le 27 juin 2009 Désolé de ne pas me faire comprendre du premier coup. Voici un exemple qui je pense sera plus clair . 1 274.6253 336.1729 17.3017 2032 273.5561 333.2459 17.313 203.33 274.4668 332.8913 17.3073 203.54 039.2175 387.3724 16.411 2025 040.9549 384.7242 16.3003 202.26 041.7836 385.2299 16.343 202.67 380.1717 137.301 19.9 2048 383.2345 136.6416 19.452 204.39 383.4449 137.5947 19.4053 204.8 Dans ce cas, il faut que le code trace une polyligne 3D non fermée de 1 à 2 puis 3 dans un calque spécifique, insérer un bloc en 3 points dans un autre calque avec les points 4,5,6 puis tracé une polyligne 3D de 7 8 et 9. Dans mon code, j'ai trouvé la solution pour insérer des blocs en lisant le fichier texte une fois puis dès qu'il trouve un code correspondant, il met le calque concerné en calque courant par CLAYER puis tracé l'élément en question. Je n'arrive pas à modifier ton code pour tracer seulement des polylignes fermées au code avec le préfixe concerné. Il faudrait à mon avis pour le cas des polylignes 3D traiter le fichier texte dans un autre code pour plus de facilité. J'ai une liste d'une centaine de code au total.Mais on peut voir déjà comme çà avec ces 3 codes exemples.En espérant que je me suis expliqué de façon claire, merci par avance de ton aide.John.
(gile) Posté(e) le 28 juin 2009 Posté(e) le 28 juin 2009 Désolé mais c'est pas vraiment plus clair. - Je ne comprends plus ce qui détermine si le code doit dessiner un polyligne 3d : avant c'était le code 203, maintenant c'est 203 ou 204 ??!!- Est-ce que le code 202 indique qu'il faut insérer un bloc 3 points ? est-ce le seul à indiquer cela ?- S'il existe d'autres codes, quelle est leur signification ?- Qu'en est-il des "blocs par un points" ?- Où est passée la sixième donnée (att) ? Avec ce que je crois arriver à décrypter des informations que tu donnes, je te propose ce bout de code.C'est vraiment le maximum de ce que je peux faire, soit tu arrives à l'adapter à tes besoins, soit tu exposes ton problème de manière claire et exhaustive. (defun c:inspts (/ filename file line lst) (setq filename (getfiled "Sélectionner un fichier point" "" "txt;csv;*" 0) ) (setq file (open filename "r")) (while (setq line (read-line file)) (setq lst (cons (str2lst line "\t") lst)) ) (close file) (setq lst (reverse lst)) (while lst (setq first (car lst) code (nth 4 first) lst (cond ((or (wcmatch code "203*") (wcmatch code "204*")) (setq lst (make_poly3d lst first code)) ) ((wcmatch code "202*") (setq lst (ins_bloc_3pts lst first code)) ) (T (setq lst (ins_bloc_1pt lst first code))) ) ) ) (princ) ) ;; Insérer "bloc par 1 point" (defun ins_bloc_1pt (lst first code / pt1 lez att1) (setq pt1 (list (atof (cadr first)) (atof (caddr first)) (atof (cadddr first)) ) lez (rtos (caddr pt1) 2 2) att1 (nth 5 first) ) (command "_.insert" "PT" "_non" pt1 1.0 1.0 0.0 lez code) (setq lst (cdr lst)) ) ;; Insérer "bloc par 3 points" (defun ins_bloc_3pts (lst first code / pt1 pt2 pt3 echX echY rot lez) (mapcar '(lambda (v l) (set v (list (atof (cadr l)) (atof (caddr l)) (atof (cadddr l)) ) ) ) '(pt1 pt2 pt3) (list first (cadr lst) (caddr lst)) ) (setq echX (distance pt1 pt2) echY (distance pt2 pt3) rot (if (= 1 (getvar "ANGDIR")) (- (angle pt1 pt2) (getvar "ANGBASE")) (+ (angle pt1 pt2) (getvar "ANGBASE")) ) lez (rtos (caddr pt1) 2 2) att1 (nth 5 first) ) (command "_.insert" "PT" "_non" pt1 "_x" echX echY 1.0 (angtos rot 2 16) lez code) (setq lst (cdddr lst)) ) ;; Dessiner polyligne 3d (defun make_poly3d (lst first code / ref pts) (setq ref (strcat (substr code 1 3) "*")) (while (and first (wcmatch (nth 4 first) ref) (setq code (nth 4 first)) ) (setq pts (cons (list (atof (nth 1 first)) (atof (nth 2 first)) (atof (nth 3 first)) ) pts ) lst (cdr lst) first (car lst) ) ) (command "_.3dpoly") (foreach p (reverse pts) (command "_non" p) ) (if (= (substr code 4) ".8") (command "_c") (command) ) lst ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 4 juillet 2009 Auteur Posté(e) le 4 juillet 2009 Merci Gile pour ta réponse.Je sais je ne suis pas très explicite quelque fois mais j'ai pu m'en sortir avec tes infos. J'ai fait une liste de code pour les polylignes, les blocs 1 point et 3 point puis j'ai fait appel à chaque sous routine correspondante selon la valeur du code trouvé dans le fichier texte. Merci encore.John.
chris_mtp Posté(e) le 22 août 2009 Auteur Posté(e) le 22 août 2009 Bonjour Gile, Je suis en train de modifer ce lisp pour l'adapter à mes beoins mais j'ai un problème avec la fonction make_poly3d.Je te rappelle en deux mots ce que je veux faire.A partir d'un semis de points codifié, c'est à dire un fichier texte N X Y Z Code, je veux tracer des polylignes. Je te donne un exemple simple avec le fichier de points format texte ci-dessous 1 328.3597 683.9375 5.150324806 2032 325.3092 684.9577 5.090597469 203.13 321.8876 686.0142 5.004440185 203.14 316.6931 686.9688 4.863586669 2055 313.3115 687.0264 4.745996852 205.16 309.8689 686.8254 4.588746593 203.57 306.7425 685.8647 4.379835319 205.110 300.0204 681.3748 4.237701208 20312 294.8277 676.3205 4.205529748 203.114 289.4974 671.1836 4.196680146 203.115 287.2692 668.5112 4.289344627 205.516 284.5862 665.5201 4.307360618 203.5 D'après ce fichier de points, le lisp doit me tracer une polyligne 3D passant par les points 1 2 3 et 6 ,une seconde polyligne passant par les points 4,5,7 et 15 et enfin une troisième polyligne passant par les points 10,12,14 et 16 car le suffixe .5 d'un code indique la polyligne 3D doit s'arréter et donc en tracer une nouvelle à partir du point suivant.Or quand j'utilise la fonction, le lisp me trace une seule polyligne 3D entre le point 1 et le point 16. Je pense qu'il faudrait modifier la première ligne de la fonction mais je ne vois pas comment.J'ai essayé d'ajouter le bout de code surligné mais je pense que la fonction ne tient pas compte de ma condition. (defun make_poly3d (lst first code / ref pts) (setq ref (strcat (substr code 1 3) "*")) (while (and first (wcmatch (nth 4 first) ref) (setq code (nth 4 first)) ) (setq pts (cons (list (atof (nth 1 first)) (atof (nth 2 first)) (atof (nth 3 first)) ) pts ) lst (cdr lst) first (car lst) ) ) (command "_.3dpoly") (foreach p (reverse pts) (command "_non" p) ) (if (= (substr code 4) ".4") (command "_c") (command) ) [surligneur] (if (= (substr code 4) ".5") (command "exit") (command) )[/surligneur] lst ) Si tu ne comprends pas, je peux te mettre en ligne une image pour voir le résultat final.Merci par avance de ton aide car là vraiment je suis bloqué. John. [Edité le 22/8/2009 par chris_mtp] [Edité le 22/8/2009 par chris_mtp]
(gile) Posté(e) le 22 août 2009 Posté(e) le 22 août 2009 Salut, Je te renvoie à ce que je disais au début de la réponse 13. Le principal de la programmation consiste à traduire des algorithmes en code.Un algorithme est un chemin, une suite de prises de décisions qui permettent d'aboutir au résultat voulu.Par exemple, la traduction logique de ce qu'on ferait dans sa tête pour dessiner des polylignes 3d à partir d'une liste de points.Les décisions dépendent de critères qui doivent objectifs et surtout déterminés dès le départ.Or à chacune de tes nouvelles demandes, ces critères évoluent... Je te donne une dernière fois un bout de code commenté qui répond à ta dernière demande (et uniquement à celle là).Ce que tu veux faire est trop spécifique et demande à intégrer trop de critères (mal définis) pour que je puisse continuer sans que cela ne me coute (moralement et financièrement). (defun make_pline (lst / loop cnt start pref pts) ;; boucle principale : tant que lst n'est pas nil (while lst ;; initialisation des données (setq loop T ; balise pour la boucle secondaire cnt 0 ; conmpteur dans la liste start (car lst) ; premier élément pref (substr (nth 4 start) 1 3) ; préfixe du code pts (list (list (atof (cadr start)) ; liste de points (atof (caddr start)) (atof (cadddr start)) ) ) lst (cdr lst) ; la liste sans son premier élément ) ;; boucle secondaire : tant que loop, lst et start ne sont pas nil (while (and loop lst (setq start (nth cnt lst))) ;; évalue si start a le même préfixe de code (if (= (substr (nth 4 start) 1 3) pref) ;; si oui : (progn ;; ajout du point à la liste pts et suppression de l'élément de la liste (setq pts (cons (list (atof (cadr start)) (atof (caddr start)) (atof (cadddr start)) ) pts ) lst (vl-remove start lst) ) ;; évalue si le suffixe du code = 5 (if (= (substr (nth 4 start) 5) "5") ;; si oui (progn ;; dessiner la poly (command "_.3dpoly") (foreach p (reverse pts) (command "_non" p) ) (command) ;; terminer la boucle secondaire (setq loop nil) ) ) ) ; si non, passer à l'élément suivant dans la liste (setq cnt (1+ cnt)) ) ) ) ) Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
chris_mtp Posté(e) le 25 août 2009 Auteur Posté(e) le 25 août 2009 Merci de ton aide Gile.Je pense que je vais pouvoir m'en sortir maintenant. John.
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant