PavIn
Pavage et Interpolation barycentrique
Paving.hpp
Aller à la documentation de ce fichier.
1 
12 #ifndef PAVING_H
13 #define PAVING_H
14 #include "Paving_config.hpp"
15 #include <Grapic.h>
16 #include <utility>
17 #include <iostream>
18 #include <fstream>
19 #include <vector>
20 #include <cassert>
21 #include <cmath>
22 #include <algorithm>
23 #include <ctime>
24 
33 
34 
36 
40 template<int N>
41 class Point final : private std::vector<TYPECOORD> {
42 public:
43  using std::vector<TYPECOORD>::begin;
44  using std::vector<TYPECOORD>::end;
45  using std::vector<TYPECOORD>::push_back;
46  using std::vector<TYPECOORD>::size;
47  using std::vector<TYPECOORD>::clear;
48  using std::vector<TYPECOORD>::operator[];
49 
50 
52  Point();
53 
55  Point(const Point<N>&);
56 
57  // Constructeur par transfert
58  //Point(Point<N> &&);
59 
61  Point(const TYPEVAL&);
62 
64  Point(const std::vector<TYPECOORD>&);
65 
67  Point(const std::vector<TYPECOORD>&, const TYPEVAL&);
68 
70  ~Point();
71 
73  inline TYPEVAL value() const {
74  return this->val;
75  }
76 
78  inline void setValue(const TYPEVAL &v) {
79  this->val = v;
80  }
81 
83 
88  static double getDistance(const Point<N>&, const Point<N>&);
89 
91 
96  Point<N> getMiddle(const Point<N>&, const Point<N>&) const;
97 
99 
106  static long double getDeterminant(const std::vector<Point<N>>&);
107 
109  friend std::ostream& operator<<(std::ostream& os, const Point<N>& p) {
110  if(p.size()==0) {
111  os << "Empty point (" << p.value() << ")";
112  } else {
113  os << "(";
114  for(unsigned int i = 0; i < N; i++) {
115  os << p.at(i);
116  if(i != p.size()-1) os << ", ";
117  }
118  os << ")";
119  if(p.value() != 0) os << " [" << p.value() << "]";
120  }
121  return os;
122  }
123 
125  friend inline bool operator==(const Point<N>& x, const Point<N>& y) {
126  for(int ii=0; ii<N; ii++) {
127  if(x[ii]!=y[ii])
128  return false;
129  }
130  return true;
131  }
132 
134  friend inline bool operator!=(const Point<N>& x, const Point<N>& y) {
135  return !(x==y);
136  }
137 
139  friend inline Point<N> operator+(const Point<N>& x, const Point<N>& y) {
140  Point<N> res;
141  for(int ii=0; ii<N; ii++) {
142  res.push_back(x[ii]+y[ii]);
143  }
144  return res;
145  }
146 
148  friend inline Point<N> operator-(const Point<N>& x, const Point<N>& y) {
149  Point<N> res;
150  for(int ii=0; ii<N; ii++) {
151  res.push_back(x[ii]-y[ii]);
152  }
153  return res;
154  }
155 
156 
157 private:
158  TYPEVAL val;
159 
160 
162 
169  long double getDeterminant_rec(const std::vector<std::vector<TYPECOORD>>&) const;
170 };
171 
173 
174 // Constructeur par défaut
175 template<int N>
176 Point<N>::Point() : std::vector<TYPECOORD>(), val(0) {
177 }
178 
179 // Constructeur par copie
180 template<int N>
181 Point<N>::Point(const Point<N> &p) : std::vector<TYPECOORD>() {
182  if(p.size() != N) {
183  std::cerr << "\033[31mERROR\033[0m : Copying Point : Point size (" << p.size() << ") does not correspond to template parameter Point<" << N << ">" << std::endl;
184  return;
185  }
186  for(auto elm : p) {
187  this->push_back(elm);
188  }
189  this->val = p.value();
190 }
191 
192 // Constructeur par transfert
193 /*
194 template<int N>
195 Point<N>::Point(Point<N> &&p) {
196  std::cerr << "\033[31mERROR\033[0m : Transfering Point : Point size (" << p.size() << ") does not correspond to template parameter Point<" << N << ">" << std::endl;
197 
198 }*/
199 
200 // Constructeur par valeur
201 template<int N>
202 Point<N>::Point(const TYPEVAL &v) : std::vector<TYPECOORD>(), val(v) {
203 }
204 
205 // Constructeur par conversion de vector
206 template<int N>
207 Point<N>::Point(const std::vector<TYPECOORD> &v) : std::vector<TYPECOORD>(), val(0) {
208  if(v.size() != N) {
209  std::cerr << "\033[31mERROR\033[0m : Making Point : Vector size (" << v.size() << ") does not correspond to template parameter Point<" << N << ">" << std::endl;
210  return;
211  }
212  for(unsigned int ii=0; ii < v.size(); ii++) {
213  this->push_back(v[ii]);
214  }
215  this->val = 0;
216 }
217 
218 // Constructeur par conversion de vector et valeur
219 template<int N>
220 Point<N>::Point(const std::vector<TYPECOORD> &v, const TYPEVAL &value) : std::vector<TYPECOORD>() {
221  std::cout << "Construit Point vector dim " << N << std::endl;
222  if(v.size() != N) {
223  std::cerr << "\033[31mERROR\033[0m : Making Point : Vector size (" << v.size() << ") does not correspond to template parameter Point<" << N << ">" << std::endl;
224  return;
225  }
226  for(auto ii : v) {
227  this->push_back(ii);
228  }
229  this->val = value;
230 }
231 
232 // Destructeur
233 template<int N>
235 }
236 
237 // Calcule la distance entre deux points de même dimension
238 template<int N>
239 double Point<N>::getDistance(const Point<N> &a, const Point<N> &b) {
240  double res=0;
241  if(a.size() != b.size())
242  return -1;
243  for(unsigned int ii=0; ii<a.size(); ii++) {
244  res+=(a[ii]-b[ii])*(a[ii]-b[ii]);
245  }
246  return sqrt(res);
247 }
248 
249 // Calcule le milieu
250 template<int N>
251 Point<N> Point<N>::getMiddle(const Point<N> &a, const Point<N> &b) const {
252  Point<N> res;
253  if(a.size() != b.size())
254  return res;
255  for(unsigned int ii=0; ii<a.size(); ii++) {
256  res.push_back((a[ii]+b[ii])/2);
257  }
258  return res;
259 }
260 
261 // Calcule le determinant entre deux points de même dimension
262 template<int N>
263 long double Point<N>::getDeterminant(const std::vector<Point<N>> &pts) {
264  std::vector<std::vector<TYPECOORD>> v_pts;
265  for(auto p: pts) {
266  v_pts.push_back(p);
267  }
268  return pts[0].getDeterminant_rec(v_pts);
269 }
270 
271 // Methode récursive du calcul de determinants
272 template<int N>
273 long double Point<N>::getDeterminant_rec(const std::vector<std::vector<TYPECOORD>> &pts) const {
274  if(pts.size() == 2) { // Si dimension 2 retourne le produit
275  return pts[0][0]*pts[1][1]-pts[1][0]*pts[0][1];
276  } else { // Sinon decoupe la matrice avec ses mineurs
277  int sign=-1;
278  double tmpRes = 0;
279  for(unsigned int ii=0; ii<pts.size(); ii++) {
280  sign*=-1; //Le signe change a chaque itération
281  std::vector<std::vector<TYPECOORD>> matrix_minor(pts);
282  matrix_minor.erase(matrix_minor.begin());
283  for(unsigned int jj=0; jj<pts.size()-1; jj++) {
284  matrix_minor[jj].erase(matrix_minor[jj].begin()+ii);
285  }
286  tmpRes += sign*pts[0][ii]*Point<N>::getDeterminant_rec(matrix_minor);
287  }
288  return tmpRes;
289  }
290 }
291 
300 
301 
303 
307 template<int N>
308 class Simplex final : private std::vector<Point<N>> {
309 
310 public:
311  using std::vector<Point<N>>::begin;
312  using std::vector<Point<N>>::end;
313  using std::vector<Point<N>>::push_back;
314  using std::vector<Point<N>>::size;
315  using std::vector<Point<N>>::clear;
316  using std::vector<Point<N>>::operator[];
317 
319  Simplex();
320 
322 
325  Simplex(const std::vector<Point<N>>&);
326 
328 
331  Simplex(const int &);
332 
334 
338  Simplex(const int &, const std::vector<Point<N>>&);
339 
341  ~Simplex();
342 
343 
345  inline int getIndice() const {
346  return this->indice;
347  }
348 
350 
353  double getVolume() const;
354 
356 
360  bool contain(const Point<N>&) const;
361 
363 
367  TYPEVAL get(const Point<N>&) const;
368 
370  friend std::ostream& operator<<(std::ostream& os, const Simplex<N>& s) {
371  if(s.size()==0) {
372  os << "Empty simplex";
373  } else {
374  os << s.getIndice() << " {" << std::endl;
375  for(auto pt: s) {
376  os << pt << std::endl;
377  }
378  os << "}";
379  }
380  return os;
381  }
382 
383 private:
384  int indice;
385 };
386 
388 
389 // Constructeur par défaut
390 template<int N>
391 Simplex<N>::Simplex() : std::vector<Point<N>>(), indice(-1) {
392 }
393 
394 // Constructeur par conversion
395 template<int N>
396 Simplex<N>::Simplex(const std::vector<Point<N>> &pts) : std::vector<Point<N>>(pts), indice(-1) {
397 }
398 
399 // Constructeur par défaut
400 template<int N>
401 Simplex<N>::Simplex(const int &i) : std::vector<Point<N>>(), indice(i) {
402 }
403 
404 // Constructeur par conversion
405 template<int N>
406 Simplex<N>::Simplex(const int &i, const std::vector<Point<N>> &pts) : std::vector<Point<N>>(pts), indice(i) {
407 }
408 
409 // Destructeur
410 template<int N>
412 }
413 
414 // Renvoie le volume du simplexe
415 template<int N>
416 double Simplex<N>::getVolume() const {
417  // Calcule la matrice pour le determinant
418  auto pointSimplexe = this->at(0);
419  std::vector<Point<N>> matrix;
420  for(unsigned int ind=1; ind<=N; ind++) {
421  auto pointFace = this->at(ind);
422  matrix.push_back(pointFace-pointSimplexe);
423  }
424  // Calcule le determinant
425  auto res = Point<N>::getDeterminant(matrix);
426 
427  int fact=1;
428  for(int ii=1; ii<=N; ii++)
429  fact*=ii;
430  // Calcule le resultat final
431  res/=fact;
432  // Renvoie la valeur absolue
433  return res>0 ? res : -res;
434 }
435 
436 // Vérifie si un point se trouve dans un simplexe donné
437 template<int N>
438 bool Simplex<N>::contain(const Point<N> &p) const {
439  if(getVolume()==0) return false;
440  for(auto pointSimplexe: *this) {
441  std::vector<Point<N>> matrixFace, matrixSommet; // matrices à comparer après calcul de determinant
442  // Crée les deux matrices
443  for(auto pointFace: *this) {
444  if(pointSimplexe == pointFace) continue;
445  matrixFace.push_back(p-pointFace);
446  matrixSommet.push_back(pointSimplexe-pointFace);
447  }
448  // Calcule les determinants
449  auto detFace = p.getDeterminant(matrixFace), detSommet = p.getDeterminant(matrixSommet);
450  // On compare les determinants
451  if(detFace*detSommet < 0) {
452  // S'ils n'ont pas le même signe, le point n'est pas dans le simplexe
453  return false;
454  }
455  }
456  // S'ils ont tous le même signe, le point est dans le simplexe
457  return true;
458 }
459 
460 // Renvoie la valeur du point qui se trouve dans ce sommet
461 template<int N>
463  TYPEVAL res = 0;
464  if(!contain(p)) {
465  std::cerr << "\033[31m\033[31mERROR\033[0m\033[0m: GET : simplex " << *this << " does not contain point " << p << std::endl;
466  return 0;
467  }
468  //calcul volume simplex Vd
469  auto volumeD = this->getVolume();
470  Simplex<N> simplexQ;
471  for(auto pointSommet: *this) {
472  for(auto pointFace: *this) {
473  if(pointSommet == pointFace) continue;
474  simplexQ.push_back(pointFace);
475  }
476  simplexQ.push_back(p);
477  // calcule volume Vq
478  auto volumeQ = simplexQ.getVolume();
479  // calcule la coordonnée barycentrique au point courant
480  auto lambda = volumeQ/volumeD;
481  // ajoute au résultat la coordonnée barycentrique multipliée par la veleur au point
482  res += lambda * pointSommet.value();
483  simplexQ.clear();
484  }
485  return res;
486 }
487 
496 
497 
499 
503 template<int N>
504 class Paving final {
505 
506 public:
507 
509  Paving();
510 
512 
519  Paving(const int &, const int &, const int &);
520 
522 
535  Paving(const char* &f);
536 
538 
542  Paving(const std::vector<Point<N>> &);
543 
545  ~Paving();
546 
547 
549  inline std::vector<Point<N>> getPoints() {
550  return this->points;
551  }
553  inline std::vector<Point<N>> getTreatedPoints() {
554  return this->treated_points;
555  }
557  inline std::vector<std::vector<int>> getSimplices() {
558  return this->simplices;
559  }
560 
562 
575  bool init();
576 
578 
583  std::vector<Simplex<N>> sliceHypercube(const std::vector<Point<N>>&hypercube, const Point<N>&mid);
584 
585 
586 
588 
592  bool add(Point<N> &p);
593 
595 
599  TYPEVAL get(const Point<N> &p);
600 
601 
603 
607  Simplex<N> getSimplex(const Point<N> &p) const;
608 
609 
611 
615  std::vector<Point<N>> getPointsFromSimplex(const std::vector<int>&) const;
616 
617 
619  void showPoints() const;
621  void showTreatedPoints() const;
623  void showSimplices() const;
624 
626  void draw() const;
627 
629  void show() const;
630 
631 
632 private:
633  std::vector<Point<N>> points;
634  std::vector<Point<N>> treated_points;
635  std::vector<std::vector<int>> simplices;
636 
640  Point<N> p_min, p_max;
641  std::vector<Point<N>> user_points;
642 
644 
649  int getNearestPoint(const Point<N>&, const std::vector<Point<N>>&) const;
650 
651 
652 
653 };
654 
656 
657 // Constructeur par défaut
658 template<int N>
660 }
661 
663 template<int N>
664 Paving<N>::Paving(const std::vector<Point<N>> &v) : points(v) {
665 }
666 
668 template<int N>
669 Paving<N>::Paving(const int & n, const int & minv, const int & maxv) : p_min(Point<N>()), p_max(Point<N>()) {
670  std::cout << "Generating " << n << " random points of dimension " << N << std::endl;
671  for(int ii = 0; ii < N; ii++) {
672  p_min.push_back(9999999);
673  p_max.push_back(-9999999);
674  }
675 
676  srand(time(NULL));
677  for(int ii = 0; ii < n; ii++) {
678  Point<N> pt((rand()%maxv)+ii);
679  for(int jj=0; jj < N; jj++) {
680  TYPEVAL val = (rand()%(maxv-minv))+minv;
681  pt.push_back(val);
682  p_min[jj] = val < p_min[jj] ? val : p_min[jj];
683  p_max[jj] = val > p_max[jj] ? val : p_max[jj];
684  }
685  this->points.push_back(pt);
686  pt.clear();
687  }
688 }
689 
690 // Constructeur avec nom de fichier
691 template<int N>
692 Paving<N>::Paving(const char* & f) : p_min(Point<N>()), p_max(Point<N>()) {
693  std::cout << "Current data dimension " << N << std::endl << std::endl;
694  std::cout << "Building Paving from file '" << f << "', " ;
695  std::ifstream inputFile(f);
696  int nbPoints, dim;
697  for(int ii = 0; ii < N; ii++) {
698  p_min.push_back(9999999);
699  p_max.push_back(-9999999);
700  }
701 
702  if(inputFile.is_open()) {
703  inputFile >> nbPoints;
704  inputFile >> dim;
705  std::cout << "data dimension " << dim << std::endl;
706  if(dim != N) {
707  std::cerr << "\033[31mERROR\033[0m : Reading file : Data dimension (" << dim << ") does not correspond to template parameter Paving<" << N << ">" << std::endl;
708  return;
709  }
710  for(int ii=1; ii<=nbPoints; ii++) {
711  Point<N> point;
712  TYPECOORD coord;
713  TYPEVAL val;
714  for(int jj=0; jj<N; jj++) {
715  inputFile >> coord;
716  point.push_back(coord);
717  p_min[jj] = val < p_min[jj] ? val : p_min[jj];
718  p_max[jj] = val > p_max[jj] ? val : p_max[jj];
719  }
720  inputFile >> val;
721  point.setValue(val);
722  this->points.push_back(point);
723  }
724  inputFile.close();
725  } else {
726  std::cerr << "\033[31mERROR\033[0m: failed open file" << std::endl;
727  }
728 }
729 
730 // Destructeur
731 template<int N>
733 }
734 
735 // INIT VERSION (D+1)-SIMPLEXE
736 template<int N>
738  std::cout << std::endl << "Paving initialisation" << std::endl << std::endl;
739  if(N==2) grapic::winInit("PavIn", WINDIM_X, WINDIM_Y);
740 
741  auto extrem_coord = std::max(abs(*std::max_element(p_max.begin(),p_max.end())), abs(*std::min_element(p_min.begin(),p_min.end())));
742  auto coeff = extrem_coord/100;
743  if(coeff < 1) coeff = 1;
744 
745  //CREATION DU (N+1)-SIMPLEXE ENGLOBANT
746  std::cout << "Creating englobing simplex..." << std::endl << std::endl;
747  std::vector<Point<N>> tmp_points(points);
748  points = std::vector<Point<N>>();
749  Simplex<N+1> eng_simplex;
750  Point<N+1> p;
751  for(int ii = 0; ii < N+2; ii++) {
752  for(int jj = 0; jj < N+1; jj++) {
753  if(ii == N+1) {
754  p.push_back(-extrem_coord);
755  } else {
756  if(ii==jj) p.push_back(extrem_coord);
757  else p.push_back(0);
758  }
759  }
760  eng_simplex.push_back(p);
761  p.clear();
762  }
763 
764  std::cout << "Start englobing simplex : " << std::endl;
765  std::cout << eng_simplex << std::endl << std::endl;
766 
767  while(!tmp_points.empty()) {
768  // Agrandissement du (N+1)-Simplexe
769  for(int ii = 0; ii < N+1; ii++) {
770  eng_simplex[ii][ii]+=coeff;
771  }
772  for(int ii = 0; ii < N+1; ii++) {
773  eng_simplex[N+1][ii]-=coeff;
774  }
775 
776  // Ajout des points restants à ce (N+1)-Simplexe
777  for(unsigned int ii = 0; ii < tmp_points.size(); ii++) {
778  Point<N> pt = tmp_points[ii];
779  pt.push_back(0);
780  Point<N+1> point;
781  for(auto c: pt) point.push_back(c);
782  point.push_back(0);
783  if(eng_simplex.contain(point)) {
784  //std::cout << point << " in " << eng_simplex << std::endl;
785  points.push_back(tmp_points[ii]);
786  tmp_points.erase(tmp_points.begin()+ii);
787  }
788  }
789  }
790  // Projection du (N+1)-Simplexe en dimension N
791  Simplex<N> main_simplex;
792  for(unsigned int ii = 0; ii < eng_simplex.size(); ii++) {
793  if(ii == eng_simplex.size()-2) continue;
794  Point<N+1> point = eng_simplex[ii];
795  Point<N> pt;
796  for(int jj = 0; jj < N; jj++) {
797  pt.push_back(point[jj]);
798  }
799  main_simplex.push_back(pt);
800  }
801 
802 
803  std::cout << "Pre-refine englobing simplex : " << std::endl;
804  std::cout << main_simplex << std::endl << std::endl;
805 
806  // AFFINAGE DU N-SIMPLEXE
807  std::cout << "Refining englobing simplex..." << std::endl << std::endl;
808 
809  bool res = true;
810  // Affinage du N-Simplexe en ramenant les points (t, 0, 0 ...), (0, t, 0 ...) ...
811  while(res) {
812  // Diminution du N-Simplexe
813  for(int ii = 0; ii < N; ii++)
814  main_simplex[ii][ii]-=coeff;
815  // Teste si tous les points sont toujours dans le simplexe
816  for(auto pt: points)
817  if(!main_simplex.contain(pt))
818  res = false;
819  }
820  // Remise en l'état
821  for(int ii = 0; ii < N; ii++)
822  main_simplex[ii][ii]+=coeff;
823  p_max.clear();
824  p_max.push_back(main_simplex[0][0]);
825  p_max.push_back(main_simplex[0][0]);
826 
827  res = true;
828  // Affinage du N-Simplexe en ramenant le point (-t, -t, -t ...)
829  while(res) {
830  for(int ii = 0; ii < N; ii++)
831  main_simplex[N][ii]+=coeff;
832  for(auto pt: points)
833  if(!main_simplex.contain(pt))
834  res = false;
835  }
836  for(int ii = 0; ii < N; ii++)
837  main_simplex[N][ii]-=coeff;
838  p_min.clear();
839  auto v = main_simplex[N][0] > 0 ? 0 : main_simplex[N][0];
840  p_min.push_back(v);
841  p_min.push_back(v);
842 
843  std::cout << "Englobing simplex : " << std::endl;
844  std::cout << main_simplex << std::endl << std::endl;
845 
846  show();
847 
848  // AJOUT DU SIMPLEXE ET DES POINTS
849  std::vector<int> sim;
850  for(unsigned int ii = 0; ii < main_simplex.size(); ii++) {
851  treated_points.push_back(main_simplex[ii]);
852  sim.push_back(ii);
853  }
854  simplices.push_back(sim);
855  show();
856 
857  // Ajout de tous les points à l'intérieur de la boite
858  Point<N> pt(main_simplex[main_simplex.size()-1]);
859  res = true;
860  while(!this->points.empty()) {
861  int id = getNearestPoint(pt, this->points);
862  pt = this->points[id];
863  this->points.erase(this->points.begin()+id);
864  if(!this->add(pt)) res = false;
865  show();
866  }
867  user_points = std::vector<Point<N>>();
868  std::cout << std::endl << std::endl << std::endl;
869  return res;
870 }
871 
872 // INIT VERSION HYPERCUBE
873 /*
874 template<int N>
875 void Paving<N>::init() {
876  std::cout << std::endl << "Init Paving ..." << std::endl;
877  grapic::winInit("PavIn", WINDIM_X, WINDIM_Y);
878 
879  // Création d'une boite englobante
880  // Création du tableau des extremums, pour chaque axe de dimension, cherche le min et le max
881  std::vector<Point<2>> extremums;
882  for(int ii = 0; ii < N; ii++) {
883  Point<2> extremum;
884  extremum.push_back(999999);
885  extremum.push_back(-999999);
886  extremums.push_back(extremum);
887  }
888  for(auto pt: this->points) {
889  for(unsigned int ii = 0; ii < pt.size(); ii++) {
890  extremums[ii][0] = pt[ii] < extremums[ii][0] ? pt[ii] : extremums[ii][0];
891  extremums[ii][1] = pt[ii] > extremums[ii][1] ? pt[ii] : extremums[ii][1];
892  }
893  }
894  // Créeation des deux points extremaux, diagonale, et sert pour calculer un affichage correct
895  for(auto extr: extremums) {
896  p_min.push_back(extr[0]);
897  p_max.push_back(extr[1]);
898  }
899 
900  show();
901 
902  // Crée les coordonnées des points extremaux dans un vector a remettre dans l'ordre
903  // Contient les valeurs issues de l'arbre binaire des possibilités des points extremaux
904  bool b = true;
905  std::vector<TYPECOORD> v_eng_points;
906  for(unsigned int ii = 0; ii < extremums.size(); ii++) {
907  int cpt = pow(2,N)/(2*(ii+1));
908  for(int jj = 0; jj <= pow(2,N)-1; jj++) {
909  if(jj%cpt == 0) b = b ? false : true;
910  if(b) {
911  v_eng_points.push_back(extremums[ii][1]);
912  } else {
913  v_eng_points.push_back(extremums[ii][0]);
914  }
915  }
916  }
917 
918  // Crée les points extremaux à partir de l'arbre binaire, leur donne la valeur du point le plus proche
919  std::vector<Point<N>> eng_points;
920  int threshold = v_eng_points.size()/N;
921  for(int ii = 0; ii < threshold; ii++) {
922  Point<N> pt;
923  for(int jj = 0; jj < N; jj++) {
924  pt.push_back(v_eng_points[ii+jj*threshold]);
925  }
926  eng_points.push_back(pt);
927  }
928  std::cout << "Englobing points:" << std::endl;
929  for(unsigned int ii = 0; ii < eng_points.size(); ii++) {
930  eng_points[ii].setValue(points[getNearestPoint(eng_points[ii], this->points)].value());
931  std::cout << eng_points[ii] << std::endl;
932  }
933  std::cout << std::endl;
934 
935  // Recherche du milieu, donne au milieu la valeur du point le plus proche
936  Point<N> mid(p_min.getMiddle(p_min, p_max));
937  mid.setValue(points[getNearestPoint(mid, this->points)].value());
938  //std::cout << "Middle : " << mid << std::endl;
940 
942  // Création du contour de la boite (suite de points, pour éviter les simplexes qui se croisent), ajout au Pavage
943  std::vector<Point<N>> cont_points;
944  std::cout <<std::endl << "Outline:" << std::endl;
945  cont_points.push_back(eng_points[0]);
946  eng_points.erase(eng_points.begin());
947  for(int ii = 0; !eng_points.empty(); ii++) {
948  ii%=eng_points.size();
949  for(int jj = 0; jj < N; jj++) {
950  if(eng_points[ii][jj] == eng_points[eng_points.size()-1][jj]) {
951  //Deux points sur le meme axe
952  cont_points.push_back(eng_points[ii]);
953  eng_points.erase(eng_points.begin()+ii);
954  break;
955  }
956  }
957  }
958  for(auto pt: cont_points) {
959  std::cout << pt << " -> ";
960  }
961  std::cout << std::endl << std::endl;
962  this->treated_points = std::vector<Point<N>>(cont_points);
963  this->treated_points.push_back(mid);
964 
965  // Création des nouveaux simplexes par combinaison de N points à la suite du contour, et du milieu
966  std::vector<Simplex<N>> simps;
967  for(unsigned int ii = 0; ii < cont_points.size(); ii++) {
968  std::vector<int> simp;
969  for(int jj = 0; jj < N; jj++) {
970  simp.push_back((ii+jj)%cont_points.size());
971  }
972  simp.push_back(cont_points.size());
973 
974  simplices.push_back(simp);
975  }
976  showSimplices();
977  show();
979 
980  // Ajout de tous les points à l'intérieur de la boite
981  Point<N> p(mid);
982  while(!this->points.empty()) {
983  int id = getNearestPoint(p, this->points);
984  p = this->points[id];
985  this->points.erase(this->points.begin()+id);
986  this->add(p);
987  show();
988  }
989 }
990 */
991 
992 // ADD
993 template<int N>
995  std::cout << "Adding point " << p << ": ";
996  // Cherche le simplexe contenant
997  Simplex<N> simplex = getSimplex(p);
998 
999  if(simplex.size()!=0) {
1000  // Ajoute le point aux points traités
1001  auto newInd = this->treated_points.size();
1002  this->treated_points.push_back(p);
1003  for(auto indSimplex: this->simplices[simplex.getIndice()]) {
1004  std::vector<int> sim;
1005  sim.push_back(newInd);
1006  for(auto indFace: this->simplices[simplex.getIndice()]) {
1007  if(indSimplex == indFace) continue;
1008  sim.push_back(indFace);
1009  }
1010  this->simplices.push_back(sim);
1011  }
1012  this->simplices.erase(this->simplices.begin()+simplex.getIndice());
1013  std::cout << "\033[32madded\033[0m" << std::endl;
1014  return true;
1015  } else {
1016  std::cout << "\033[31mnot in any simplex\033[0m" << std::endl;
1017  return false;
1018  }
1019 
1020 }
1021 
1022 // GET
1023 template<int N>
1025  TYPEVAL res = 0;
1026  std::cout << "Getting " << p << std::endl << std::endl;
1027  // Cherche le simplexe contenant
1028  Simplex<N> simplexD = getSimplex(p);
1029  std::cout << "Containing simplex: " << simplexD << std::endl;
1030  // Si un simplexe est trouvé
1031  if(simplexD.size()!=0) {
1032  res = simplexD.get(p);
1033  user_points.push_back(p);
1034  } else {
1035  std::cout << "\033[31mPoint " << p << " not in any simplex\033[0m" << std::endl;
1036  }
1037  return res;
1038 }
1039 
1040 // Point le plus proche
1041 template<int N>
1042 int Paving<N>::getNearestPoint(const Point<N> &p, const std::vector<Point<N>> &v) const {
1043  int res, ii=0;
1044  double d = 9999999, tmpD;
1045  for(auto elm : v) {
1046  tmpD = Point<N>::getDistance(p, elm);
1047  if(tmpD < d && p!=elm) {
1048  d = tmpD;
1049  res = ii;
1050  }
1051  ii++;
1052  }
1053  return res;
1054 }
1055 
1056 // Renvoie le simplexe contenant le point
1057 template<int N>
1059  int ind=0;
1060  for(auto vec: this->simplices) {
1061  Simplex<N> simp(ind, getPointsFromSimplex(vec));
1062  if(simp.getVolume() > 0) {
1063  if(simp.contain(p)) {
1064  return simp;
1065  }
1066  }
1067  ind++;
1068  }
1069  return Simplex<N>();
1070 }
1071 
1072 // Renvoie les points d'un simplexe donné
1073 template<int N>
1074 std::vector<Point<N>> Paving<N>::getPointsFromSimplex(const std::vector<int> &s) const {
1075  std::vector<Point<N>> res;
1076  for(auto ind: s) {
1077  Point<N> pt = this->treated_points[ind];
1078  res.push_back(pt);
1079  }
1080  return res;
1081 }
1082 
1083 // showPoints
1084 template<int N>
1086  std::cout << "Points (" << this->points.size() << ") :" << std::endl;
1087  for(auto p : this->points) {
1088  std::cout << " " << p << std::endl;
1089  }
1090  std::cout << std::endl;
1091 }
1092 
1093 // showTreatedPoints
1094 template<int N>
1096  std::cout << "Treated points (" << this->treated_points.size() << ") :" << std::endl;
1097  for(auto p : this->treated_points) {
1098  std::cout << " " << p << std::endl;
1099  }
1100  std::cout << std::endl;
1101 }
1102 
1103 // showSimplices
1104 template<int N>
1106  std::cout << "Simplices (" << this->simplices.size() << ") :" << std::endl;
1107  int ind = 0;
1108  for(auto v: this->simplices) {
1109  Simplex<N> sim(ind++, getPointsFromSimplex(v));
1110  std::cout << sim << std::endl;
1111  }
1112  std::cout << std::endl;
1113 }
1114 
1115 // Dessin
1116 template<int N>
1117 void Paving<N>::draw() const {
1118  TYPECOORD height = p_max[0]-p_min[0];
1119  TYPECOORD width = p_max[1]-p_min[1];
1120  double coeff = WINDIM_X/width < WINDIM_Y/height ? (WINDIM_X)/width : (WINDIM_Y)/height;
1121  grapic::color(242,224,26);
1122  for(auto pt: this->points) {
1123  grapic::point((pt[0]-p_min[0])*coeff, (pt[1]-p_min[1])*coeff);
1124  }
1125 
1126  grapic::color(74, 239, 231);
1127  if(simplices.empty()) return;
1128  for(auto vec: this->simplices) {
1129  Point<N> a(this->treated_points[vec[0]]), b(this->treated_points[vec[1]]), c(this->treated_points[vec[2]]);
1130  grapic::line((a[0]-p_min[0])*coeff, (a[1]-p_min[1])*coeff, (b[0]-p_min[0])*coeff, (b[1]-p_min[1])*coeff);
1131  grapic::line((a[0]-p_min[0])*coeff, (a[1]-p_min[1])*coeff, (c[0]-p_min[0])*coeff, (c[1]-p_min[1])*coeff);
1132  grapic::line((c[0]-p_min[0])*coeff, (c[1]-p_min[1])*coeff, (b[0]-p_min[0])*coeff, (b[1]-p_min[1])*coeff);
1133  }
1134 
1135  grapic::color(239, 74, 1);
1136  if(user_points.empty()) return;
1137  Point<N> pt(user_points[user_points.size()-1]);
1138  Simplex<N> sim(getSimplex(pt));
1139  for(auto pt_sim: sim) {
1140  grapic::line((pt[0]-p_min[0])*coeff, (pt[1]-p_min[1])*coeff, (pt_sim[0]-p_min[0])*coeff, (pt_sim[1]-p_min[1])*coeff);
1141  }
1142 }
1143 
1144 // Affichage
1145 template<int N>
1146 void Paving<N>::show() const {
1147  if(N==2) {
1148  grapic::backgroundColor(0,0,0);
1149  grapic::winClear();
1150  draw();
1151  grapic::winDisplay();
1152  std::cout << "Press ENTER to continue" << std::endl;
1153  std::cin.ignore();
1154  }
1155 }
1156 
1157 #endif
friend bool operator==(const Point< N > &x, const Point< N > &y)
Test d&#39;égalité entre deux points.
Definition: Paving.hpp:125
Classe Simplex.
Definition: Paving.hpp:308
bool contain(const Point< N > &) const
Vérifie si un point se trouve dans le simplexe.
Definition: Paving.hpp:438
const int WINDIM_X
Longueur des fenêtres d&#39;affichage.
Definition: Paving_config.hpp:26
friend bool operator!=(const Point< N > &x, const Point< N > &y)
Test de la différence entre deux points.
Definition: Paving.hpp:134
TYPEVAL get(const Point< N > &p)
Méthode centrale: calcule en fonction d&#39;un point donné
Definition: Paving.hpp:1024
friend Point< N > operator+(const Point< N > &x, const Point< N > &y)
Permet l&#39;addition des points membres à membres.
Definition: Paving.hpp:139
const int WINDIM_Y
Hauteur des fenêtres d&#39;affichage.
Definition: Paving_config.hpp:29
~Point()
Destructeur.
Definition: Paving.hpp:234
std::vector< Point< N > > getPointsFromSimplex(const std::vector< int > &) const
Renvoie les points d&#39;un simplexe donné
Definition: Paving.hpp:1074
void draw() const
Dessine le Pavage pour la fenêtre graphique.
Definition: Paving.hpp:1117
double TYPECOORD
Type des coordonnées des échantillons.
Definition: Paving_config.hpp:20
std::vector< Point< N > > getTreatedPoints()
Retourne tous les points traités sous forme d&#39;un vector.
Definition: Paving.hpp:553
double getVolume() const
Renvoie le volume du simplexe.
Definition: Paving.hpp:416
Classe Point.
Definition: Paving.hpp:41
void showTreatedPoints() const
Afiche les points traités sur la sortie standard.
Definition: Paving.hpp:1095
void showPoints() const
Afiche les points sur la sortie standard.
Definition: Paving.hpp:1085
bool init()
Initialise le Pavage.
Definition: Paving.hpp:737
~Paving()
Destructeur.
Definition: Paving.hpp:732
bool add(Point< N > &p)
Ajoute un point incrémentalement au pavage.
Definition: Paving.hpp:994
Simplex< N > getSimplex(const Point< N > &p) const
Renvoie le simplexe contenant le point.
Definition: Paving.hpp:1058
std::vector< std::vector< int > > getSimplices()
Retourne tous les simplexes.
Definition: Paving.hpp:557
Point< N > getMiddle(const Point< N > &, const Point< N > &) const
Calcule le milieu de deux points de même dimension.
Definition: Paving.hpp:251
Configuration des paramètres utilisateurs.
TYPEVAL value() const
Retourne la valeur du point.
Definition: Paving.hpp:73
int getIndice() const
Retourne l&#39;indice du simplexe dans le tableau de simplexes de la classe Pavage.
Definition: Paving.hpp:345
~Simplex()
Destructeur.
Definition: Paving.hpp:411
static double getDistance(const Point< N > &, const Point< N > &)
Calcule la distance entre deux points de même dimension.
Definition: Paving.hpp:239
double TYPEVAL
Type des valeurs des échantillons.
Definition: Paving_config.hpp:23
static long double getDeterminant(const std::vector< Point< N >> &)
Calcule le déterminant entre deux points de même dimension.
Definition: Paving.hpp:263
Simplex()
Construit un simplex vide.
Definition: Paving.hpp:391
Classe Paving.
Definition: Paving.hpp:504
void showSimplices() const
Afiche les simplices sur la sortie standard.
Definition: Paving.hpp:1105
std::vector< Point< N > > getPoints()
Retourne tous les points sous forme d&#39;un vector.
Definition: Paving.hpp:549
TYPEVAL get(const Point< N > &) const
Renvoie la valeur du point du simplexe.
Definition: Paving.hpp:462
Point()
Construit un point de valeur 0.
Definition: Paving.hpp:176
Paving()
Constructeur par défaut.
Definition: Paving.hpp:659
void show() const
Affichge le Pavage dans une fenêtre graphique.
Definition: Paving.hpp:1146
void setValue(const TYPEVAL &v)
Change la valeur du point.
Definition: Paving.hpp:78
friend Point< N > operator-(const Point< N > &x, const Point< N > &y)
Permet la soustraction des points membres à membres.
Definition: Paving.hpp:148