Aller au contenu

Décaler uniquement un segment de polyligne.


Messages recommandés

Posté(e)

C'est une routine que j'essaye d'améliorer, j'ai voulu l'écrire sans faire d'appel à commande.

Il me reste juste un petit problème à résoudre, c'est le côté de décalage pour les arcs.

 

Pour les segments droit ça fonctionne bien, mais pour les arrondis je ne sais comment faire pour avoir une fiabilité sur la détermination du côté à décaler.

Un autre problème (moins important); je ne sais comment émuler le paramètre "par" ("_through") de la commande décaler avec (vla-Offset).

 

La routine s'appuie sur (near_vertex) sur laquelle (gile) m'a déjà bien aidé.

 

(defun c:offset_vertex ( / obj dxf_obj obj_vlax pt_sel par i pt_first pt_snd bulge e_next pt_ref lst_dxf rad p_cen dxf_210 dis_offset where_pt v1 v2 det_or)
(while (not (setq obj (entsel "\nChoix d'une polyligne "))))
(cond
	((or (eq (cdr (assoc 0 (setq dxf_obj (entget (car obj))))) "LWPOLYLINE")
		(and
			(eq (cdr (assoc 0 dxf_obj)) "POLYLINE")
			(zerop (boole 1 112 (cdr (assoc 70 dxf_obj))))
		)
	 )
		(vl-load-com)
		(setq
			obj_vlax (vlax-ename->vla-object (car obj))
			pt_sel
			(vlax-curve-getClosestPointToProjection
				obj_vlax
				(trans (cadr obj) 1 0)
				(mapcar '- (trans (getvar "VIEWDIR") 1 0) (trans '(0 0 0) 1 0))
			)
			par (vlax-curve-getParamAtPoint obj_vlax pt_sel)
			i 0
		)
		(if (>= par (vlax-curve-getEndParam obj_vlax)) (setq par (1- par)))
			(setq pt_first (trans (vlax-curve-getPointAtParam obj_vlax (fix par)) 0 1)
		)
		(if (= (1+ (fix par)) (vlax-curve-getEndParam obj_vlax))
			(setq pt_snd (trans (vlax-curve-getEndPoint obj_vlax) 0 1))
			(setq pt_snd (trans (vlax-curve-getPointAtParam obj_vlax (1+ (fix par))) 0 1))
		)
		(cond
			((eq (cdr (assoc 0 dxf_obj)) "LWPOLYLINE")
				(while (or (/= (caar dxf_obj) 42) (if (< i (fix par)) (setq i (1+ i))))
					(setq bulge (cdadr dxf_obj) dxf_obj (cdr dxf_obj))
				)
			)
			(T
				(setq e_next (entnext (cdar dxf_obj)))
				(repeat (fix par) (setq e_next (entnext e_next)))
				(setq bulge (cdr (assoc 42 (entget e_next))))
			)
		)
		(setq dxf_obj (entget (car obj)) pt_ref pt_snd)
		(if (zerop bulge)
			(setq lst_dxf
				(list
					(cons 0 "LINE")
					(cons 100 "AcDbEntity")
					(assoc 67 dxf_obj)
					(assoc 410 dxf_obj)
					(cons 8 (getvar "CLAYER"))
					(cons 100 "AcDbLine")
					(cons 10 (trans pt_first 1 0))
					(cons 11 (trans pt_snd 1 0))
					(assoc 210 dxf_obj)
				)
			)
			(setq
				dxf_210 (cdr (assoc 210 dxf_obj))
				pt_first (trans pt_first 1 dxf_210)
				pt_snd (trans pt_snd 1 dxf_210)
				rad (abs (/ (distance pt_first pt_snd) (sin (* 2.0 (atan bulge))) 2.0))
				p_cen
				(polar
					pt_first
					(if (> bulge 0.0)
						(+ (angle pt_first pt_snd) (- (/ pi 2.0) (* 2.0 (atan bulge))))
						(- (angle pt_first pt_snd) (+ (/ pi 2.0) (* 2.0 (atan bulge))))
					)
					rad
				)
				lst_dxf
				(list
					(cons 0 "ARC")
					(cons 100 "AcDbEntity")
					(assoc 67 dxf_obj)
					(assoc 410 dxf_obj)
					(cons 8 (getvar "CLAYER"))
					(cons 100 "AcDbCircle")
					(cons 10 p_cen)
					(cons 40 rad)
					(cons 100 "AcDbArc")
					(cons 50 (angle p_cen (if (> bulge 0.0) pt_first pt_snd)))
					(cons 51 (angle p_cen (if (> bulge 0.0) pt_snd pt_first)))
					(assoc 210 dxf_obj)
				)
			)
		)
		(foreach n '(6 39 48 62 370 420)
			(if (assoc n dxf_obj)
				(setq lst_dxf (append lst_dxf (list (assoc n dxf_obj))))
			)
		)
		(initget "Par _Through")
		(setvar "OFFSETDIST"
			(if (not (setq dis_offset (getdist (strcat "\nSpécifiez la distance de décalage ou [Par] <" (if (< (getvar "OFFSETDIST") 0) "Par" (rtos (getvar "OFFSETDIST"))) ">: "))))
				(progn (if (< (getvar "OFFSETDIST") 0) (setq dis_offset "Through")) (getvar "OFFSETDIST"))
				(if (eq dis_offset "Through") -1 dis_offset)
			)
		)
		(if (< (getvar "OFFSETDIST") 0)
			(princ "\nAttribuez une valeur à \"Par le point\": ")
			(princ "\nSpécifiez un point sur le côté à décaler: ")
		)
		(initget 9)
		(setq where_pt (getpoint))
		(entmake lst_dxf)
		(setq e_last (entlast))
		(if (< (getvar "OFFSETDIST") 0)
			(setvar "OFFSETDIST"
				(distance
					(vlax-curve-getClosestPointToProjection e_last
						(trans where_pt 1 0)
						(mapcar '- (trans (getvar "VIEWDIR") 1 0) (trans '(0 0 0) 1 0))
						T
					)
					(list (car (trans where_pt 1 0)) (cadr (trans where_pt 1 0)))
				)
			)
		)
		(if (eq "LINE" (cdr (assoc 0 lst_dxf)))
			(setq
				v1 (mapcar '- pt_ref pt_sel)
				v2 (mapcar '- (trans where_pt 1 0) pt_sel)
			)
			(setq
				v1 (mapcar '- (polar pt_sel (+ (angle pt_sel (trans p_cen dxf_210 0)) (/ pi 2)) rad) pt_sel)
				v2 (mapcar '- (trans where_pt 1 0) pt_sel)
			)
		)
		(setq det_or (apply '(lambda (x1 y1 z1 x2 y2 z2) (- (* x1 y2) (* y1 x2))) (append v1 v2)))
		(cond
			((> det_or 0.0) (setvar "OFFSETDIST" (abs (getvar "OFFSETDIST"))))
			((< det_or 0.0) (setvar "OFFSETDIST" (- (abs (getvar "OFFSETDIST")))))
		)
		(if
			(vl-catch-all-error-p
				(vl-catch-all-apply
					'vla-Offset
					(list (vlax-ename->vla-object e_last)
						(getvar "OFFSETDIST")
					)
				)
			)
			(princ "\nL'objet ne peut pas être décalé.")
			(setvar "OFFSETDIST" (if (eq dis_offset "Through") -1 (abs (getvar "OFFSETDIST"))))
		)
		(entdel e_last)
	)
	(T
		(princ "\nN'est pas une polyligne valable pour cette fonction!")
	)
)
(prin1)
)

[Edité le 24/4/2007 par bonuscad]

 

Application de la gestion d'erreur de Gilles, plus élégante que la mienne.

 

 

[Edité le 24/4/2007 par bonuscad]

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

Salut,

 

Et encore bravo, pour quelqu'un qui veut "passer la main"... ;)

 

Pour déterminer le côté de décalage des arcs, je suggèrerais de faire un test différent de celui des segments rectilignes.

Il suffirait de faire la différence entre : la distance entre le centre et le point retourné par grread et le rayon de l'arc.

 

(if (= "LINE" (cdr (assoc 0 lst_dxf)))
      (setq
 v1	(mapcar '- pt_ref pt_sel)
 v2	(mapcar '- (trans (cadr key) 1 0) pt_sel)
 det_or	(apply
	  '(lambda (x1 y1 z1 x2 y2 z2) (- (* x1 y2) (* y1 x2)))
	  (append v1 v2)
	)
      )
      (setq det_or (- (distance p_cen (trans (cadr key) 1 dxf_210)) rad))
    ) 

 

Je n'ai pas testé en profondeur, mais ça semble fonctionner.

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

Posté(e)

Merci Gilles de ta suggestion,

 

J'ai essayé, cela fonctionne bien dans des SCU parallèles au SCG, mais pas dans des SCU non parallèles.

J'ai donc gardé le même algorithme que pour un segment droit que j'ai simplement appliqué à la tangente au point de sélection, au lieu de l'appliquer à la corde comme précédemment.

 

Après des tests cela à l'aire de vouloir fonctionner correctement.

 

J'ai trouvé aussi le moyen d'appliquer le paramètre "Par le point" de la fonction décaler.

 

Le seul "Hic" qui reste est la gestion de l'erreur dans le cas d'un arc ou la valeur de décalage est plus grande que le rayon et que celui est décalé vers le centre.

 

J'aurais voulu savoir si une fonction comme (vl-catch.... pourrait m'aider à résoudre simplement cette gestion d'erreur lors de l'appel à (vla-Offset car je n'ai encore jamais utilisé cette fonction.

 

PS: J'ai mis à jour le code dans le 1er post

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

Salut,

 

 

Avec vl-catch-all-apply la routine continuera même si vla-offset génère une erreur, et vl-catch-all-error-p permet d'évaluer si vl-catch-all-apply en a généré une. On peut faire un truc du style :

 

si erreur => envoie un message, sinon => change OFFSETDIST, et la routine continue : (entdel e_last) ...

 

 

 

(if (vl-catch-all-error-p
   (vl-catch-all-apply
     'vla-Offset
     (list (vlax-ename->vla-object e_last)
	   (getvar "OFFSETDIST")
     )
   )
 )
      (princ "\nL'objet ne peut pas être décalé.")
      (setvar "OFFSETDIST"
       (if (eq dis_offset "Through")
	 -1
	 (abs (getvar "OFFSETDIST"))
       )
      )
    ) 

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

Posté(e)

OK

 

J'avais déjà modifié le code car j'avais trouvé une solution, mais il n'est pas impossible que j'adopte la méthode que tu m'as proposé, plus simple... ;)

 

Merci encore, je penses que le code est fiable maintenant.

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

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é