Aller au contenu

Problème avec un programme lisp


bourinox

Messages recommandés

Bonjour tout le monde,

 

Voila j'ai un souci avec un programme lisp il se bloque dans certaines circonstance et je n'arrive pas trouvé mon erreur. Si quelqu'un peut m'aider ce serait vraiment gentil.

 

Je vous explique le principe. du programme.

 

J'ai des blocs (A, B, C,..Z) que je dois remplacer par d'autre blocs (A1,B1,C1....,Z1) qui eux n'ont pas forcément le même point d'insertion ni la même echelle et qui n'ont pas le même nom.

J'ai donc écrit pour commencer un fichier texte tabulé structuré de la façon suivante:

 

Nom bloc existant (tab) Nom bloc cible (tab) Dx (tab) Dy (Tab) echX (Tab) echY

 

Par exemple: si le bloc" A" qui est un carré a comme point d'insertion 0;0 et come longeur 1 mètre, et que le bloc A1 est un carré avec un point d'insertion 0;1 et qui a comme longeur 2 metre..

 

A (tab) A1 (tab) 1 (tab) 0 (tab) 0,5 (tab) 0,5

 

Ensuite j'ai écrit un programme lisp qui en faisant appel à ce fichier txt tabulé remplace tous les bloc( A,B,C,...,Z) par les bloc (A1,B1,C1,....,Z1).

 

le voici:

(defun c:chblocs ()

(setq fic (open "C:/sevres/02_Table sandreauDESMOULINS/tabledefdESMOULIN.txt" "r"))

(read-line fic)

(setq ligne (read-line fic))

(while (/= ligne nil)

;lecture des paramètres

(setq posblc2 (vl-string-position 9 ligne))

(setq posdx (vl-string-position 9 ligne (+ posblc2 1)))

(setq posdy (vl-string-position 9 ligne (+ posdx 1)))

(setq posechx (vl-string-position 9 ligne (+ posdy 1)))

(setq posechy (vl-string-position 9 ligne (+ posechx 1)))

(setq nomblc1 (substr ligne 1 posblc2))

(setq nomblc2 (substr ligne (+ posblc2 2) (- posdx posblc2 1)))

(setq dx (atof (substr ligne (+ posdx 2) (- posdy posdx 1))))

(setq dy (atof (substr ligne (+ posdy 2) (- posechx posdy 1))))

(setq echx2 (atof (substr ligne (+ posechx 2) (- posechy posechx 1))))

(setq echy2 (atof (substr ligne (+ posechy 2) (- (strlen ligne) posechy 1))))

;echange du bloc

(setq jeusel (ssget "x" (list (cons 0 "INSERT") (cons 2 nomblc1))))

(setq nbobj (sslength jeusel))

(setq i 1)

(setq listobj (list (ssname jeusel 0)))

(repeat (- nbobj 1)

(setq listobj (append listobj (list (ssname jeusel i))))

(setq i (+ i 1))

)

(setq i 0)

(repeat nbobj

(setq objet (nth i listobj))

(setq i (+ i 1))

(setq dxf (entget objet))

(foreach code dxf

(progn

(if (= (car code) 0)

(setq tipe code)

)

(if (= (car code) 2)

(setq nom code)

)

(if (= (car code) 10)

(setq coordblc1 code)

)

(if (= (car code) 50)

(setq rotblc1 (cdr code))

)

(if (= (car code) 41)

(setq echxblc1 code)

(setq echx (cdr echxblc1))

)

(if (= (car code) 42)

(setq echyblc1 code)

(setq echy (cdr echyblc1))

)

)

)

(if (= (cdr tipe) "INSERT")

(if (= (cdr nom) nomblc1)

(progn

;calcul du point d'insertion du nouveau bloc

(setq xblc1 (nth 1 coordblc1))

(setq yblc1 (nth 2 coordblc1))

(if (/= dy 0)

(progn

(setq deca (sqrt (+ (* dx dx echx echx echx2 echx2) (* dy dy echy echy echy2 echy2))))

(setq ang (atan (/ (* dx echx) (* dy echy))))

(setq dx2 (* deca (sin (- ang rotblc1))))

(setq dy2 (* deca (cos (- ang rotblc1))))

(if (< dy 0)

(progn

(setq dx2 (- 0 dx2))

(setq dy2 (- 0 dy2))

)

)

)

(progn

(if (/= dx 0)

(progn

(if (< dx 0) (setq ang PI) (setq ang 0))

(setq dx2 (* echx2 echx dx (cos (- ang rotblc1))))

(setq dy2 (* echy2 echy dx (sin (+ ang rotblc1))))

)

(progn

(setq dx2 (* echx2 echx dx))

(setq dy2 (* echy2 echy dy))

)

)

)

)

(setq coordblc2 coordblc1)

(setq coordblc2 (subst (+ xblc1 dx2) xblc1 coordblc2))

(setq coordblc2 (subst (+ yblc1 dy2) yblc1 coordblc2))

;echange du bloc

(setq nvnom (cons 2 nomblc2))

(setq echxblc2 (cons 41 (* echx2 echx)))

(setq echyblc2 (cons 42 (* echy2 echy)))

(setq dxf (subst nvnom nom dxf))

(setq dxf (subst coordblc2 coordblc1 dxf))

(setq dxf (subst echxblc2 echxblc1 dxf))

(setq dxf (subst echyblc2 echyblc1 dxf))

(entmod dxf)

)

)

)

)

(setq ligne (read-line fic))

)

(close fic)

)

 

Le problème est le suivant :

Quand le programme ne trouve pas le bloc A sur le dessin il s'arrete et ne passe pas au bloc suivant. Sauriez vous d'où cela vient?

 

 

Voila désolé pour le post pavé et merci d'avance pour les éventuelle réponse.

 

 

Lien vers le commentaire
Partager sur d’autres sites

Bonjour

Que se passe t il si la ligne "(if (= (cdr nom) nomblc1)" renvoit la réponse NON ? car cette ligne renvoit vers une seule (et grande) boucle avec un "PROGN".

Donc il si (if (= (cdr nom) nomblc1) renvoit "NON" ... ca se bloque ???

 

Je te conseille de ne pas mettre 5 IF en parallèle car le déboguage et difficile.

Il faut mieux faire plusieurs petit defun plutot qu'un grand, c'est beaucoup plus simple a déboguer...

A bientot

Florent

 

Lien vers le commentaire
Partager sur d’autres sites

(setq jeusel (ssget "x" (list (cons 0 "INSERT") (cons 2 nomblc1))))

(setq nbobj (sslength jeusel))

(setq i 1)

(setq listobj (list (ssname jeusel 0)))

(repeat (- nbobj 1)

(setq listobj (append listobj (list (ssname jeusel i))))

(setq i (+ i 1))

)

(setq i 0)

(repeat nbobj

(setq objet (nth i listobj))

(setq i (+ i 1))

 

pourquoi faut-il créer une liste listobj à partir du jeu de sélection et ne pas dépiauter directement le jeu de sélection lui-même ?

 

(setq jeusel (ssget "x" (list (cons 0 "INSERT") (cons 2 nomblc1))))
(if jeusel
(progn
 (setq I 0)
 (while (< I (sslength jeusel))
   (setq E (ssname jeusel I))
   (setq A (entget E))
   (setq NOMBLOCK (strcase (cdr (assoc 2 A))))
   (setq PTINS (cdr (assoc 10 A)))
   (setq ANGROT (cdr (assoc 50 A)))
   (setq ECHX (cdr (assoc 41 A)))
   (setq ECHY (cdr (assoc 42 A)))
  ...
insérer ici le code supplémentaire
 ...
   (setq I (+ I 1))
 )
)
)

 

je pense que cela simplifiera grandement le code et te permettra de voir plus clair.

 

(if (= (cdr tipe) "INSERT")

 

Je pense que ce if ne sert à rien puisque tu fais un ssget en filtrant justement les INSERT et que donc cette condition sera toujours vraie.

 

Amicalement

 

Zebulon_

 

[Edité le 16/11/2005 par zebulon_]

C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme)

C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi)

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Quelques remarques juste comme çà, je n'ai pas approfondi.

 

Tu devrais déclarer tes variables locales, elle seraient renvoyées à nil à la fin de l'exécution de ta routine, sinon, par exemple, à chaque exécution de la routine, dans la variable listobj vont s'ajouter à la liste précédente, les nouveaux blocs sélectionnés.

 

Tu devrais d'ailleurs essayer de diminuer un peu le nombre de variables.

 

Certaines lignes me semblent inutiles, par exemple :

- le premier (read-line fic),

- comme le dit zebulon_ , le (if (= (cdr tipe) "INSERT")

- mais aussi le (if (= (cdr nom) nomblc1) pour la même raison (ce qui répond à la remarque de Florent_Bourg)

 

Question de style, tu pourrais alléger ton code en supprimant des (progn ... par exemple :

(progn

(setq dx2 (- 0 dx2))

(setq dy2 (- 0 dy2))

)

peu s'écrire :

(setq dx2 (- dx2)

dy2 (- dy2)

)

 

Enfin peu-être ajouter après le (entmod dxf) un (entupd obj).

 

En espérant t'avoir un peu aidé...

 

À plus

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Re,

 

Je n'ai pas essayé ton LISP, mais après avoir laissé décanter un peu.

 

Quand le programme ne trouve pas le bloc A sur le dessin

 

Ton problème me semble venir de la liste listobj qui contiendrait des objets qui ne sont pas sur le dessin, et ce, parcequ'elle n'a pas été "vidée".

Quand on utilise une liste affectée à une variable, il est prudent de "vider" la variable avant de la redéfinir avec un (setq listobj nil) au cas où cette variable ait déjà été utilisée dans l'exécution d'un LISP dans lequel elle n'était pas déclarée (d'où l'intérêt de déclarer les variables).

 

Mais dans le cas présent, comme le dit Zebulon_, cette liste n'est pas utile, tu peux parcourir directement le jeu de sélection qui, lui, ne peut contenir que les objets existants dans le dessin et qui sont passé par ton filtre de sélection.

 

Bon courage

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

...virer les if mais je l'aime bien cette fonction moi

 

Essaie aussi la fonction cond, on s'embête moins avec les progn. (que j'ai justement oublié de mettre dans mon exemple ci dessus :red: )

 

Un exemple piqué dans l'aide d'autocad

 

 
 (cond
     ((= what_next 4)                       ;Prompt user to
       (getpoint "\npick a point")          ;pick pt.
     )
     ((= what_next 0)
       (prompt "\nuser cancelled dialog")
     )
   )

 

Si tu aimes les if, tu adoreras les cond

 

Amicalement

 

Zebulon_

 

[Edité le 16/11/2005 par zebulon_]

C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme)

C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi)

Lien vers le commentaire
Partager sur d’autres sites

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 compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • 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é