NDDEM
Texturing.h
Go to the documentation of this file.
1 
14 #include "Tools.h"
15 #include "io.h"
16 
17 #include <thread>
18 #include <regex>
19 #include <limits>
20 #include <filesystem>
21 
22 extern bool blenderrender ;
23 
24 #define DeltaX 0.1
25 #define FilePerLine 100
26 
27 void phi2color (vector<uint8_t>::iterator px, cv1d & phi, int d, vector<vector<float>> & colors) ;
28 using namespace std ;
29 
31 class Timestep {
32 public:
33  v2d X ;
34  v2d A ;
35 } ;
36 
38 template <int d>
39 class Texturing {
40 public :
41  int Nlambda=32 ;
42  int Ntheta=32 ;
43  vector<vector<float>> colors ;
44  const vector<vector<float>> allcolorslist = {
45  {1,0,0},
46  {0,1,0},
47  {0,0,1},
48  {1,1,0},
49  {0,1,1},
50  {1,0,1}} ;
51 
52  const vector<vector<vector<float>>> allcolors = {
53  {{231./256., 37./256., 100./256.}}, // official NDDEM pink
54  {{1,1,0},{0,1,1}}};
55 
58  #ifdef TEXTURINGPATH
59  string BasePath = TEXTURINGPATH "/../Samples/" ;
60  string DirectorySave = TEXTURINGPATH "/../Textures/" ;
61  #else
62  string BasePath = "../Samples/" ;
63  string DirectorySave = "../Textures/" ;
64  #endif
65  int N ;
67 
68  vector <Timestep> Ts ;
69  vector <int> TsName ;
70  v1d R ;
71  v1d View ;
72  vector <int> ViewPoint ;
73  vector <int> NewViewPoint ;
74  vector <int> RenderedAlready ;
75  bool runfast ;
77 
78  bool justloaded ;
79  int nrotate ;
80  vector<vector<string>> FileList ;
81  vector <std::thread> Threads;
82  const bool singlefiles = true ;
83 
84  // function
85  int initialise (map <string,string> args) ;
86  int clean() ;
87  int set_grid (int nb) ;
88  void spaceloop (v1d View, uint tsint, int nrotate, int dim) ;
89  void timeloop (v1d View, uint tsint, int nrotate) ;
90  void hereandnow(v1d View, uint tsint, int nrotate) ;
91  int MasterRender() ;
92  int SetNewViewPoint (map <string,string> args) ;
93  bool isrendered () ;
94  void Render (vector <string> & filerendered, cv1d & View, int nrotate, int time, cv2d &X, cv1d & R, cv2d &A) ;
95  int viewpermute (v1d & View) ;
96  void rescale (v1f & c, cv1f sum) ;
97  void filepathname (char * path, int n, int time, cv1d & View);
98  void filepathname (char * path, int time, cv1d & View);
99 
100  int write_vtkmap (map <string,string> args) ;
101  int write_colormap_vtk_base () ;
102  int write_colormap_nrrd_base (map <string,string> args) ;
103 
104 } ;
105 
106 
107 /*****************************************************************************************************
108  * *
109  * *
110  * *
111  * IMPLEMENTATIONS *
112  * *
113  * *
114  * *
115  * ***************************************************************************************************/
116 inline void dispvector (const v1d & a) {for (auto v: a) printf("%g ", v); printf("\n") ; fflush(stdout) ; }
117 inline void dispvector (const v1f & a) {for (auto v: a) printf("%g ", v); printf("\n") ; fflush(stdout) ; }
118 inline void dispvector (const vector<int> & a) {for (auto v: a) printf("%d ", v); printf("\n") ; fflush(stdout) ; }
119 
120 template <int d>
121 void runthread_timeloop (Texturing<d> * T, v1d View, uint tsint, int nrotate)
122 {T->timeloop(View, tsint,nrotate) ; }
123 
124 template <int d>
125 void runthread_spaceloop (Texturing<d> * T, v1d View, uint tsint, int nrotate, int dim)
126 {T->spaceloop(View, tsint,nrotate, dim) ; }
127 //=========================================================================
128 
129 template <int d>
130 int Texturing<d>::initialise (map <string,string> args)
131 {
133  printf("{%s}", DirectorySave.c_str()) ;
134  string Directory=args["path"] ;
135  //DirectorySave= args["texturepath"] ;
136  set_grid (atoi(args["resolution"].c_str())) ;
137 
138  //Get all the relevent files in the Directory, sort them and identify the timesteps
139  std::filesystem::directory_iterator D(BasePath + Directory) ;
140  vector <string> tmpfilelst ;
141  vector <std::pair<int,string>> filelistloc, filelistA ;
142  for (auto& p : std::filesystem::directory_iterator(BasePath+Directory)) tmpfilelst.push_back(p.path().string()) ;
143  regex exprloc{".*dump-([0-9]+).csv"};
144  regex exprA{".*dumpA-([0-9]+).csv"};
145  smatch what;
146  for (auto &a : tmpfilelst)
147  {
148  if (regex_match(a, what, exprloc)) filelistloc.push_back(make_pair(stoi(what[1].str()), a)) ;
149  if (regex_match(a, what, exprA)) filelistA.push_back(make_pair(stoi(what[1].str()), a)) ;
150  }
151  std::sort(filelistloc.begin(), filelistloc.end()) ;
152  std::sort(filelistA.begin() , filelistA.end() ) ;
153  TsName.resize(filelistloc.size(), 0) ;
154  for (uint i=0 ; i<filelistloc.size() ; i++) TsName[i]=filelistloc[i].first ;
155 
156  // Let's read everything
157  Ts.resize(filelistloc.size()) ;
158  for (uint i=0 ; i<filelistloc.size() ; i++)
159  {
160  R.clear() ;
161  csvread_XR (filelistloc[i].second.c_str(), Ts[i].X, R, d) ;
162  printf("%d ", i) ; fflush(stdout) ;
163  }
164  for (uint i=0 ; i<filelistA.size() ; i++) csvread_A(filelistA[i].second.c_str(), Ts[i].A, d) ;
165  N = Ts[0].X.size() ;
166  int nrotate=3 ; // Rotate all the coordinates already
167  for (auto & v : Ts)
168  {
169  for (int i=0 ; i<N ; i++)
170  {
171  rotate(v.X[i].begin(), v.X[i].begin()+nrotate, v.X[i].end()) ;
173  }
174  }
175  Boundaries.resize(2) ;
176  Boundaries[0].resize(d-3, INT_MAX) ;
177  Boundaries[1].resize(d-3, INT_MIN) ;
178  for (auto &v : Ts)
179  for (auto &w : v.X)
180  {
181  for (uint i=0 ; i<d-3 ; i++)
182  {
183  if (w[i]<Boundaries[0][i]) Boundaries[0][i] = w[i] ;
184  if (w[i]>Boundaries[1][i]) Boundaries[1][i] = w[i] ;
185  }
186  }
187  auto tmpbound = max_element(R.begin(), R.end()) ;
188  for (uint i=0 ; i<d-3 ; i++) {Boundaries[0][i] -= (*tmpbound) ; Boundaries[1][i] += (*tmpbound) ; }
189 
190  // Color gradient initialisation
191  if (static_cast<uint>(d-1)>allcolorslist.size()) printf("ERR: not enough color gradients!!\n") ;
192  //if (d-3<allcolors.size()) colors=allcolors[d-3] ; //TODO
193  //else
194  colors=allcolorslist ;
195 
196  View.resize(d, 0) ;
197  printf("[[[%ld]]]", View.size()) ; fflush(stdout) ;
198  RenderedAlready.resize(2*(d-3+1), 0) ;
199  ViewPoint.resize(d-3+1, INT_MIN) ;
200  NewViewPoint.resize(d-3+1, 0) ;
201  FileList.resize(d-3+1) ;
202  Threads.resize(d-3+1) ;
203  justloaded=true ;
204  singlerendered=false ;
205  return 0 ;
206 }
207 
208 //==================================================
209 template <int d>
211 {
212 colors.clear() ;
213 lambdagrid.clear() ;
214 thetagrid.clear() ;
215 
216 Boundaries.clear() ;
217 TsName.clear() ;
218 R.clear() ;
219 View.clear() ;
220 ViewPoint.clear() ;
221 NewViewPoint.clear() ;
222 
223 for (auto & Thr : Threads)
224  if (Thr.joinable())
225  {
226  auto ThrID = Thr.native_handle() ;
227  pthread_cancel(ThrID);
228  Thr.join() ;
229  }
230 
231 Threads.clear();
232 Tools<d>::clear() ;
233 vector<Timestep>().swap(Ts) ;
234 Boundaries.clear() ;
235 ViewPoint.clear() ;
236 NewViewPoint.clear() ;
237 View.clear() ;
238 RenderedAlready.clear() ;
239 for (auto & u : FileList)
240  for (auto & v: u)
241  std::filesystem::remove(v.c_str()) ;
242 
243 return 0 ;
244 }
245 //=================================================
246 template <int d>
247 int Texturing<d>::SetNewViewPoint (map <string,string> args)
248 {
249  printf("|%s|", args["ts"].c_str()) ; fflush(stdout) ;
250  int Time=atoi(args["ts"].c_str()) ;
251  printf("H") ; fflush(stdout) ;
252  char dimstr[10] ;
253  printf("[]%ld[]", View.size() ) ; fflush(stdout) ;
254  View[0]=View[1]=View[2]=NAN ;
255  printf("E") ; fflush(stdout) ;
256  for (uint dd=3 ; dd<d ; dd++)
257  {
258  sprintf(dimstr, "x%d", dd+1) ;
259  View[dd]=atof(args[dimstr].c_str()) ;
260  }
261  printf("F") ; fflush(stdout) ;
262  nrotate = viewpermute (View) ;
263  if (nrotate != 3 && d>3) printf("WHAT? No the first 3D should be NaNs ...") ;
264  for (uint i=0 ; i<d-3 ; i++) {NewViewPoint[i] = static_cast<int>(round(View[i]/DeltaX));}
265 printf("B") ; fflush(stdout) ;
266  auto tmp = find(TsName.begin(), TsName.end(), Time) ;
267  if (tmp == TsName.end()) {printf("WARN: not found timestep\n") ; return -1 ; }
268  NewViewPoint[d-3] = tmp-TsName.begin() ;
269 printf("C") ; fflush(stdout) ;
270  if (atoi(args["running"].c_str())==1) runfast=true ;
271  else runfast=false ;
272  printf("D") ; fflush(stdout) ;
273  return 0 ;
274 }
275 //=====================================================
276 template <int d>
278 {
279  if (singlerendered) {singlerendered=false ; return true ; }
280 
281  for (uint i=0 ; i<d-3 ; i++)
282  if (NewViewPoint[i]<RenderedAlready[i*2] || NewViewPoint[i]>RenderedAlready[i*2+1])
283  return false ;
284 
285  int t ;
286  if (NewViewPoint[d-3]<RenderedAlready[(d-3)*2]) t = NewViewPoint[d-3] +Ts.size() ;
287  else t= NewViewPoint[d-3] ;
288 
289  if (t>=RenderedAlready[(d-3)*2]+RenderedAlready[(d-3)*2+1]) return false ;
290 
291  return true ;
292 }
293 
294 
295 //=====================================================
296 template <int d>
298 {
299  //printf("%d %d | %d %d\n", ViewPoint[0], ViewPoint[1], NewViewPoint[0], NewViewPoint[1]) ;
300  // Alright, lets start the threads
301 
302  if (! isrendered() && runfast) {dispvector(RenderedAlready) ; hereandnow(View, NewViewPoint[d-3], nrotate) ; singlerendered=true ; }
303  if (! runfast)
304  {
305  for (uint i=0 ; i<d-3 ; i++)
306  {
307  for (uint j=0 ; j<d-3+1 ; j++)
308  {
309  if (j==i) continue ;
310  if (NewViewPoint[j] != ViewPoint[j])
311  {
312  if (Threads[i].joinable())
313  {
314  auto ThreadID = Threads[i].native_handle() ;
315  pthread_cancel(ThreadID);
316  Threads[i].join() ;
317  }
318  dispvector(NewViewPoint) ;
319  Threads[i] = std::thread(runthread_spaceloop<d>, this, View, NewViewPoint[d-3], nrotate, i) ;
320  break ;
321  }
322  }
323  }
324  for (uint j=0 ; j<d-3 ; j++)
325  {
326  if (NewViewPoint[j] != ViewPoint[j])
327  {
328  if (Threads[d-3].joinable())
329  {
330  auto ThreadID = Threads[d-3].native_handle() ;
331  pthread_cancel(ThreadID) ;
332  Threads[d-3].join() ;
333  }
334  dispvector(NewViewPoint) ;
335  Threads[d-3] = std::thread(runthread_timeloop<d>, this, View, NewViewPoint[d-3], nrotate) ;
336  }
337  }
338 
339  if (d==3 && justloaded)
340  {
341  Threads[d-3] = std::thread(runthread_timeloop<d>, this, View, NewViewPoint[d-3], nrotate) ;
342  justloaded=false ;
343  }
344  }
345 ViewPoint=NewViewPoint ;
346 return 0 ;
347 }
348 
349 //===========================================================
350 template <int d>
351 void Texturing<d>::spaceloop (v1d View, uint tsint, int nrotate, int dim)
352 {
353 //printf("S") ; fflush(stdout) ;
354 for (auto & v : FileList[dim]) std::filesystem::remove(v.c_str()) ;
355 FileList[dim].clear() ;
356 
357 auto Viewdec = View ;
358 while (Viewdec[dim]>Boundaries[0][dim] || View[dim]<Boundaries[1][dim])
359 {
360  Viewdec[dim] -= DeltaX ;
361  View[dim] += DeltaX ;
362 
363  //printf("s") ; fflush(stdout) ;
364 
365  if (Viewdec[dim]>Boundaries[0][dim]) Render(FileList[dim], Viewdec, nrotate, TsName[tsint], Ts[tsint].X, R, Ts[tsint].A) ;
366  RenderedAlready[2*dim] = Viewdec[dim] / DeltaX ;
367  if (View[dim]<Boundaries[1][dim]) Render(FileList[dim], View, nrotate, TsName[tsint], Ts[tsint].X, R, Ts[tsint].A) ;
368  RenderedAlready[2*dim+1] = View[dim] / DeltaX ;
369 }
370 RenderedAlready[2*dim] = INT_MIN ;
371 RenderedAlready[2*dim+1] = INT_MAX ;
372 printf("Spaceloop is done") ; fflush(stdout) ;
373 }
374 //-----------------------------------------------------
375 template <int d>
376 void Texturing<d>::timeloop (v1d View, uint tsint, int nrotate)
377 {
378 int dim=FileList.size()-1 ;
379 for (auto & v : FileList[dim]) std::filesystem::remove(v.c_str()) ;
380 
381 FileList[dim].clear() ;
382 uint timeidxinit=tsint ;
383 //if (tsint>=Ts.size()) tsint=0 ;
384 RenderedAlready[2*(d-3)] = tsint ;
385 RenderedAlready[2*(d-3)+1] = 0;
386 do {
387 Render(FileList[dim],View, nrotate, TsName[tsint], Ts[tsint].X, R, Ts[tsint].A) ;
388 printf("%d ", tsint) ; fflush(stdout) ;
389 tsint++ ;
390 printf("%d ", tsint) ; fflush(stdout) ;
391 RenderedAlready[2*(d-3)+1] ++ ;
392 if (tsint>=Ts.size()) tsint=0 ;
393 } while (tsint != timeidxinit) ;
394 printf("Timeloop is done") ; fflush(stdout) ;
395 }
396 //-----------------------------------------------------
397 template <int d>
398 void Texturing<d>::hereandnow (v1d View, uint tsint, int nrotate)
399 {
400 int dim=FileList.size()-1 ;
401 for (auto & v : FileList[dim]) std::filesystem::remove(v.c_str()) ;
402 
403 FileList[dim].clear() ;
404 //uint timeidxinit=tsint ;
405 Render(FileList[dim],View, nrotate, TsName[tsint], Ts[tsint].X, R, Ts[tsint].A) ;
406 }
407 //-----------------------------------------------------
408 template <int d>
409 void Texturing<d>::Render (vector <string> & filerendered, cv1d & View, int nrotate, int time, cv2d &X, cv1d & R, cv2d &A)
410 {
411 v1d sp (d,0) ; v1d spturned (d,0) ; // Surface point (point on the surface of the sphere)
412 v1d phi (d-1,0), phinew(d-1,0) ; // Angles of the hyperspherical coordinates. All angles between 0 and pi, except the last one between 0 and 2pi
413 vector<uint8_t> img ; int stride ;
414 int imgx0=0 ;
415 if (singlefiles)
416 {
417  img.resize(Nlambda*Ntheta*3,0) ;
418  stride=Ntheta ;
419 }
420 else
421 {
422  img.resize( Ntheta * FilePerLine * (N/FilePerLine+1)* Nlambda*3,0) ;
423  stride = Nlambda * FilePerLine ;
424 }
425 
426 for (int i=0 ; i<N ; i++)
427 {
428  // Check if we are in view
429  double rsqr = R[i]*R[i] ;
430  //rotate(X[i].begin(), X[i].begin()+nrotate, X[i].end()) ;
431  for (uint j=0 ; j<d-3 ; j++)
432  rsqr -= (View[j]-X[i][j])*(View[j]-X[i][j]) ;
433  if (rsqr<=0)
434  {
435  //char path[5000] ;
436  //sprintf(path, "%s/Texture-%d-%d.png", Directory.c_str(), TimeCur->first, i) ;
437  //experimental::filesystem::remove(path) ;
438  continue ;
439  }
440 
441  // We are in view, let's get to it let's get the first phi's (constants)
442  for (uint j=0 ; j<d-3 ; j++)
443  {
444  double cosine = (View[j]-X[i][j])/R[i] ;
445  for (uint k=0 ; k<j ; k++)
446  cosine /= sin(phi[k]) ;
447  phi[j] = acos(cosine) ;
448  }
449 
450 
451  for (int j = 0 ; j<Nlambda ; j++)
452  for (int k=0 ; k<Ntheta ; k++)
453  {
454  // Finalising the phi array (useless, but just because
455  phi[d-3]=lambdagrid[j] ;
456  phi[d-2]=thetagrid[k] ;
457 
458  for (uint dd=0 ; dd<d-3 ; dd++) {sp[dd]=View[dd]-X[i][dd] ;}
459  //sp = View-X[i] ; // All the dimensions except the last 3 are now correct
460  sp[d-3] = R[i] ;
461  for (uint j=0 ; j<d-3 ; j++) sp[d-3] *= sin(phi[j]) ;
462  sp[d-2]=sp[d-3] ; sp[d-1]=sp[d-3] ;
463 
464  //********** The mathematical version (logical):
465  //sp[d-3] *= cos(phi[d-3]) ;
466  //sp[d-2] *= sin(phi[d-3])*cos(phi[d-2]) ;
467  //sp[d-1] *= sin(phi[d-3])*sin(phi[d-2]) ;
468 
469  if (blenderrender)
470  {
471  //********** Version agreeing with default uv sphere mapping in Blender 2.79
472  sp[d-3] *= sin(phi[d-3])*cos(phi[d-2]-M_PI/2.) ;
473  sp[d-2] *= sin(phi[d-3])*sin(phi[d-2]-M_PI/2.) ;
474  sp[d-1] *= cos(phi[d-3]) ;
475  }
476  else
477  {
478  //********** Version agreeing with the Threejs visualisation
479  sp[d-3] *= cos(phi[d-3]) ;
480  sp[d-2] *= sin(phi[d-3])*cos(-phi[d-2]) ;
481  sp[d-1] *= sin(phi[d-3])*sin(-phi[d-2]) ;
482  }
483 
484  //dispvector(sp) ;
485  // Now sp should be right, let's check
486  //printf("Checking the point on surface: {%g} {%g} should be equal\n", Tools::norm(sp), R[i] ) ;
487  // Rotating the point vector back in dimensions, and then rotating in space according to the basis A
488  rotate(sp.begin(), sp.begin()+((d-nrotate)%d), sp.end()) ;
489  Tools<d>::matvecmult(spturned, A[i], sp) ;
490  // and ... rotating back :)
491  rotate(spturned.begin(), spturned.begin()+nrotate, spturned.end()) ;
492  Tools<d>::hyperspherical_xtophi (spturned, phinew) ;
493  /*if (i==9)
494  {
495  printf("=======================\n") ;
496  dispvector(sp) ;
497  dispvector(A[i]) ;
498  dispvector(spturned) ;
499  //printf("%g %g %g %g| %g %g %g %g\n", phi[0], phi[1], phi[2], phi[3], phinew[0], phinew[1], phinew[2], phinew[3]) ;
500  }*/
501  //if (phi[1]==0) phi[1]=M_PI ;
502  phi2color (img.begin() + imgx0 * 3 + k*3 + j*stride*3, phinew, d, colors) ;
503  }
504 
505  if (singlefiles)
506  {
507  char path[5000] ;
508  filepathname(path, i, time, View) ;
509  write_img(path, Ntheta, Nlambda, img.data()) ;
510  filerendered.push_back(path);
511  }
512  else
513  {
514  imgx0 += Ntheta ;
515  if (imgx0 >= Ntheta * FilePerLine) imgx0 = 0 + i/FilePerLine * (Ntheta*Nlambda*FilePerLine) ;
516  }
517 }
518 
519 if (!singlefiles)
520 {
521  char path[5000] ;
522  filepathname(path, time, View) ;
523  write_img(path, Ntheta*FilePerLine, Nlambda * (N/FilePerLine +1), img.data()) ;
524  filerendered.push_back(path);
525 }
526 return ;
527 }
528 //--------------------------------------------------------
529 template <int d>
531 {
532  // Set Lambda and Theta grids
533  if (nb>0 && nb<16)
534  Nlambda=Ntheta=(1<<nb);
535  else if (nb>=16)
536  Nlambda=Ntheta=nb ;
537  else
538  {
539  colors=allcolors[1] ;
540  write_colormap_vtk(4, colors) ;
541  exit(0) ;
542  }
543  lambdagrid.resize(Nlambda,0) ;
544  thetagrid.resize(Ntheta,0) ; //lambda:latitude (0:pi), theta: longitude (0:2pi)
545 
546  // Setting up the grid in latitude-longitude
547  for (int i=0 ; i<Nlambda ; i++) lambdagrid[i]= M_PI/(2.*Nlambda)+ M_PI/Nlambda*i ;
548  for (int i=0 ; i<Ntheta-1 ; i++) thetagrid[i] =2*M_PI/(2.*(Ntheta-1) )+2*M_PI/(Ntheta-1) *i ;
549  thetagrid[Ntheta-1]=thetagrid[0];
550  return 0 ;
551 }
552 //=================================================
553 template <int d>
555 {
556 if (d>3) //All view dimensions are NaN if d==3
557 {
558  int nrotate=0 ;
559  while (isnan(View[0]))
560  {
561  rotate(View.begin(), View.begin()+1 , View.end()) ;
562  nrotate++ ;
563  }
564  if (nrotate==0)
565  {
566  auto b = find_if(View.begin(), View.end(), [](double dd) { return std::isnan(dd); } ) ;
567  rotate(View.begin(), b+3, View.end()) ;
568  nrotate = b-View.begin()+3 ;
569  }
570  nrotate %= View.size() ;
571 return nrotate ;
572 }
573 else return 0 ;
574 }
575 //====================================================
576 template <int d>
577 void Texturing<d>::filepathname (char * path, int n, int time, cv1d &View)
578 {
579  char tmp[1000] ;
580  sprintf (path, "%s/Texture-%d-%05d", DirectorySave.c_str(), n, time) ;
581  for (uint i=0 ; i<d-3 ; i++)
582  {
583  strcpy(tmp, path) ;
584  sprintf(path, "%s-%.1f", tmp, View[i]) ;
585  }
586  strcat(path, ".png") ;
587 }
588 template <int d>
589 void Texturing<d>::filepathname (char * path, int time, cv1d &View)
590 {
591  char tmp[1000] ;
592  sprintf (path, "%s/TextureTile-%05d", DirectorySave.c_str(), time) ;
593  for (uint i=0 ; i<d-3 ; i++)
594  {
595  strcpy(tmp, path) ;
596  sprintf(path, "%s-%.1f", tmp, View[i]) ;
597  }
598  strcat(path, ".png") ;
599 }
600 //================================================
601 template <int d>
603  write_colormap_vtk(d, colors) ;
604  return 0 ;
605 }
606 template <int d>
607 int Texturing<d>::write_colormap_nrrd_base (map <string,string> args){
608  write_NrrdIO(args["path"], d, colors) ;
609  return 0 ;
610 }
612 template <int d>
613 int Texturing<d>::write_vtkmap (map <string,string> args)
614 {
615  v1d View ; int nrotate=3 ;
616  View.push_back(atof(args["x4"].c_str())) ;
617  int time = atoi(args["ts"].c_str()) ;
618  int idx = atoi(args["N"].c_str()) ;
619 
620  v1d sp (d,0) ; v1d spturned (d,0) ; // Surface point (point on the surface of the sphere)
621  v1d phi (d-1,0), phinew(d-1,0) ; // Angles of the hyperspherical coordinates. All angles between 0 and pi, except the last one between 0 and 2pi
622  vector<uint8_t> img ;
623 
624  img.resize(3*Nlambda*(Ntheta-1),0) ;
625 
626  FILE *vtkout ;
627  char path[5000] ;
628  sprintf(path,"Colormap-Surface-%d-%d.vtk", idx, time) ;
629  vtkout=fopen(path, "w") ;
630  fprintf(vtkout,"# vtk DataFile Version 2.0\nTexture surface for ND DEM\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS %d float\n", Nlambda*(Ntheta-1)) ;
631 
632  // Check if we are in view
633  double rsqr = R[idx]*R[idx] ;
634  for (uint j=0 ; j<d-3 ; j++)
635  rsqr -= (View[j]-Ts[time].X[idx][j])*(View[j]-Ts[time].X[idx][j]) ;
636  if (rsqr<=0)
637  return -1 ;
638 
639  // We are in view, let's get to it let's get the first phi's (constants)
640  for (uint j=0 ; j<d-3 ; j++)
641  {
642  double cosine = (View[j]-Ts[time].X[idx][j])/R[idx] ;
643  for (uint k=0 ; k<j ; k++)
644  cosine /= sin(phi[k]) ;
645  phi[j] = acos(cosine) ;
646  }
647 
648  for (int j = 0 ; j<Nlambda ; j++)
649  for (int k=0 ; k<Ntheta-1 ; k++)
650  {
651 
652  // Finalising the phi array (useless, but just because
653  phi[d-3]=lambdagrid[j] ;
654  phi[d-2]=thetagrid[k] ;
655 
656  for (uint dd=0 ; dd<d-3 ; dd++) {sp[dd]=View[dd]-Ts[time].X[idx][dd] ;}
657  //sp = View-X[i] ; // All the dimensions except the last 3 are now correct
658  sp[d-3] = R[idx] ;
659  for (uint j=0 ; j<d-3 ; j++) sp[d-3] *= sin(phi[j]) ;
660  sp[d-2]=sp[d-3] ; sp[d-1]=sp[d-3] ;
661  sp[d-3] *= cos(phi[d-3]) ;
662  sp[d-2] *= sin(phi[d-3])*cos(phi[d-2]) ;
663  sp[d-1] *= sin(phi[d-3])*sin(phi[d-2]) ;
664  //dispvector(sp) ;
665  // Now sp should be right, let's check
666  //printf("Checking the point on surface: {%g} {%g} should be equal\n", Tools::norm(sp), R[i] ) ;
667  // Rotating the point vector back in dimensions, and then rotating in space according to the basis A
668  rotate(sp.begin(), sp.begin()+((d-nrotate)%d), sp.end()) ;
669  Tools<d>::matvecmult(spturned, Ts[time].A[idx], sp) ;
670  // and ... rotating back :)
671  rotate(spturned.begin(), spturned.begin()+nrotate, spturned.end()) ;
672  Tools<d>::hyperspherical_xtophi (spturned, phinew) ;
673 
674  fprintf(vtkout, "%g %g %g\n", phinew[0], phinew[1], phinew[2]) ;
675 
676  phi2color (img.begin()+j*(Ntheta-1)*3+k*3, phinew, d, colors) ;
677  }
678 
679  fprintf(vtkout, "\nCELLS %d %d\n", (Nlambda-1)*(Ntheta-2), (Nlambda-1)*(Ntheta-2)*5 ) ;
680  for (int i=0 ; i<Nlambda-1 ; i++)
681  for (int j=0 ; j<Ntheta-2 ; j++)
682  fprintf(vtkout, "4 %d %d %d %d\n", i*(Ntheta-1)+j, i*(Ntheta-1)+j+1, (i+1)*(Ntheta-1)+j+1, (i+1)*(Ntheta-1)+j) ;
683 
684  fprintf(vtkout, "\nCELL_TYPES %d\n", (Nlambda-1)*(Ntheta-2)) ;
685  for (int i=0 ; i<(Nlambda-1)*(Ntheta-2) ; i++) fprintf(vtkout, "9 ") ;
686  fprintf(vtkout, "\n") ;
687 
688  fprintf(vtkout, "\nPOINT_DATA %d\nCOLOR_SCALARS Color 3\n", Nlambda*(Ntheta-1)) ;
689  for (int j = 0 ; j<Nlambda ; j++)
690  for (int k=0 ; k<Ntheta-1 ; k++)
691  fprintf(vtkout, "%g %g %g\n", img[j*(Ntheta-1)*3+k*3]/256., img[j*(Ntheta-1)*3+k*3+1]/256., img[j*(Ntheta-1)*3+k*3+2]/256.) ;
692  fclose(vtkout) ;
693 
694  return 0 ;
695 }
696 
697 
Handles all the computation for the textures.
Definition: Texturing.h:39
v2d Boundaries
List of boundaries.
Definition: Texturing.h:66
vector< vector< float > > colors
Colors vector for the different dimensions.
Definition: Texturing.h:43
vector< int > TsName
Actual integer timestep.
Definition: Texturing.h:69
vector< int > NewViewPoint
Used if the location&timestep require a modification. Eventually transfered to ViewPoint when the ren...
Definition: Texturing.h:73
v1d lambdagrid
Pixel grid in latitude.
Definition: Texturing.h:56
bool justloaded
Keep track if no render happened yet (used for the 3D simulation)
Definition: Texturing.h:78
int nrotate
Definition: Texturing.h:79
v1d thetagrid
Pixel grid in longitude.
Definition: Texturing.h:57
vector< std::thread > Threads
Rendering thread list.
Definition: Texturing.h:81
vector< int > RenderedAlready
Keeps track of what location/timesteps have already been rendered and do not need to be recomputed.
Definition: Texturing.h:74
vector< Timestep > Ts
List of Timestep.
Definition: Texturing.h:68
void rescale(v1f &c, cv1f sum)
Coloring rescaling.
v1d R
Particle radii.
Definition: Texturing.h:70
v1d View
Location of the rendering in the ND space.
Definition: Texturing.h:71
vector< int > ViewPoint
Current location&timestep for rendering.
Definition: Texturing.h:72
bool runfast
Render only the current location&timestep, not doing any additional rendering for caching purposes.
Definition: Texturing.h:75
bool singlerendered
Render a single location&timestep.
Definition: Texturing.h:76
int N
Number of grains.
Definition: Texturing.h:65
vector< vector< string > > FileList
Data file list.
Definition: Texturing.h:80
Individual timestep data.
Definition: Texturing.h:31
v2d X
Particle locations.
Definition: Texturing.h:33
v2d A
Particle attached frame.
Definition: Texturing.h:34
const vector< float > cv1f
Definition: Typedefs.h:16
vector< vector< double > > v2d
Definition: Typedefs.h:10
vector< float > v1f
Definition: Typedefs.h:12
unsigned int uint
Definition: Typedefs.h:8
static void matvecmult(v1d &res, cv1d &A, cv1d &B)
Multiply a matrix with a vector, in place.
Definition: Tools.h:701
static double hyperspherical_xtophi(cv1d &x, v1d &phi)
Convert from cartesian to hyperspherical coordinates.
Definition: Tools.h:889
const vector< double > cv1d
Definition: Typedefs.h:13
const vector< vector< double > > cv2d
Definition: Typedefs.h:14
static void transpose_inplace(v1d &a)
Transpose in-place.
Definition: Tools.h:259
static void clear()
Get the class ready for a different dimension.
Definition: Tools.h:339
vector< double > v1d
Definition: Typedefs.h:9
static void initialise()
Initialise the member variables, in particular the variables to handle skew-symmetric flattened matri...
Definition: Tools.h:318
int viewpermute(v1d &View)
Rotate the viewpoint so that the rendered view is using the first 3 dimensions. Effectively unused si...
Definition: Texturing.h:554
int write_vtkmap(map< string, string > args)
Outputs the texture as a vtk surface.
Definition: Texturing.h:613
int csvread_A(const char path[], v2d &result, int d)
Reader for CSV orientation informations.
Definition: io.cpp:21
v1d thetagrid
Definition: io.h:33
void runthread_spaceloop(Texturing< d > *T, v1d View, uint tsint, int nrotate, int dim)
Function to call Texturing::spaceloop()
Definition: Texturing.h:125
uint d
bool blenderrender
Definition: Server.cpp:24
int csvread_XR(const char path[], v2d &result, v1d &R, int d)
Reader for CSV location informations.
Definition: io.cpp:48
void filepathname(char *path, int n, int time, cv1d &View)
Generates the proper texture name.
Definition: Texturing.h:577
void dispvector(const v1d &a)
Convenient function to print a vector on screen.
Definition: Texturing.h:116
int SetNewViewPoint(map< string, string > args)
Modify the current location and/or timestep en render.
Definition: Texturing.h:247
void hereandnow(v1d View, uint tsint, int nrotate)
Render the current location at the current timestep.
Definition: Texturing.h:398
int write_colormap_vtk_base()
Output the colormap as a vtk volume.
Definition: Texturing.h:602
int set_grid(int nb)
Set the grid in latitude-longitude.
Definition: Texturing.h:530
v1d lambdagrid
int N
void Render(vector< string > &filerendered, cv1d &View, int nrotate, int time, cv2d &X, cv1d &R, cv2d &A)
Do the actual rendering of the textures.
Definition: Texturing.h:409
void phi2color(vector< uint8_t >::iterator px, cv1d &phi, int d, vector< vector< float >> &colors)
Convert from hyperspherical coordinates to actual pixel color, using the provided vector of colors.
Definition: Texturing.cpp:18
#define FilePerLine
Line size for single file tiled output.
Definition: Texturing.h:25
int clean()
Clean the data to get ready for another simulation rendering.
Definition: Texturing.h:210
void runthread_timeloop(Texturing< d > *T, v1d View, uint tsint, int nrotate)
Function to call Texturing::timeloop()
Definition: Texturing.h:121
int write_colormap_nrrd_base(map< string, string > args)
Output the texture as an NRRD file.
Definition: Texturing.h:607
void timeloop(v1d View, uint tsint, int nrotate)
Run all the rendering for the curent timestep, for all other location in dimensions higher than 3D vi...
Definition: Texturing.h:376
int write_colormap_vtk(int d, vector< vector< float >> &colors)
Writer for VTK colormaps.
Definition: io.cpp:77
int MasterRender()
Handle the rendering threads.
Definition: Texturing.h:297
#define DeltaX
Step in location for the visualisation.
Definition: Texturing.h:24
string DirectorySave
int initialise(map< string, string > args)
Loads all the data for the requested simulation in memory.
Definition: Texturing.h:130
void spaceloop(v1d View, uint tsint, int nrotate, int dim)
Run all the rendering in the current location, at all timesteps.
Definition: Texturing.h:351
v2d Boundaries
int write_img(char path[], int w, int h, uint8_t *px)
Write for png textures.
Definition: io.cpp:6
int write_NrrdIO(string path, int d, vector< vector< float >> &colors)
Writer for NRRD colormaps.
Definition: io.cpp:116
bool isrendered()
Verify if the current location/timestep is already rendered.
Definition: Texturing.h:277
void filepathname(char *path, int n, int time, cv1d View)
Filename generator.
Definition: json.hpp:5678
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1181
PUGI_IMPL_FN void sort(I begin, I end, const Pred &pred)
Definition: pugixml.cpp:7707