Aller au contenu

Polylignes 3D avec des arcs


(gile)

Messages recommandés

Ça avait commencé ici.

 

J'ai essayé d'aboutir un peu mieux une routine qui permet de dessiner des polylignes 3D avec des arcs.

 

Les arcs sont en fait une successions de segments droits dont le nombre par arc est défini par l'utilisateur au lancement de la routine. Le nombre d'arc par défaut est mémorisé dans le dessin.

 

Les coordonnées des sommets sont calculées en fonction de l'arc plan projeté sur le plan XY du SCU courant, cet arc est déterminé par ses points de départ et de fin et sa tangente au départ. Par défaut l'arc est tangent au segment précédent (comme pour une polyligne) l'utilisateur peut spécifier une autre direction (comme l'option direction des polylignes).

 

L'altitude de chaque sommet est calculé par interpolation linéaire en fonction de l'altitude des polints de départ et de fin (les sommets s'inscrivent sur un arc hécoïdal).

 

La polyligne n'est créée qu'après validation (Entrée, Espace ou clic droit), pendant sa construction elle est affichée en "surbrillance", il est possible d'annUler une ou plusieurs opérations.

 

Taper 3dpolyarc pour lancer la commande et suivre les indications de la ligne de commande.

 

En images :

en gris une polyligne 2D sélectionnée figure la projection de la polyligne 3D qui va passer par les extrémités des lignes verticales.

 

http://img479.imageshack.us/img479/2445/poly3d1fq9.png

http://img19.imageshack.us/img19/4493/poly3d2cc5.png

http://img265.imageshack.us/img265/8070/poly3d3lg5.png

 

le code :

 

;;; 3dPolyArc -Gilles Chanteau- 29/04/07
;;; Crée une polyligne 3D.
;;; En option "Arc" les sommets s'inscrivent sur une hélicoïde,
;;; - leur altitude est calculée par interpolation linéaire en fonction
;;; de l'altitude des points de départ et de fin.
;;; - la courbure est celle de l'arc défini par la projection de ces points
;;; sur le plan XY du SCU courant et la tangente au départ de l'arc
;;; (tangent au dernier segment ou à la direction spécifiée).

(defun c:3dPolyArc (/		3dPolyArc_err	    drawvecs
	      segmentundo	  AcDoc	    ModSp     prec
	      p1	p2	  tg	    opt	      plst tglst
	      cnt
	     )
 (vl-load-com)

 ;;***********************************************************;;

 (defun 3dPolyArc_err (msg)
   (if	(= msg "Fonction annulée")
     (princ)
     (princ (strcat "\nErreur: " msg))
   )
   (redraw)
   (vla-EndUndoMark AcDoc)
   (setq *error* m:err
  m:err	nil
   )
   (princ)
 )

 ;;***********************************************************;;

 (defun drawvecs (lst)
   (setq p1 (last lst))
   (redraw)
   (if	(      (grvecs (apply 'append
	     (mapcar '(lambda (x1 x2)
			(list -255 x1 x2)
		      )
		     (reverse (cdr (reverse lst)))
		     (cdr lst)
	     )
      )
     )
   )
 )

 ;;***********************************************************;;

 (defun segmentundo ()
   (if	(      (prompt "\nTous les segments ont déjà été annulés.")
     (setq plst  (sublst plst 1 (- (length plst) (car cnt)))
    tglst (cdr tglst)
    cnt	  (cdr cnt)
     )
   )
 )

 (setq	AcDoc	(vla-get-ActiveDocument (vlax-get-acad-object))
ModSp	(vla-get-ModelSpace AcDoc)
m:err	*error*
*error*	3dPolyArc_err
 )
 (vla-StartUndoMark AcDoc)
 (if (not (vlax-ldata-get "interpoly3d" "prec"))
   (vlax-ldata-put "interpoly3d" "prec" 20)
 )
 (prompt
   (strcat "\nParamètre courant - Nombre de segments par arc: "
    (itoa (vlax-ldata-get "interpoly3d" "prec"))
   )
 )
 (while (not (vl-consp p1))
   (initget 1 "Segments")
   (setq
     p1
      (getpoint
 "\nSpécifiez le point de départ de la polyligne ou [segments]: "
      )
   )
   (if	(= p1 "Segments")
     (progn
(initget 6)
(if (setq prec
	   (getint
	     (strcat "\nSpécifiez le nombre de segments pour les arcs 			     (itoa (vlax-ldata-get "interpoly3d" "prec"))
		     ">: "
	     )
	   )
    )
  (vlax-ldata-put "interpoly3d" "prec" prec)
)
     )
   )
 )
 (setq	prec  (vlax-ldata-get "interpoly3d" "prec")
plst   (cons p1 plst)
cnt   (cons 1 cnt)
loop1 T
 )
 (while loop1
   (initget "Arc annUler")
   (setq
     p1 (last plst)
     p2 (getpoint
   p1
   "\nSpécifiez l'extrémité de la ligne ou [Arc/annUler]: "
 )
   )
   (if	p2
     (progn
(if (= p2 "annUler")
  (segmentundo)
  (if (= p2 "Arc")
    (progn
      (if (null tglst)
	(progn
	  (initget 1)
	  (setq	tglst
		 (cons
		   (getorient
		     p1
		     "\nSpécifiez la direction de la tangente pour le point de départ de l'arc: "
		   )
		   tglst
		 )
	  )
	)
      )
      (setq loop2 T)
      (while loop2
	(setq p2 p1)
	(while (equal p1 p2 1e-9)
	  (initget "Direction Ligne annUler")
	  (setq	p2
		 (getpoint
		   p1
		   "\nSpécifiez l'extrémité de l'arc ou [Direction/Ligne/annUler]: "
		 )
	  )
	)
	(if p2
	  (if (= p2 "Ligne")
	    (setq loop2 nil)
	    (if	(= p2 "annUler")
	      (progn
		(segmentundo)
		(drawvecs plst)
	      )
	      (if (= p2 "Direction")
		(progn
		  (initget 1)
		  (setq	tglst
			 (cons
			   (getorient
			     p1
			     "\nSpécifiez la direction de la tangente pour le point de départ de l'arc: "
			   )
			   tglst
			 )
		  )
		)
		(progn
		  (setq	new  (interpol (last plst)
				       p2
				       (car tglst)
				       prec
			     )
			plst (append plst new)
			cnt  (cons (length new) cnt)
		  )
		  (drawvecs plst)
		)
	      )
	    )
	  )
	  (setq	loop2 nil
		loop1 nil
	  )
	)
      )
    )
    (setq plst (append plst (list p2))
	  tglst (cons (angle p1 p2) tglst)
	  cnt (cons 1 cnt)
    )
  )
)
(drawvecs plst)
     )
     (setq loop1 nil)
   )
 )
 (if (    (vlax-invoke
     ModSp
     'add3dPoly
     (apply 'append (mapcar '(lambda (p) (trans p 1 0)) plst))
   )
 )
 (redraw)
 (vla-EndUndoMark AcDoc)
 (setq	*error*	m:err
m:err nil
 )
 (princ)
)

(defun interpol	(pt1   pt2   tg	   prec	 /     alt1  alt2  p1	 p2
	 mid   cen   rad   ang	 i_ang i_alt n	   p_int ptlst
	)
 (setq	alt1 (caddr pt1)
alt2 (caddr pt2)
 )
 (mapcar '(lambda (p pt) (set p (list (car pt) (cadr pt) 0.0)))
  '(p1 p2)
  (list pt1 pt2)
 )
 (setq	mid (mapcar '(lambda (x1 x2) (/ (+ x1 x2) 2)) p1 p2))
 (if (setq cen	(inters	p1
		(polar p1 (+ tg (/ pi 2)) 1.0)
		mid
		(polar mid (+ (angle p1 p2) (/ pi 2)) 1.0)
		nil
	)
     )
   (progn
     (setq rad	(distance cen p1)
    ang	(ang      )
     (if (	(setq ang (- ang (* 2 pi)))
     )
     (setq i_ang (/ ang prec)
    i_alt (/ (- alt1 alt2) prec)
    n	  0
     )
     (repeat prec
(setq p_int (polar cen (- (angle cen p2) (* i_ang n)) rad)
      p_int (list (car p_int) (cadr p_int) (+ alt2 (* i_alt n)))
      ptlst (cons p_int ptlst)
      n	    (1+ n)
)
     )
     (setq tglst (cons (+ tg ang) tglst))
   )
   (setq ptlst	(list pt2)
  tglst	(cons (+ tg (angle p1 p2)) tglst)
   )
 )
 ptlst
)

;;; Ang
(defun ang  (if (and (    ang
   (ang  )
)

;;; SUBLST Retourne une sous-liste
;;; Premier élément : 1
;;; (sublst '(1 2 3 4 5 6) 3 2) -> (3 4)
;;; (sublst '(1 2 3 4 5 6) 3 nil) -> (3 4 5 6)

(defun sublst (lst start leng / rslt)
 (if (not (    (setq leng (- (length lst) (1- start)))
 )
 (repeat leng
   (setq rslt	(cons (nth (1- start) lst) rslt)
  start	(1+ start)
   )
 )
 (reverse rslt)
) 

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

Lien vers le commentaire
Partager sur d’autres sites

Hello (gile)

 

Un seul mot : BRAVO :) :D :cool:

 

Il y a un truc qui m'énerve ENORMEMENT chez Autodesk :

Ils conçoivent des améliorations en 2D et 2D dans le noyau d'AutoCAD, et donc

 

- Pourquoi n'ont ils jamais prévu de faire des ARCs en 3D ?

 

- Pouquoi les objets 3D ont toujours le type de ligne CONTINUOUS ?

 

Je ne sais plus quand les 3DPOLY sont apparues ?!

Vu de loin je pense que c'est avec AutoCAD R11 ... :exclam:

 

Le Decapode

 

 

 

[Edité le 30/4/2007 par lecrabe]

Autodesk Expert Elite Team

Lien vers le commentaire
Partager sur d’autres sites

Salut,

Personnellement, pour réaliser des polignes 3D avec arc, j'utilisais le lissage (mais les courbes sont réalisées tangeantes au sommets...donc on les perdait (les sommets) !.. et il fallait les "retravailler" ensuite....)

encore merci (gile) !

http://xs114.xs.to/xs114/07181/poly3d1.JPG

 

http://xs114.xs.to/xs114/07181/poly3d2.JPG

Si vous êtes persuadés de tout savoir sur un sujet, c''est que vous en ignorez quelque chose...

Lien vers le commentaire
Partager sur d’autres sites

Bonjour,

 

En fait, ce n'est pas une réponse, mais une question.

Le fait d'obtenir une polyligne 3d est-il plus intéressant qu 'un spline.

C' est en fait ce que j' utilise (la spline) pour récupérer en vba la ligne de chant supérieur des limons courbe balancées..

 

Cordialement

 

 

Lien vers le commentaire
Partager sur d’autres sites

D'abord merci pour les compliments, mais n'allez pas trop vite, essayez la fonction qui est loin d'être parfaite.

 

Faire l'équivalent des "arcs" avec les poly 3d est une gageure et oblige à quelques choix arbitraires concernant la figure résultante.

J'avais fait ici une version assez proche dont les parties en "arcs" s'inscrivent sur un arc de cercle plan défini par 3 points (3 points sur l'arc ou les extrémités et le centre).

 

Le choix ici, est d'avoir des arcs de cercles en projection sur plan XY en s'appuyant sur la tangente à l'extémité du point suivant, il est tout aussi arbitraire que le précédent et les deux sont autant "valables". En l'état, le calcul de l'altitudes des sommets des segments figurant les arcs se faisant par interpolation linéaire entre les deux extrémités il peut y avoir des "ruptures de pente" entre les arcs.

 

nazemrap,

ni le LISP donné ici, ni celui donné dans le lien ne font des polylignes 3D semblables à une spline, ils essayent juste d'imiter les polylignes 2D. Les splines sont des courbes issus de calculs beaucoup plus complexes. Un des intérêts des polylignes 3D était surtout évident avant la version 2007 où c'était le seul objet non-plan pouvant servir de chemin d'extrusion.

 

Si on veut faie des poly 3d comme des splines on peut utiliser : 3dPolySpline, qui par un habile artifice crée une poly 3d de la même façon qu'on fait une spline.

 

(defun c:3dpolyspline
      (/ pt nb spl fpts len1 len2 lseg cnt plst n cl poly)

 (vl-load-com)

 (or (vlax-ldata-get "3dPolySpline" "n")
     (vlax-ldata-put "3dPolySpline" "n" 20)
 )
 (setvar "cmdecho" 0)
 (prompt
   (strcat
     "\nParamètre courant - Nombre de segments entre chaque point de lissage: "
     (itoa (vlax-ldata-get "3dPolySpline" "n"))
   )
 )
 (while (not (and (setq pt
		  (getpoint "\nSpécifiez le premier point ou : ")
	   )
	   (listp pt)
      )
 )
   (initget 7)
   (setq
     nb
      (getint
 (strcat
   "\nSpécifiez le nombre de segments entre chaque point de lissage: "
 )
      )
   )
   (vlax-ldata-put "3dPolySpline" "n" nb)
 )
 (setq nb (vlax-ldata-get "3dPolySpline" "n"))
 (command "_.spline" pt)
 (setvar "cmdecho" 1)
 (while (/= 0 (getvar "CMDACTIVE"))
   (command pause)
 )
 (setq spl (vlax-ename->vla-object (entlast)))
 (setq fpts (3d-coord->pt-lst (vlax-get spl 'Fitpoints)))
 (setq
   len1 (vlax-curve-getDistAtParam spl (vlax-curve-getEndParam spl))
 )
 (repeat (setq n (1- (length fpts)))
   (setq len2 (vlax-curve-getDistAtPoint spl (nth (1- n) fpts))
  lseg (/ (- len1 len2) nb)
  cnt  0
   )
   (repeat nb
     (setq plst (cons
	   (vlax-curve-getPointAtDist spl (- len1 (* cnt lseg)))
	   plst
	 )
    cnt	 (1+ cnt)
     )
   )
   (setq n    (1- n)
  len1 len2
   )
 )
 (setq plst (cons (car fpts) plst))
 (if (= (vla-get-Closed spl) :vlax-true)
   (setq plst (reverse (cdr (reverse plst)))
  cl   T
   )
 )
 (setq	poly
 (vlax-invoke
   (vla-get-modelSpace
     (vla-get-ActiveDocument (vlax-get-acad-object))
   )
   'add3dPoly
   (apply 'append plst)
 )
 )
 (and cl (vla-put-Closed poly :vlax-true))
 (vla-delete spl)
 (princ)
) 

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

Lien vers le commentaire
Partager sur d’autres sites

Un exemple en images sera sûrment plus parlant que mes confuses explications.

 

4 vues,Droite et Face en haut ; Isometrie SE et Dessus en bas :

 

avec 3dPolyArc, en partant du niveau 0, un premier segment droit et deux autres en arc comme la poly 2d (en gris)

 

http://img409.imageshack.us/img409/2982/3dpolyarcab0.png

 

avec 3dPolySpline

 

http://img296.imageshack.us/img296/6577/3dpolysplinerv6.png

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é