Aller au contenu

Dessiner une parabole


Invité cosinus85

Messages recommandés

Un code trouvé sur le net il y a pas mal de temps, j'ai juste traduit les messages.

 

; PARABEL.LSP Copyright (c) 1988, 1999 by Martin Vogel
;
; Zeichnet eine quadratische Parabel
;
; Wahlweise kann die Parabel durch drei Punkte bestimmt werden oder durch
; die Angabe von zwei Punkten und der Tangente im Startpunkt.
; Die Parabelgleichung wird im Textfenster von AutoCAD ausgegeben.


(Defun C:Parabole (/ p0 p02 p1 p12 pm xm ym pm2 t0 w a b c d n x dx tuwas)
 (SetVAR "CmdEcho" 0)
 (Initget 7)
 (Setq p0 (getpoint "\nPoint de départ: "))
 (SetQ x (Car p0))
 (Setq p1 (getpoint "\nPoint de fin: "))
 (Initget 7 "Tangente Hauteur _TAngent THickness")
 (Setq pm (getpoint "\nDéfinition par la [Tangente/Hauteur] ordinale "))
 (IF (eq pm "TAngent")
     (PROGN
       (Setq t0 (/ (sin (setq w (getangle p0 "\nDirection de la Tangente: ")))
                   (cos w)))
       (setq c (- (car p1) x))
       (setq a (/ (- (cadr p1) (* t0 c) (cadr p0)) (* c c)))
       (setq b (- t0 (* 2 a x)))
       (setq c (+ (cadr p0) (* a x x) (- (* t0 x)))))
     (PROGN
       (IF (eq pm "THickness")
             (setq pm (list (/ (+ x (car p1)) 2)
                            (+ (/ (+ (cadr p0) (cadr p1)) 2)
                               (getdist "Hauteur: ")))))
       (setq p02 (* x x))
       (setq pm2 (* (car pm) (car pm)))
       (setq p12 (* (car p1) (car p1)))
       (setq D
        (- (+ (* p02 (car pm)) (* x p12) (* pm2 (car p1)))
           (+ (* p12 (car pm)) (* (car p1) p02) (* pm2 x))))
        (setq a  (/ (- (+ (* (cadr p0) (car pm))
                          (* x (cadr p1))
                          (* (cadr pm) (car p1)))
                       (+ (* (cadr p1) (car pm))
                          (* (car p1) (cadr p0))
                          (* (cadr pm) x)))
                    D))
        (setq b  (/ (- (+ (* p02 (cadr pm))
                          (* (cadr p0) p12)
                          (* pm2 (cadr p1)))
                       (+ (* p12 (cadr pm))
                          (* (cadr p1) p02)
                          (* pm2 (cadr p0))))
                    D))
        (setq c  (/ (- (+ (* p02 (car pm) (cadr p1))
                          (* (car p0) (cadr pm) p12)
                          (* (cadr p0) pm2 (car p1)))
                       (+ (* p12 (car pm) (cadr p0))
                          (* (car p1) (cadr pm) p02)
                          (* (cadr p1) pm2 (car p0))))
                  D))))
 (Write-Line (StrCat "\nEquation de la Parabole: " (rtos a 2) "*x^2 + "
                     (rtos b 2) "*x + " (rtos c 2)))
 (InitGet 7)
 (Setq n (GetInt "\nNombre de segments: "))
 (setq dx (/ (- (car p1) x) n))
 (Setq tuwas '(Command "_.PLINE" p0))
 (Repeat n (SetQ tuwas
           (Append Tuwas
                   (List(List 'Quote
                              (List (SetQ x (+ x dx))
                                    (+ (* a x x) (* b x) c)))))))
 (SetQ Tuwas (Append Tuwas '("")))
 (Eval Tuwas)
 (Command "_.PEDIT" "_Last" "_Fit" "_exit")
 (princ)
)

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

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

J'avais fait un LISP il y a quelque temps pour dessiner une parabole., mais ça ne répond pas vraiment à la demande, puisque le dessin se base sur le sommet et le foyer spécifié. Le code implémente une méthode graphique.

 

;; PARABOLE (gile)
;; dessine une spline figurant une parabole en fonction du sommet et du foyer spécifié

(defun c:parabole (/ foyer sommet inc dir pt ray circle lst)
 (vl-load-com)
 (setq space (getspace))
 (initget 1)
 (setq	sommet (getpoint "\nSommet: "))
 (initget 1)
 (setq foyer (getpoint sommet "\nFoyer: ")
dist   (distance foyer sommet)
inc    (/ dist 100)
dir    (angle sommet foyer)
lst (cons sommet lst)
 )
 (repeat 50
   (setq ray
   (vla-addRay
     space
     (vlax-3d-point (setq pt (polar sommet dir inc)))
     (vlax-3d-point (polar pt (+ dir (/ pi 2)) 1.0))
   )
   )
   (setq circle (vla-addCircle
	   space
	   (vlax-3d-point foyer)
	   (+ dist inc)
	 )
   )
   (setq int  (vlax-invoke circle 'IntersectWith ray acExtendNone)
  lst (cons (list (car int) (cadr int) (caddr int)) lst)
  inc  (* 1.2 inc)
   )
   (vla-delete ray)
   (vla-delete circle)
 )
 (setq	vec (vec1 (cadr lst) (car lst))
lst (apply 'append (reverse (cdr lst))))
 (vla-mirror
   (vla-addSpline
     space
     (vlax-make-variant
(vlax-safearray-fill
  (vlax-make-safearray
    vlax-vbDouble
    (cons 0 (1- (length lst)))
  )
  lst
)
     )
     (vlax-3d-point (polar '(0 0 0) (+ dir (/ pi 2)) 1.0))
     (vlax-3d-point vec)
   )
   (vlax-3d-point sommet)
   (vlax-3d-point foyer)
 )
 (princ)
)

;; VEC1
;; Retourne le vecteur normé (1 unité) de sens p1 p2
;;
;; Arguments : deux points

(defun vec1 (p1 p2)
 ((lambda (d)
    (if (not (zerop d))
      (mapcar (function (lambda (x1 x2) (/ (- x2 x1) d))) p1 p2)
    )
  )
   (distance p1 p2)
 )
)

 

J'en ai donc écrit un autre qui s'appuie sur une équation du type : y = ax² + bx + c.

Ça ressemble un peu à ce que j'ai vu de la routine VBA proposée par jeff66.

 

;; PARAB (gile)
;; Dessine une spline figurant une parabole dont l'axe est parallèle à l'axe Y
;; L'utilisateur saisit, dans un boite de dialogue, les paramètre définissant la courbe :
;; - valeurs a, b et c de l'équation ax² + bx + c (accepte les fractions)
;; - largeur maximale entre les branches de la courbe
;; - nombre de points de lissages de la spline
;; - possibilité de placer un point sur le foyer
;; - possibilité de dessiner la directrice

(defun c:parab (/ *error* action tmp file id stat a b c w n f d)

 ;; Redefinition de *error*
 (defun *error* (msg)
   (and msg
 (/= msg "Fonction annulée")
 (princ (strcat "\nErreur: " msg))
   )
   (and dz (setvar 'dimzin dz))
   (princ)
 )

 ;; Action pour les clés "b" et "c"
 (defun action	(key value)
   (or	(set (read key) (distof value))
(or
  (alert "Nécessite un nombre ou une fraction valide")
  (mode_tile key 2)
  (and
    (set (read key) 0.)
    (done_dialog 2)
  )
)
   )
 )

 ;; Boite de dialogue
 (setq	tmp  (vl-filename-mktemp "tmp.dcl")
file (open tmp "w")
 )
 (write-line
   "parab:dialog{
      label=\"Parabole\";
      initial_focus=\"a\";
      width = 32;
      :text{label=\"Equation de la courbe : y = ax² + bx + c\";}
      :row{
        :edit_box{label=\"a :\";key=\"a\";edit_width=6;allow_accept= true;}
        :edit_box{label=\"b :\";key=\"b\";edit_width=6;allow_accept= true;}
        :edit_box{label=\"c :\";key=\"c\";edit_width=6;allow_accept= true;}
      }
      :edit_box{label=\"Largeur maximum :\";key=\"w\";edit_width=6;allow_accept= true;}
      :edit_box{label=\"Nombre de points de lissage :\";key=\"n\";edit_width=6;allow_accept= true;}
      :toggle{label=\"Foyer\";key=\"f\";}
      :toggle{label=\"Directrice\";key=\"d\";}
      spacer;
      ok_cancel;
    }"
   file
 )
 (close file)
 (setq	a    1.
b    0.
c    0.
w    5.
n    41
f "0"
d "0"
stat 2
dz   (getvar 'dimzin)
 )
 (  (while (    (if	(new_dialog "parab" id)
     (progn
(setvar 'dimzin 8)
(foreach k '("a" "b" "c" "w")
  (set_tile k (rtos (eval (read k)) 2 16))
)
(set_tile "n" (itoa n))
(foreach k '("f" "d")
  (set_tile k (eval (read k)))
)
(action_tile
  "a"
  "(or
    (and
      (setq a (distof $value))
      (/= a 0)
    )
    (or
      (alert \"Nécessite un nombre différent de 0 ou une fraction valide\")
      (mode_tile $key 2)
      (and
	(setq a 1.)
	(done_dialog 2)
      )
    )
  )"
)
(foreach k '("b" "c")
  (action_tile k "(action $key $value)")
)
(action_tile
  "w"
  "(or (and
	(setq w (distof $value))
	(	      )
      (or
	(alert \"Nécessite un nombre strictement positif\")
	(mode_tile $key 2)
	(and
	  (setq w 5.)
	  (done_dialog 2)
	)
      )
  )"
)
(action_tile
  "n"
  "(if (	    (progn
      (alert \"Nécessite un entier supérieur a 2\")
      (mode_tile $key 2)
      (setq n 41)
      (done_dialog 2)
    )
    (setq n (atoi $value))
  )"
)
(foreach k '("f" "d")
  (action_tile k "(set (read $key) $value)")
)
(action_tile "accept" "(done_dialog 1)")
(action_tile "cancel" "(done_dialog 0)")
(setq stat (start_dialog))
     )
   )
 )
 (unload_dialog id)
 (vl-file-delete tmp)
 (if (= stat 1)
   (gc:parabola a b c w n (= "1" f) (= "1" d))
 )
 (*error* nil)
)

;; gc:parabola
;; Dessine une spline figurant une parabole
;; La courbe est symétrique par rapport à son axe parallèle à l'axe Y
;; elle représente la courbe définie par une équation du type : ax² + bx + x
;;
;; Arguments :
;; a, b, c : paramètres de l'équation
;; w       : largeur maximale entre les branches
;; n       : nombre de points de lissage, si le nombre spécifié est pair,
;;           un point de lissage est automatiquement ajouté au sommet
;; f       : si non nil, dessine un point sur le foyer
;; d       : si non nil, dessine une ligne sur la directrice
(defun gc:parabola (a b	c w n s d /
	      ;;_ Variables :
	      foo ;_ fonction
	      x0 ;_ coordonnée x du sommet de la parabole
	      sum ;_  sommet de la parabole
	      ang ;_ angle incrémenté
	      inc ;_ incrément
	      lst ;_ liste des points de lissage
)
 
 ;; Retourne la coordonnée Y en fonction de la coordonnée X
 (defun foo (x) (+ (* a x x) (* b x) c))
 
 (setq	x0 (- (/ (float b) (* 2 a)))
sum  (list x0 (foo x0) 0.)
ang  (/ (* pi 5) 3)
inc  (/ pi (* 6 (/ n 2)))
 )
 (repeat (if (zerop (rem n 2))
    (1+ n)
    n
  )
   (setq lst (cons (list (setq x (+ x0 (* w (cos ang)))) (foo x) 0.) lst)
  ang (- ang inc)
   )
 )
 (entmake
   (append
     (list
'(0 . "SPLINE")
'(100 . "AcDbEntity")
'(100 . "AcDbSpline")
'(71 . 3)
     )
     (mapcar '(lambda (p) (cons 11 p)) lst)
   )
 )

 (if s
 (entmake
   (list
     '(0 . "POINT")
     (cons 10 (mapcar '+ sum (list 0. (/ 1 (* 4 a)) 0.)))
     )
   )
   )

 (if d
 (entmake
   (list
     '(0 . "LINE")
     (cons 10 (mapcar '+ sum (list (/ w -2.) (/ -1 (* 4 a)) 0.)))
     (cons 11 (mapcar '+ sum (list (/ w 2.) (/ -1 (* 4 a)) 0.)))
     )
   )
   )
)

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é