Est-ce une implémentation raisonnable de la fonction quadratique de Bézier dans OCaml?

StackOverflow https://stackoverflow.com/questions/145056

  •  02-07-2019
  •  | 
  •  

Question

Un ami est tombé sur une fonction de courbe de Bézier quadratique dans sa base de code qui utilisait un gigantesque nid de rats d’une table de commutation pour effectuer le calcul. Il m'a mis au défi de trouver une seule expression courte qui lui permettrait de remplacer le gigantesque bloc de code.

En essayant de satisfaire deux curiosités différentes, j’ai pensé essayer d’implémenter la fonction dans OCaml. Je suis un très novice programmeur OCaml et je ne connais pas non plus la fonction. Cette implémentation spécifique est difficile à obtenir via Google.

Les critiques sur les performances / exactitude de la fonction ainsi que sur son implémentation sont très appréciées.

Mise en œuvre de Courbe de Bézier quadratique :

let rec b2 n =
let p1 = -10. in
let p2 = 10. in
let q = n*.n in
let rec b2i n i hd =
  if i > n then
    List.rev hd
  else
    let t = i /. n in
  b2i n (i+.1.) ((((1.-.t)**2.)*.p1+.(2.*.t*.(1.-.t)*.q)+.(t**2.)*.p2) :: hd)
in b2i n 0. []
;;
let floatprint lst = List.iter (fun f -> Printf.printf "%f; " f) lst ;;
floatprint (b2 8.);;
Était-ce utile?

La solution

b2 n'est pas récursif, vous n'avez donc pas besoin de [laisser rec b2 n =]. Puisque n ne change jamais, pas besoin de l'avoir comme argument pour b2i, utilisez simplement n depuis la portée englobante. Votre fonction interne devrait dépendre de p0, p1 et p2, mais je la vois dépendre de -10., N ** 2 et 10. La fonction a également la forme d'une carte de [0.0; 1,0; 2,0; ...; n.0] aux valeurs finales. Pourriez-vous l'écrire:

let b i = 
  let t = i /. n in
  let tminus = (1.-.t) in
  (tminus *. tminus *. p0) +. (2. *. t *. tminus *. p1) +. (t *. t * p2)
in
List.map b ([generate list 1.0; 2.0; ... n.0])

Une fonction permettant de générer la liste 1.0 ... n.0 pourrait être: (pour le petit n)

let rec count m n = if m > n then [] else m :: (count (m+.1.) n)

Autres conseils

J'ai deux suggestions:

Vous devriez appeler List.rev après le retour de b2i afin qu'ocaml puisse exploiter ses optimisations en fonction de la récursion finale. Cependant, je ne suis pas sûr que ocaml gère bien la mise en œuvre actuelle. List.rev est cependant récursif. Vous remarquerez que, dans ce message , cela se fait comme ça.

Vous pouvez également faire de la résolution de l'itération un argument optionnel tel que ? (epsilon = 0.1) .

En tant que programmeur, je ne vois pas grand chose de mal à part cela - tant que P1 et P2 sont en fait des constantes. Compilez-le et voyez la différence d'assemblage entre le déplacement de List.rev à l'intérieur ou à l'extérieur de la récursion finale.

C'est peut-être une bonne idée, mais hd n'est pas un bon nom pour un paramètre de liste. List.hd est une fonction standard qui renvoie le premier élément d'une liste. L'utilisation de hd comme nom d'une liste entraînera de la confusion.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top