using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; using System; using UnityEngine.UI; public class Interpolateur : MonoBehaviour { // Pas d'échantillonnage public float pas = 1 / 100; // Conteneur des points cliqués public GameObject Donnees; // Les points (X,Y) cliqués private List X = new List(); private List Y = new List(); public enum EInterpolationType { Lagrange, Neville }; public EInterpolationType InterpolationType = EInterpolationType.Lagrange; public enum EParametrisationType { Reguliere, Distance, RacineDistance, Tchebytcheff, None } public EParametrisationType ParametrisationType = EParametrisationType.Reguliere; // Pour le dessin des courbes private List P2DRAW = new List(); // UI public Text text; ////////////////////////////////////////////////////////////////////////// // fonction : buildParametrisationReguliere // // semantique : construit la parametrisation reguliere et les // // échantillons de temps selon cette parametrisation // // params : // // - int nbElem : nombre d'elements de la parametrisation // // - float pas : pas d'échantillonage // // sortie : // // - List T : parametrisation reguliere // // - List tToEval : echantillon sur la parametrisation // ////////////////////////////////////////////////////////////////////////// (List, List) buildParametrisationReguliere(int nbElem, float pas) { // Vecteur des pas temporels List T = new List(); // Echantillonage des pas temporels List tToEval = new List(); // Construction des pas temporels for (int i = 0; i < nbElem; i++) { T.Add(i); } // Construction des échantillons for (float i = T.First(); i <= T.Last(); i += pas) { tToEval.Add(i); } return (T, tToEval); } ////////////////////////////////////////////////////////////////////////// // fonction : buildParametrisationDistance // // semantique : construit la parametrisation sur les distances et les // // échantillons de temps selon cette parametrisation // // params : // // - int nbElem : nombre d'elements de la parametrisation // // - float pas : pas d'échantillonage // // sortie : // // - List T : parametrisation distances // // - List tToEval : echantillon sur la parametrisation // ////////////////////////////////////////////////////////////////////////// (List, List) buildParametrisationDistance(int nbElem, float pas) { // Vecteur des pas temporels List T = new List(); // Echantillonage des pas temporels List tToEval = new List(); // Construction des pas temporels T.Add(0); for (int i = 0; i < X.Count - 1; i++) { float distance = (float)Math.Sqrt((Math.Pow(X[i + 1] - X[i], 2) + Math.Pow(Y[i + 1] - Y[i], 2))); T.Add(T.Last() + distance); } // Construction des échantillons for (float i = T.First(); i < T.Last(); i += pas) { tToEval.Add(i); } return (T, tToEval); } //////////////////////////////////////////////////////////////////////////// // fonction : buildParametrisationRacineDistance // // semantique : construit la parametrisation sur les racines des distances// // et les échantillons de temps selon cette parametrisation // // params : // // - int nbElem : nombre d'elements de la parametrisation // // - float pas : pas d'échantillonage // // sortie : // // - List T : parametrisation racines distances // // - List tToEval : echantillon sur la parametrisation // //////////////////////////////////////////////////////////////////////////// (List, List) buildParametrisationRacineDistance(int nbElem, float pas) { // Vecteur des pas temporels List T = new List(); // Echantillonage des pas temporels List tToEval = new List(); // Construction des pas temporels T.Add(0); for (int i = 0; i < X.Count - 1; i++) { float distance = (float)Math.Sqrt(Math.Sqrt((Math.Pow(X[i + 1] - X[i], 2) + Math.Pow(Y[i + 1] - Y[i], 2)))); T.Add(T.Last() + distance); } // Construction des échantillons for (float i = T.First(); i < T.Last(); i += pas) { tToEval.Add(i); } return (T, tToEval); } ////////////////////////////////////////////////////////////////////////// // fonction : buildParametrisationTchebycheff // // semantique : construit la parametrisation basée sur Tchebycheff // // et les échantillons de temps selon cette parametrisation// // params : // // - int nbElem : nombre d'elements de la parametrisation // // - float pas : pas d'échantillonage // // sortie : // // - List T : parametrisation Tchebycheff // // - List tToEval : echantillon sur la parametrisation // ////////////////////////////////////////////////////////////////////////// (List, List) buildParametrisationTchebycheff(int nbElem, float pas) { // Vecteur des pas temporels List T = new List(); // Echantillonage des pas temporels List tToEval = new List(); // Construction des pas temporels for (int i = 0; i < X.Count; i++) { float value = (float)Math.Cos((2 * i + 1) * Math.PI / (2 * (X.Count - 1) + 2)); T.Add(value); } // Construction des échantillons for (float i = T.First(); i > T.Last(); i -= pas) { tToEval.Add(i); } return (T, tToEval); } ////////////////////////////////////////////////////////////////////////// // fonction : applyLagrangeParametrisation // // semantique : applique la subdivion de Lagrange aux points (x,y) // // placés en paramètres en suivant les temps indiqués // // params : // // - List X : liste des abscisses des points // // - List Y : liste des ordonnées des points // // - List T : temps de la parametrisation // // - List tToEval : échantillon des temps sur T // // sortie : rien // ////////////////////////////////////////////////////////////////////////// void applyLagrangeParametrisation(List X, List Y, List T, List tToEval) { for (int i = 0; i < tToEval.Count; ++i) { // Calcul de xpoint et ypoint float t = tToEval[i]; float xpoint = lagrange(t, T, X); float ypoint = lagrange(t, T, Y); Vector3 pos = new Vector3(xpoint, 0.0f, ypoint); P2DRAW.Add(pos); } } ////////////////////////////////////////////////////////////////////////// // fonction : applyNevilleParametrisation // // semantique : applique la subdivion de Neville aux points (x,y) // // placés en paramètres en suivant les temps indiqués // // params : // // - List X : liste des abscisses des points // // - List Y : liste des ordonnées des points // // - List T : temps de la parametrisation // // - List tToEval : échantillon des temps sur T // // sortie : rien // ////////////////////////////////////////////////////////////////////////// void applyNevilleParametrisation(List X, List Y, List T, List tToEval) { for (int i = 0; i < tToEval.Count; ++i) { // Appliquer neville a l'echantillon i float t = tToEval[i]; Vector2 v = neville(X, Y, T, t); Vector3 pos = new Vector3(v[0], 0.0f, v[1]); P2DRAW.Add(pos); } } ////////////////////////////////////////////////////////////////////////// // fonction : lagrange // // semantique : calcule la valeur en x du polynome de Lagrange passant // // par les points de coordonnées (X,Y) // // params : // // - float x : point dont on cherche l'ordonnée // // - List X : liste des abscisses des points // // - List Y : liste des ordonnées des points // // sortie : valeur en x du polynome de Lagrange passant // // par les points de coordonnées (X,Y) // ////////////////////////////////////////////////////////////////////////// private float lagrange(float x, List X, List Y) { float sum = 0.0f; int n = X.Count; for (int j = 0; j < n; j++) { float prod = 1.0f; for (int i = 0; i < n; i++) { if (i != j) { prod *= (x - X[i]) / (X[j] - X[i]); } } sum += Y[j] * prod; } return sum; } ////////////////////////////////////////////////////////////////////////// // fonction : neville // // semantique : calcule le point atteint par la courbe en t sachant // // qu'elle passe par les (X,Y) en T // // params : // // - List X : liste des abscisses des points // // - List Y : liste des ordonnées des points // // - List T : liste des temps de la parametrisation // // - t : temps ou on cherche le point de la courbe // // sortie : point atteint en t de la courbe // ////////////////////////////////////////////////////////////////////////// private Vector2 neville(List X, List Y, List T, float t) { int n = X.Count; List nevX = new List(X); List nevY = new List(Y); for (int i = n - 1; i > 0; i--) { for (int j = 0; j < i; j++) { nevX[j] = (T[j + n - i] - t) / (T[j + n - i] - T[j]) * nevX[j] + (t - T[j]) / (T[j + n - i] - T[j]) * nevX[j + 1]; nevY[j] = (T[j + n - i] - t) / (T[j + n - i] - T[j]) * nevY[j] + (t - T[j]) / (T[j + n - i] - T[j]) * nevY[j + 1]; } } return new Vector2(nevX.First(), nevY.First()); } ////////////////////////////////////////////////////////////////////////// //////////////////////// NE PAS TOUCHER !!! ////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Update() { if (Input.GetKeyDown(KeyCode.Return)) { var ListePointsCliques = GameObject.Find("Donnees").GetComponent(); List T = new List(); List tToEval = new List(); if (ListePointsCliques.X.Count > 0) { X = ListePointsCliques.X; Y = ListePointsCliques.Y; if (InterpolationType == EInterpolationType.Lagrange) { switch (ParametrisationType) { case EParametrisationType.None: List x = new List(); List y = new List(); var xmax = 10.0f; var xcur = -10.0f; while (xcur < xmax) { xcur += pas; x.Add(xcur); } for (int i = 0; i < x.Count; i++) { y.Add(lagrange(x[i], X, Y)); } for (int i = 0; i < x.Count; ++i) { Vector3 pos = new Vector3(x[i], 0.0f, y[i]); P2DRAW.Add(pos); } break; case EParametrisationType.Reguliere: (T, tToEval) = buildParametrisationReguliere(X.Count, pas); applyLagrangeParametrisation(X, Y, T, tToEval); break; case EParametrisationType.Distance: (T, tToEval) = buildParametrisationDistance(X.Count, pas); applyLagrangeParametrisation(X, Y, T, tToEval); break; case EParametrisationType.RacineDistance: (T, tToEval) = buildParametrisationRacineDistance(X.Count, pas); applyLagrangeParametrisation(X, Y, T, tToEval); break; case EParametrisationType.Tchebytcheff: (T, tToEval) = buildParametrisationTchebycheff(X.Count, pas); applyLagrangeParametrisation(X, Y, T, tToEval); break; } } else if (InterpolationType == EInterpolationType.Neville) { switch (ParametrisationType) { case EParametrisationType.Reguliere: (T, tToEval) = buildParametrisationReguliere(X.Count, pas); applyNevilleParametrisation(X, Y, T, tToEval); break; case EParametrisationType.Distance: (T, tToEval) = buildParametrisationDistance(X.Count, pas); applyNevilleParametrisation(X, Y, T, tToEval); break; case EParametrisationType.RacineDistance: (T, tToEval) = buildParametrisationRacineDistance(X.Count, pas); applyNevilleParametrisation(X, Y, T, tToEval); break; case EParametrisationType.Tchebytcheff: (T, tToEval) = buildParametrisationTchebycheff(X.Count, pas); applyNevilleParametrisation(X, Y, T, tToEval); break; case EParametrisationType.None: text.text = "Vous devez choisir un type de parametrisation pour utiliser Neville"; break; } } } } } ////////////////////////////////////////////////////////////////////////// //////////////////////// NE PAS TOUCHER !!! ////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OnDrawGizmosSelected() { Gizmos.color = Color.blue; for (int i = 0; i < P2DRAW.Count - 1; ++i) { Gizmos.DrawLine(P2DRAW[i], P2DRAW[i + 1]); } } }