Aller au contenu

cote polyligne


chris_mtp

Messages recommandés

Bonjour,

 

J'ai fait ce petit lisp qui permet de coter une lwpolyligne mais à la fin j'ai le retour suivant :

 

; erreur: type d'argument incorrect: point 2D/3D: nil

 

(defun c:nettoie_pro (/ i ent bdent ptlst typent pt0 pt ptn di dn txt txtn ts ht htb ech tr)
(command "-UNITES" 2 2 3 3 300.000g)

(command "_osnap" "auc")
(setq ent (car (entsel "\nCliquez une polyligne :")))
(setq ech (getreal "\nECHELLE : "))
(setq ts (* ech 0.0016))
(setq ht (* ech 0.005))
(setq htb (* ech 0.0075))
(setq tr (* ech 0.01))
(setq bdent (entget ent))
(setq ptlst (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= (car x) 10)) bdent)))
(setq typent (cdr (assoc 0 bdent)))
(setq i 0)
(if (= typent "LWPOLYLINE")
(while (< i (length ptlst))
(setq pt0 (nth 0 ptlst))
(setq pt (nth i ptlst))
(setq ptn (nth (+ i 1) ptlst))
(setq di (distance pt ptn))
(setq dn (distance pt0 ptn))
(setq txt (strcat (rtos di 2 2)))
(setq txtn (strcat (rtos dn 2 2)))
(command "texte" "mc" (list (+ (/ (- (car ptn) (car pt)) 2) (car pt)) (+ (cadr ptn) ht) 0) ts 200 txt)
(command "texte" "mc" (list (car ptn) (- (cadr ptn) htb) 0) ts 200 txtn)
(setq i (+ i 1))
))
(command "-UNITES" 2 4 3 3 300.000g)
(prin1)
) 

 

Le pb doit venir de la boucle while mais pourquoi ?

Merci par avance de votre aide.

John.

Lien vers le commentaire
Partager sur d’autres sites

Je n'ai pas étudié ton code dans le détail, mais voilà quelques propositions :

 

Tout d'abord, pour traiter le dernier segment des polylignes fermées, tu peux ajouter le premier sommet à la fin de la liste

 

(if (= 1 (logand 1 (cdr (assoc 70 bdent))))
 (setq ptlst (append ptlst (list (car ptlst))))
)

 

Ensuite, il suffit de se rappeler que le nombre de segments est égal au nombre de sommets - 1 :

 

avec n = 0

 

(repeat (1- (length ptlst)) ...)

ou

(while (

 

ou en initialisant n à (1- (length ptlst)) et en "décrémentant".

 

On peut aussi faire 2 listes décalée d'un sommet et les traiter avec mapcar

 

(setq l1 (reverse (cdr (reverse ptlst) l2 (cdr ptlst))

(mapcar '(lambda (p1 p2) (setq di (distance p1 p2)) ...) l1 l2)

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

Lien vers le commentaire
Partager sur d’autres sites

Merci Gile pour ta réponse.

J'ai pu m'en sortir avec le logand.

Par contre, maintenant j'ai un autre pb qui me bloque.

 

Comment faire pour créer une liste de coordonnées type xy puis de tracer par la suite une polyligne 3D qui passe par chacun des points de la liste ?

En fait je calcule des distances qui correspondent à des coordonnées locales.

 

John.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Je ne comprends pas bien la demande : pourquoi une polyligne 3d si les points sont 2d ?

 

Pour faire une liste de points 2d à partir d'une liste de points 3d (ptlst), on peut utiliser la fonction mapcar.

 

mapcar requiert deux arguments : une fonction et une (ou plusieurs) liste(s) et retourne la liste qui est le résultat de l'application de la fonction à chacun des éléments de la (ou des) liste(s).

 

On peut donc faire une fonction qui transforme un point 3d en point 2d :

 

(defun Point3d->Point2d (pt)
 (list (car pt) (cadr pt))
)

et ensuite utiliser cette fonction dans une expression mapcar :

 

(setq 2dptlst (mapcar 'Point3d->Point2d ptlst))

 

Mais pour éviter de faire un defun et rendre le code plus explicite, on utilise en général la fonction lambda qui permet de définir une fonction anonyme à l'endroit même où elle est utilisée :

 

(setq 2dptlst (mapcar '(lambda (pt) (list (car pt) (cadr pt))) ptlst)

 

Pour faire passer la liste de points comme argument à une commande, on peut utiliser foreach ou encore mapcar.

 

(command "_3dpoly")
(foreach pt 2dptlst (command pt))
(command "") ; ou (command "_c") pour clore

ou :

 

(command "_3dpoly")
(mapcar 'command 2dptlst)
(command)

 

 

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

Lien vers le commentaire
Partager sur d’autres sites

Merci Gile pour ces infos mais en fait,

 

je souhaiterais faire une liste des distances cumulées d'une polyligne et des delta z à partir du premier point.

 

J'ai essayé donc de faire une liste mais j'ai le retour numberp: nil

 

(setq pt0 (nth 0 lst_pl))
(foreach pt lst_pl
(setq 2dptlst (mapcar '(lambda (pt) (list (distance pt0 pt) (- (caddr pt) (caddrpt0))) lst_pl))))

 

Je dois donc construire ma liste autrement non ?

 

John.

Lien vers le commentaire
Partager sur d’autres sites

Re,

 

Tes demandes me paraissent toujours un peu confuses

 

J'ai essayé donc de faire une liste mais j'ai le retour numberp: nil

 

Tu écris caddrpt0 au lieu de caddr pt0.

Si tu utilises l'éditeur Visual LISP (ce que je te recommande fortement) les symboles 'protégés' (comme caddr) apparaissent en bleu, les autres symboles (variables par exemple) en noir, ce qui facilite la visibilité de ce type d'erreur.

 

Petite précision : la fonction distance retourne la distance entre 2 points, distance mesurée en ligne droite bien sûr.

 

Si tu veux les distances cumulées sur la polyligne il faut les ajouter au fur et à mesure :

 

(setq dist   0
     pt0    (car lst_pl)
     alt0   (caddar lst pl)		; (caddar ) = (caddr (car ...))
     result (mapcar '(lambda (pt)
		(list (setq dist (+ dist (distance pt0 pt)))
		      (- (caddr pt) alt0)
		)
	      )
	     (cdr lst_pl)
     )
)

 

Le code ci dessus ne fonctionne qu'avec des polylignes n'ayant que des segments rectilignes. Pour des polylignes avec arc, il faut voir du côté des fonctions vlax-curve-*.

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

Lien vers le commentaire
Partager sur d’autres sites

Merci Gile,

Si mes demandes sont confuses, je m'explique.

J'ai voulu faire un lisp qui permet d'afficher la distance cumulée de chaque sommet d'une polyligne et la dénivelé par rapport au premier point sous forme de listing dans autocad mais j'ai pu m'en sortir avec tes infos.

 

Par contre, il me faudrait maintenant insérer un bloc sur chaque point de la polyligne 3D avec comme valeur d'attribut la cote Z de chaque sommet.

 

Voila ce que j'ai pu faire en tirant des exemples à droite et à gauche mais j'ai le retour VLA-OBJECT nil

 

 
(foreach pt lstpt
(setq valz (caddr pt))
(setq att (command "_insert" "nod" pt ech ech "0"))
(setq tag (vla-get-TagString att))
(cond
((= "Z" tag)
(vla-put-TextString att (rtos valz 2 2))
))

 

Pourquoi ?

John.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

En gros, il y 2 façon d'accéder aux données des objets AutoCAD : par les données DXF ou par l'interface COM (parfois appelée ActiveX)

La première utilise le type ENAME avec les fonctions entget, entmod... , la seconde utilise le type VLA-OBJECT avec les fonctions vla-* ou vlax-* (dites fonctions Visual LISP ou vlisp).

 

Dans ton exemple, il y a plusieurs erreurs :

 

(setq att (command "_insert" "nod" pt ech ech "0"))

La fonction command retourne toujours nil, donc ton expression affecte nil à att.

Pour récupérer le ENAME de la référence créée avec command il faut utiliser entlast :

(command "_insert" "nod" pt ech ech "0")
(setq ent (entlast))

Un bloc (référence ou définition) est une entité dit "complexe", c'est à dire composée de "sous entités" : les attributs par exemple.

Pour accéder aux références d'attributs d'une référence de bloc, on utilise la fonction entnext.

Regarde les routines ci dessous qui permettent de récupérer ou d'attribuer la valeur d'une référence d'attribut en spécifiant son étiquette.

 

(setq tag (vla-get-TagString att))

Comme dit plus haut att est nil. Si att etait un ENAME acquis avec (entlast), il y aurait quand même une erreur parce que vla-get-TagString attend un VLA-OBJECT.

On convertit un ENAME en VLA-OBJECT avec la fonction vlax-ename->vla-object. Mais même en faisant ça on aurait une erreur parce que la dernière entité créée (retournée par entlast) est une référence de bloc, pas un attribut et n'a donc pas de propriété TagString.

Il faudrait donc récupérer la liste des attributs de la référence de bloc et chercher dans celle ci l'attribut dont l'étiquette correspond.

(foreach att (vlax-get (vlax-ename->vla-object ent) 'Attributes)
 (if (= "Z" (vla-get-TagString att))
   (vla_put_TextString att (rtos valz 22))
 )
)

 

Mais je pense qu'il est préférable d'acquérir d'abord de bonnes bases avec AutoLISP, l'utilisation des fonctions Visual LISP sera d'autant plus facile par la suite.

 

;;; GetAttValue
;;; Retourne la valeur d'un attribut
;;;
;;; Arguments
;;; blk : le nom d'entité du bloc
;;; tag : le nom de l'étiquette de l'attribut

(defun GetAttValue (blk tag / lst loop val)
 (setq	lst  (entget (entnext blk))
loop (= "ATTRIB" (cdr (assoc 0 lst)))
 )
 (while loop
   (if	(= (strcase tag) (cdr (assoc 2 lst)))
     (setq val	 (cdr (assoc 1 lst))
    loop nil
     )
     (setq lst	 (entget (entnext (cdr (assoc -1 lst))))
    loop (= "ATTRIB" (cdr (assoc 0 lst)))
     )
   )
 )
 val
)

;;; SetAttValue
;;; Attribue une valeur de un attribut
;;;
;;; Arguments
;;; blk : le nom d'entité du bloc
;;; tag : le nom de l'étiquette de l'attribut
;;; val : la valeur à attribuer

(defun SetAttValue (blk tag val / lst loop)
 (setq	lst  (entget (entnext blk))
loop (= "ATTRIB" (cdr (assoc 0 lst)))
 )
 (while loop
   (if	(= (strcase tag) (cdr (assoc 2 lst)))
     (progn
(entmod (subst (cons 1 val) (assoc 1 lst) lst))
(setq loop nil)
(entupd blk)
     )
     (setq lst	 (entget (entnext (cdr (assoc -1 lst))))
    loop (= "ATTRIB" (cdr (assoc 0 lst)))
     )
   )
 )
)

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

Lien vers le commentaire
Partager sur d’autres sites

Merci,

 

Si tu peux prends le temps de l'analyser pour voir comment on boucle sur les "sous entités" (attributs) de la référence de bloc et comment on arrête la boucle dès que l'étiquette est trouvée ou quand entnext ne retourne plus un attribut.

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

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é