VTKFIG  0.20.20181114
Easy VTK based in situ visualization
vtkfigMainThread-2018-01-26-2205.cxx
Go to the documentation of this file.
1 #include <stdexcept>
2 #include <chrono>
3 
4 #include <vtkRenderWindow.h>
5 #include <vtkRenderWindowInteractor.h>
6 #include <vtkInteractorStyleTrackballCamera.h>
7 #include <vtkWindowToImageFilter.h>
8 #include <vtkPNGWriter.h>
9 #include <vtkCommand.h>
10 #include <vtkProperty.h>
11 #include <vtkProperty2D.h>
12 #include <vtkObjectBase.h>
13 #include <vtkPropCollection.h>
14 #include <vtkContextScene.h>
15 
16 #include "vtkfigFrame.h"
17 #include "vtkfigFigure.h"
18 #include "vtkfigMainThread.h"
19 #include "config.h"
20 
21 
22 namespace vtkfig
23 {
24  namespace internals
25  {
26  MainThread * MainThread::mainthread=0;
27 
29  {
30 
31  if (mainthread==0) return;
32  for (auto& frame :mainthread->framemap)
33  {
34  for (auto & subframe: frame.second->subframes)
35  subframe.renderer->RemoveAllViewProps();
36  frame.second->window->Finalize();
37 
38  }
39  mainthread->framemap.clear();
40  mainthread->interactor->TerminateApp();
41  }
42 
43 
45  {
46  if (mainthread==0)
47  mainthread=new MainThread();
48  std::atexit(DeleteMainThread);
49  return mainthread;
50  }
51 
53  {
54  int wtime=5;
55  char* port_string= getenv("VTKFIG_PORT_NUMBER");
56  char* wtime_string=getenv("VTKFIG_WAIT_SECONDS");
57  char *debug_string=getenv("VTKFIG_DEBUG");
58  char *multi_string=getenv("VTKFIG_MULTITHREADED");
59  char *dbuff_string=getenv("VTKFIG_DOUBLEBUFFER");
60 
61 
62 
63  if (debug_string!=0)
64  debug_level=atoi(debug_string);
65 
66 
67 #if XXXCONFIG_APPLE
69  if (multi_string!=0 && atoi(multi_string))
70  {
71  if (debug_level>0)
72  cout << "overriding multithreading default (off) on APPLE" << endl;
74  }
75 #endif
77  if (multi_string!=0 && !atoi(multi_string))
78  {
79  if (debug_level>0)
80  cout << "overriding multithreading default (on) on" << endl;
82  }
83 
84  if (dbuff_string!=0)
85  this->double_buffering=atoi(dbuff_string);
86 
87 
88  if (wtime_string!=0)
89  wtime=atoi(wtime_string);
90 
91 
92  if (port_string!=0)
93  {
94  int port=atoi(port_string);
95  if (port<=0)
96  throw std::runtime_error("Invalid port number for server");
97  OpenConnection(port,wtime);
98  }
99 
100  if (debug_level>0)
101  {
102  char sc='c';
103  if (connection_open)
104  sc='s';
105 
107  cout << sc<< " try running multithreaded" << endl;
108  else
109  cout << sc<<" try running single threaded" << endl;
110  }
111  }
112 
113 
114  void MainThread::OpenConnection(int port, int wtime)
115  {
116  if (connection_open) return;
117 
118  cout << "Server start listening on port "<< port << endl;
119  communicator=vtkSmartPointer<Communicator>::New();
120  communicator->server_listen_num_retry=1;
121  communicator->server_listen_waiting_time=1000*wtime;
122  int rc=communicator->ServerConnect(port);
123  if (rc)
124  cout << "Server connected" << endl;
125  else
126  {
127  cout << "Nobody is listening ... giving up" << endl;
128  throw std::runtime_error("Server connection failed");
129  exit(1);
130  }
131  connection_open=true;
132  }
133 
135  {
136  if (debug_level>0)
137  cout << " ~mt" << endl;
138  if (this->running_multithreaded)
139  {
140  std::this_thread::sleep_for(std::chrono::milliseconds(10));
141  Terminate();
142  std::this_thread::sleep_for(std::chrono::milliseconds(10));
143  this->thread->join();
144  }
145  else
146  Terminate();
147 
148  framemap.clear();
149  }
150 
151 
152 
154  {
155  if (connection_open)
157  else if (interactor)
158  interactor->Start();
159  }
160 
162  {
163  frame->mainthread=this;
165  this->iframe=lastframenum;
166  framemap[lastframenum++]=frame;
167  if (lastframenum==1)
168  {
170  {
171  Start();
172  }
173  else
174  {
175  if (connection_open)
176  {
179  }
180  else
181  {
182  PrepareRenderThread(this);
183  }
184  }
185  }
186  else
187  {
189  }
190  }
191 
192 
194  {
195  assert(frame==framemap[frame->number_in_frame_list]);
197  frame->number_in_frame_list=-1;
198  }
199 
201  {
203  }
204 
205 
207  {
208  this->communication_blocked=true;
209 
211 
212  do
213  {
214  std::this_thread::sleep_for (std::chrono::milliseconds(10));
215  if (!this->running_multithreaded)
216  Show();
217  }
218  while (this->communication_blocked);
219 
220  }
221 
222 
223  void MainThread::SendCommand(int number_in_frame_list, const std::string from, Communicator::Command cmd)
224  {
225  if (debug_level>0)
226  cout << "mt " << from << " " << number_in_frame_list << endl;
227 
228 
229  this->cmd=cmd;
230  this->iframe=number_in_frame_list;
232  {
233  std::unique_lock<std::mutex> lock(this->mutex);
234  this->condition_variable.wait(lock);
235  }
236  else
237  Update();
238  }
239 
241  {
243  }
244 
245 
246 
250  class MyInteractorStyle : public vtkInteractorStyleTrackballCamera
251  {
252 
254  std::vector<Figure*>edited_figures;
255 
257  bool edit_mode =false;
258 
260  bool left_button_down=false;
261 
263  int lastx=0;
264 
266  int lasty=0;
267 
268 
270  Frame *frame=0;
271 
272 
273  public:
274 
275 
276 
278  {
279  return new MyInteractorStyle();
280  }
281 
282  MyInteractorStyle(): vtkInteractorStyleTrackballCamera() {};
283 
284  void SetFrame(Frame *f)
285  {
286  this->frame=f;
287  }
288 
289  virtual void OnConfigure()
290  {
291  for (auto & figure: frame->figures)
292  {
293  for (auto & actor: figure->ctxactors)
294  actor->GetScene()->SetDirty(true);
295  }
296  vtkInteractorStyleTrackballCamera::OnConfigure();
297  }
298 
300  virtual void OnLeftButtonDown()
301  {
302 
303 
306  if (this->edit_mode)
307  {
308  this->left_button_down=true;
309  lastx=this->Interactor->GetEventPosition()[0];
310  lasty=this->Interactor->GetEventPosition()[1];
311  }
312  else
313  vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
314  }
315 
317  virtual void OnLeftButtonUp()
318  {
319  for (auto &figure: frame->figures)
320  {
321 
322  if (frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
323  figure->RTShowActive();
324  else
325  figure->RTShowInActive();
326  frame->window->Render();
327  }
328 
330  if (this->left_button_down)
331  this->left_button_down=false;
332  else
333  vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
334  }
335 
337  virtual void OnMouseMove()
338  {
339 
340 
342  if (this->left_button_down)
343  {
344  // Calculate difference between old and
345  // new mouse position
346  int thisx=this->Interactor->GetEventPosition()[0];
347  int thisy=this->Interactor->GetEventPosition()[1];
348  int dx=thisx-lastx;
349  int dy=thisy-lasty;
350 
351  // Pass to all edited figures
352  for (auto figure:this->edited_figures)
353  figure->RTProcessMove(dx,dy);
354 
355  // Render changed figure
356  this->Interactor->Render();
357 
358  // Set new old position
359  lastx=thisx;
360  lasty=thisy;
361  }
362  else
363  vtkInteractorStyleTrackballCamera::OnMouseMove();
364  }
365 
367  virtual void OnChar()
368  {
369  // Get the key pressed
370  std::string key = this->Interactor->GetKeySym();
371 
372  //cout << key << endl;
373 
374  // disable some standard vtk keys
375  if(key== "f") {}
376 
377  // q -> exit
378  else if(key == "q")
379  {
380  exit(0);
381  }
382 
383  // Reset Camera
384  else if(key == "r")
385  {
386  for (auto & subframe: this->frame->subframes)
387  {
388  if (subframe.renderer==this->CurrentRenderer)
389  {
390  frame->RTResetCamera(subframe);
391  }
392  }
393  this->Interactor->Render();
394  }
395 
396  // Toggle wireframe
397  else if(key == "w")
398  {
399  for (auto &figure: this->frame->figures)
400  if (this->frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
401  {
402  figure->state.wireframe=!figure->state.wireframe;
403  if (figure->state.wireframe)
404  for (auto & actor: figure->actors) actor->GetProperty()->SetRepresentationToWireframe();
405  else
406  for (auto& actor: figure->actors) actor->GetProperty()->SetRepresentationToSurface();
407  this->Interactor->Render();
408  }
409 
410  }
411 
412  // Write output to png
413  else if (key=="p")
414  {
415 
416  // Generate file name using current time
417  auto now = std::chrono::system_clock::now();
418  auto time = std::chrono::system_clock::to_time_t(now);
419  std::tm * ttm = localtime(&time);
420  char time_str[] = "yyyy-mm-ddTHH:MM:SS ";
421  strftime(time_str, strlen(time_str), "%Y-%m-%dT%H:%M:%S", ttm);
422  auto fname=frame->parameter.wintitle+"-"+time_str+".png";
423 
424  auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
425  imgfilter->SetInput(frame->window);
426  imgfilter->Update();
427 
428  auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
429  pngwriter->SetInputConnection(imgfilter->GetOutputPort());
430  pngwriter->SetFileName(fname.c_str());
431 
432  this->Interactor->Render();
433  pngwriter->Write();
434 
435  cout << "Frame written to "<< fname << endl;
436  }
437 
438  // Keys which toggle editing
439  else if (key == "x" || key== "y" || key== "z" || key== "l" || key== "a")
440  {
441  if (!this->edit_mode)
442  {
443 
444  this->edit_mode=true;
448  for (auto &figure: frame->figures)
449  {
450 
451  if (
452  frame->subframes[figure->framepos].renderer==this->CurrentRenderer
453  // &&(
454  // (key=="a" && figure->SubClassName()=="Quiver")
455  // ||
456  // (key=="x" && figure->SubClassName()=="SurfaceContour")
457  // ||
458  // (key=="y" && figure->SubClassName()=="SurfaceContour")
459  // ||
460  // (key=="z" && figure->SubClassName()=="SurfaceContour")
461  // ||
462  // (key=="l" && figure->SubClassName()=="SurfaceContour")
463  // )
464  )
465  this->edited_figures.push_back(figure);
466  }
467  }
468 
470  for (auto figure : this->edited_figures)
471  figure->RTProcessKey(key);
472  this->Interactor->Render();
473  }
474 
475 
476  // Emulate mouse move for all edited figures
477  else if(key == "Left" || key== "Down")
478  {
479  if (this->edit_mode)
480  {
481  for (auto figure : this->edited_figures)
482  figure->RTProcessMove(-1,-1);
483  this->Interactor->Render();
484  }
485  }
486 
487  // Emulate mouse move for all edited figures
488  else if(key == "Right" || key== "Up")
489  {
490  if (this->edit_mode)
491  {
492  for (auto figure : this->edited_figures)
493  figure->RTProcessMove(1,1);
494  this->Interactor->Render();
495  }
496  }
497 
498  // These are interaction keys in edit mode
499  else if(key == "Return" || key=="Delete")
500  {
501  if (this->edit_mode)
502  {
503  for (auto figure : this->edited_figures)
504  figure->RTProcessKey(key);
505  this->Interactor->Render();
506  }
507  }
508 
509  // Escape ends edit mode
510  else if(key == "Escape")
511  {
512  this->edit_mode=false;
513  for (auto figure : this->edited_figures)
514  {
515  figure->RTProcessKey(key);
516  figure->RTMessage("");
517  }
518  this->Interactor->Render();
519  this->edited_figures.resize(0);
520  this->Interactor->Render();
521  }
522 
523  // Toggle some states independent of edit mode
524  else if(key == "I" || key== "L" || key == "E" || key == "S" || key == "slash" || key == "B" || key == "C" || key == "O"|| key == "A")
525  {
526  for (auto &figure: frame->figures)
527  if (frame->subframes[figure->framepos].renderer==this->CurrentRenderer)
528  figure->RTProcessKey(key);
529 
530  this->Interactor->Render();
531  }
532 
533  // Block/unblock calculation
534  else if (key=="space")
535  {
538  frame->title_actor->SetText(6,"-|-");
539  else
540  frame->title_actor->SetText(6,"---");
541  frame->title_actor->Modified();
542  frame->window->Render();
543  }
544 
545  // Block/unblock calculation
546  else if (key=="BackSpace")
547  {
549  if (!frame->mainthread->communication_blocked)
550  frame->step_number=std::max(frame->step_number-2,0);
551 
552  }
553 
554  else if (key=="asterisk")
555  {
556  if (!frame->single_subframe_view)
557  for(int i=0;i<this->frame->subframes.size();i++)
558  {
559  if (this->frame->subframes[i].renderer==this->CurrentRenderer)
560  this->frame->active_subframe=i;
561  }
562 
564  frame->RTSetSingleView(frame->single_subframe_view);
565  this->Interactor->Render();
566  }
567 
568 
569  else if (frame->single_subframe_view && key=="Next")
570  {
571  frame->RTSetActiveSubFrame(frame->active_subframe-1,true);
572  this->Interactor->Render();
573  }
574 
575  else if (frame->single_subframe_view && key=="Prior")
576  {
577  frame->RTSetActiveSubFrame(frame->active_subframe+1,true);
578  this->Interactor->Render();
579  }
580 
581 
582 
583  // Print help string
584  else if(key == "h" or key == "question")
585  {
586  cout << Frame::KeyboardHelp;
587  }
588 
589  // Pass other keys to base
590  else
591  {
592  vtkInteractorStyleTrackballCamera::OnChar();
593  }
594  }
595  };
596 
597 
598 
601  class MyTimerCallback : public vtkCommand
602  {
603  public:
604  // Main thread to interact with
606 
607 
608  vtkSmartPointer<vtkRenderWindowInteractor> Interactor=0;
609 
610  static MyTimerCallback *New() {return new MyTimerCallback;}
611 
612 
613  virtual void Execute(
614  vtkObject *vtkNotUsed(caller),
615  unsigned long eventId,
616  void *vtkNotUsed(callData)
617  )
618  {
619 
620 
621  if (this->mainthread->communication_blocked && mainthread->cmd != Communicator::Command::MainThreadShow) return;
622 
623  if (
624  vtkCommand::TimerEvent == eventId // Check if timer event
625  && this->mainthread->cmd!=Communicator::Command::Empty // Check if command has been given
626  )
627  {
628 
629 
630  // Lock mutex
631  if (this->mainthread->running_multithreaded)
632  std::unique_lock<std::mutex> lock(this->mainthread->mutex);
633 
634  // Command dispatch
635  switch(mainthread->cmd)
636  {
637 
638  // Add frame to main thread
640  {
641  mainthread->RTAddFrame(mainthread, mainthread->iframe);
642  }
643  break;
644 
645  // Remove frame from mainthread
647  {
648 
649  auto frame=mainthread->framemap[mainthread->iframe];
650  for (auto & subframe: frame->subframes)
651  subframe.renderer->RemoveAllViewProps();
652 
653  frame->window->Finalize();
654 
655  mainthread->framemap.erase(frame->number_in_frame_list);
656 
657  }
658  break;
659 
660 
661 
663  {
664  // Add actors from figures to renderer
665  for (auto & framepair: mainthread->framemap)
666  framepair.second->RTAddFigures();
667 
668 
669 
670  for (auto & framepair: mainthread->framemap)
671  {
672  auto frame=framepair.second;
673 
674  if(frame->mainthread->communication_blocked)
675  frame->title_actor->SetText(6,"-|-");
676  else
677  frame->title_actor->SetText(6,"---");
678 
679  frame->title_actor->Modified();
680 
681  // for (auto & figure: framepair.second->figures)
682  // figure->RTUpdateActors();
683  frame->window->Render();
684  if (frame->videowriter && ! frame->mainthread->communication_blocked)
685  {
686  this->Interactor->Render();
687  auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
688  imgfilter->SetInput(frame->window);
689  imgfilter->Update();
690  frame->videowriter->SetInputConnection(imgfilter->GetOutputPort());
691  this->Interactor->Render();
692  frame->videowriter->Write();
693  }
694  }
695  //this->Interactor->Render();
696  }
697  break;
698 
699  // Write picture to file
701  {
702  auto frame=mainthread->framemap[mainthread->iframe];
703  auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
704  auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
705 
706  pngwriter->SetInputConnection(imgfilter->GetOutputPort());
707  pngwriter->SetFileName(frame->parameter.filename.c_str());
708 
709  imgfilter->SetInput(frame->window);
710  imgfilter->Update();
711 
712  this->Interactor->Render();
713  pngwriter->Write();
714  }
715  break;
716 
717  // Start video
719  {
720  auto frame=mainthread->framemap[mainthread->iframe];
721 
722  frame->videowriter = vtkSmartPointer<vtkOggTheoraWriter>::New();
723  frame->videowriter->SetFileName(frame->parameter.filename.c_str());
724  frame->videowriter->Start();
725  }
726  break;
727 
729  {
730  auto frame=mainthread->framemap[mainthread->iframe];
731  frame->videowriter->End();
732  frame->videowriter=0;
733  }
734  break;
735 
737  {
738  auto frame=mainthread->framemap[mainthread->iframe];
739  frame->RTRemoveFigure(frame->parameter.current_figure);
740  }
741  break;
742 
743 
745  {
746  auto frame=mainthread->framemap[mainthread->iframe];
747  frame->RTSetLayout(frame->parameter.nvpx,frame->parameter.nvpy);
748  frame->RTResetRenderers(false);
749  }
750 
751  // Set frame size
753  {
754  auto frame=mainthread->framemap[mainthread->iframe];
755  frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
756  }
757  break;
758 
759  // Set active subframe
761  {
762  auto frame=mainthread->framemap[mainthread->iframe];
763  frame->RTSetActiveSubFrame(frame->parameter.active_subframe,false);
764  }
765  break;
766 
767  // Set active subframe
769  {
770  auto frame=mainthread->framemap[mainthread->iframe];
771  auto& subframe=frame->subframes[frame->parameter.active_subframe];
772  frame->RTSetActiveSubFrameCameraViewAngle(subframe,frame->parameter.camera_view_angle);
773  }
774  break;
775 
776  // Set active subframe
778  {
779  auto frame=mainthread->framemap[mainthread->iframe];
780  auto& subframe=frame->subframes[frame->parameter.active_subframe];
781  frame->RTSetActiveSubFrameCameraPosition(subframe,frame->parameter.camera_position);
782  }
783  break;
784 
785  // Set active subframe
787  {
788  auto frame=mainthread->framemap[mainthread->iframe];
789  auto& subframe=frame->subframes[frame->parameter.active_subframe];
790  frame->RTSetActiveSubFrameCameraFocalPoint(subframe,frame->parameter.camera_focal_point);
791  }
792  break;
793 
795  {
796  auto frame=mainthread->framemap[mainthread->iframe];
797  frame->RTSetSingleView(frame->parameter.single_subframe_view);
798  }
799  break;
800 
801 
802 
803  // Set frame position
805  {
806  auto frame=mainthread->framemap[mainthread->iframe];
807  frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
808  }
809  break;
810 
811  // Set frame title
813  {
814  auto frame=mainthread->framemap[mainthread->iframe];
815  frame->RTInit();
816  frame->title_actor->SetText(7,frame->parameter.frametitle.c_str());
817  frame->title_actor->Modified();
818 
819  }
820  break;
821 
822  // Set window title
824  {
825  auto frame=mainthread->framemap[mainthread->iframe];
826  frame->window->SetWindowName(frame->parameter.wintitle.c_str());
827  }
828  break;
829 
830  // Link camera to other
832  {
833  auto frame=mainthread->framemap[mainthread->iframe];
834  auto renderer=mainthread->framemap[mainthread->iframe]->subframes[frame->parameter.camlinkthisframepos].renderer;
835  auto lrenderer=mainthread->framemap[frame->parameter.camlinkframenum]->subframes[frame->parameter.camlinkframepos].renderer;
836  renderer->SetActiveCamera(lrenderer->GetActiveCamera());
837  }
838  break;
839 
840  // Terminate
842  {
843 
844  for (auto & framepair: mainthread->framemap)
845  framepair.second->window->Finalize();
846 
847  mainthread->framemap.clear();
848 
849  this->Interactor->TerminateApp();
850 
851  mainthread->running_multithreaded=false;
852 
853  mainthread->condition_variable.notify_all();
854 
855  return;
856  }
857  break;
858 
859  default:;
860  }
861 
862  // Clear command
863  mainthread->cmd=Communicator::Command::Empty;
864 
865  // Notify that command was exeuted
866  if (mainthread->running_multithreaded)
867  //
868  mainthread->condition_variable.notify_all();
869  else
870  // dirty trick to unblock event loop.
871  // hopefully works if multitreading does not
872  mainthread->interactor->TerminateApp();
873 
874  }
875  }
876  };
877 
878 
879  void MainThread::RTAddFrame(MainThread* mainthread, int iframe)
880  {
881  auto frame=mainthread->framemap[iframe];
882  frame->window = vtkSmartPointer<vtkRenderWindow>::New();
883  frame->window->SetWindowName("vtkfig");
884 
885  if (mainthread->double_buffering)
886  frame->window->DoubleBufferOn();
887  else
888  frame->window->DoubleBufferOff();
889 
890  frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
891  frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
892 
893  frame->RTResetRenderers(true);
894 
895  frame->RTInit();
896  frame->title_subframe.renderer->AddActor(frame->title_actor);
897  frame->title_actor->SetText(6,"---");
898  frame->title_actor->SetText(7,frame->parameter.frametitle.c_str());
899 
900  }
901 
903  {
904  RTAddFrame(mainthread,0);
905  auto frame=mainthread->framemap[0];
906 
907  mainthread->interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
908  auto style = vtkSmartPointer<MyInteractorStyle>::New();
909  style->SetFrame(frame);
910  mainthread->interactor->SetInteractorStyle(style);
911 
912  mainthread->interactor->SetRenderWindow(frame->window);
913 
914  auto callback = vtkSmartPointer<MyTimerCallback>::New();
915  callback->Interactor=mainthread->interactor;
916  callback->mainthread=mainthread;
917  mainthread->interactor->AddObserver(vtkCommand::TimerEvent,callback);
918 
919  mainthread->interactor->Initialize();
920 
921  mainthread->interactor->CreateRepeatingTimer(mainthread->timer_interval);
922  }
923 
925  {
926 
928  mainthread->running_multithreaded=true;
929 
930  mainthread->interactor->Start();
931  mainthread->running_multithreaded=false;
932  mainthread->condition_variable.notify_all();
933 
934  mainthread->interactor->SetRenderWindow(0);
935  mainthread->interactor->TerminateApp();
936  mainthread->running_multithreaded=false;
937 
938  //window->Finalize();
939  }
940 
941  void MainThread::Start(void)
942  {
943  if (connection_open)
944  this->thread=std::make_shared<std::thread>(CommunicatorThread,this);
945  else
946  this->thread=std::make_shared<std::thread>(RenderThread,this);
947 
948  do
949  {
950  std::this_thread::sleep_for (std::chrono::milliseconds(10));
951  }
952  while (!this->running_multithreaded);
953  }
954 
955 
959  {
961 
962  }
963 
965  {
966  if (mainthread->cmd!=Communicator::Command::Empty)
967  {
968 
969  // Lock mutex
970  if (mainthread->running_multithreaded)
971  std::unique_lock<std::mutex> lock(mainthread->mutex);
972 
973  if (mainthread->debug_level>0)
974  cout << "s cmd: " << static_cast<int>(mainthread->cmd) << " frame: " <<mainthread->iframe<< endl;
975 
976  mainthread->communicator->SendCommand(mainthread->cmd);
977  mainthread->communicator->SendInt(mainthread->iframe);
978 
979  // Command dispatch
980  switch(mainthread->cmd)
981  {
982 
984  {
985 
986  }
987  break;
988 
990  {
991  auto frame=mainthread->framemap[mainthread->iframe];
992  mainthread->communicator->SendInt(frame->parameter.nvpx);
993  mainthread->communicator->SendInt(frame->parameter.nvpy);
994  frame->nvpx=frame->parameter.nvpx;
995  frame->nvpy=frame->parameter.nvpy;
996  }
997  break;
998 
1000  {
1001  auto frame=mainthread->framemap[mainthread->iframe];
1002  mainthread->communicator->SendInt(frame->parameter.active_subframe);
1003  }
1004  break;
1005 
1007  {
1008 
1009  }
1010  break;
1011 
1013  {
1014  for (auto framepair: mainthread->framemap)
1015  for (auto & figure: framepair.second->figures)
1016  {
1017  figure->SetRange();
1018  figure->ServerRTSendData(mainthread->communicator);
1019  }
1020  }
1021  break;
1022 
1024  {
1025 
1026  auto frame=mainthread->framemap[mainthread->iframe];
1027  mainthread->communicator->SendString(frame->parameter.filename);
1028  }
1029  break;
1030 
1032  {
1033  auto frame=mainthread->framemap[mainthread->iframe];
1034  mainthread->communicator->SendInt(frame->parameter.winsize_x);
1035  mainthread->communicator->SendInt(frame->parameter.winsize_y);
1036  }
1037  break;
1038 
1040  {
1041  auto frame=mainthread->framemap[mainthread->iframe];
1042  mainthread->communicator->SendInt(frame->parameter.winposition_x);
1043  mainthread->communicator->SendInt(frame->parameter.winposition_y);
1044  }
1045  break;
1046 
1048  {
1049  auto frame=mainthread->framemap[mainthread->iframe];
1050  mainthread->communicator->SendString(frame->parameter.frametitle);
1051  }
1052  break;
1053 
1054 
1056  {
1057  auto frame=mainthread->framemap[mainthread->iframe];
1058  mainthread->communicator->SendString(frame->parameter.wintitle);
1059  }
1060  break;
1061 
1062 
1064  {
1065  auto frame=mainthread->framemap[mainthread->iframe];
1066  mainthread->communicator->SendString(frame->parameter.current_figure->SubClassName());
1067  mainthread->communicator->SendInt(frame->parameter.current_figure->framepos);
1068  }
1069  break;
1070 
1072  {
1073  auto frame=mainthread->framemap[mainthread->iframe];
1074  mainthread->communicator->SendString(frame->parameter.current_figure->SubClassName());
1075  mainthread->communicator->SendInt(frame->parameter.current_figure->framepos);
1076  }
1077  break;
1078 
1079 
1081  {
1082  auto frame=mainthread->framemap[mainthread->iframe];
1083  mainthread->communicator->SendInt(frame->parameter.camlinkthisframepos);
1084  mainthread->communicator->SendInt(frame->parameter.camlinkframenum);
1085  mainthread->communicator->SendInt(frame->parameter.camlinkframepos);
1086  }
1087  break;
1088 
1090  {
1091  // for (auto & figure: frame->figures)
1092  // {
1093 
1094  // //frame->communicator->SendCommand(vtkfig::Command::FrameShow);
1095  // }
1096 
1097  }
1098  break;
1099 
1101  // Close window and terminate
1102  {
1103 
1104  if (mainthread->debug_level>0)
1105  cout << "s term" << endl;
1106  mainthread->framemap.clear();
1107  // Notify that command was exeuted
1108  mainthread->condition_variable.notify_all();
1109  mainthread->running_multithreaded=false;
1110  return;
1111  }
1112  break;
1113 
1114  default:
1115  {
1116  cout << "s cmd: " << static_cast<int>(mainthread->cmd) << endl;
1117  throw std::runtime_error("wrong command on server");
1118  }
1119 
1120  break;
1121  }
1122 
1123  // Clear command
1124  mainthread->cmd=Communicator::Command::Empty;
1125 
1126  // Notify that command was exeuted
1127  if (mainthread->running_multithreaded)
1128  mainthread->condition_variable.notify_all();
1129  }
1130 
1131  }
1132 
1134  {
1135  mainthread->running_multithreaded=true;
1136  PrepareCommunicatorThread(mainthread);
1137  while(1)
1138  {
1139  std::this_thread::sleep_for (std::chrono::milliseconds(5));
1141  }
1142  mainthread->running_multithreaded=false;
1143  }
1144 
1145 
1146 
1147  }
1148 
1149 }
void RTSetSingleView(bool single_viewport)
vtkSmartPointer< Communicator > communicator
Communicator object for communication with cliend.
int lastframenum
Number of last frame created.
virtual void OnChar()
Overwrite keyboard callback.
bool communication_blocked
space down state ?
static MainThread * CreateMainThread()
Start thread.
double timer_interval
Timer interval for timer callback.
internals::MainThread * mainthread
The spinning main thread.
Definition: vtkfigFrame.h:408
static MainThread * mainthread
"This" thread
void RTSetActiveSubFrame(int isub, bool hide_old)
Set visible subframe.
void Show()
Show all frames aka nonblocking event loop.
vtkSmartPointer< vtkRenderWindowInteractor > interactor
vtkSmartPointer< vtkRenderWindow > window
Window vontaining frame.
Definition: vtkfigFrame.h:414
void OpenConnection(int port, int wtime)
Open connection to client.
void Start()
Spawn parallel thread for rendering or communication.
Communicator::Command cmd
Communication command.
std::condition_variable condition_variable
Condition variable signalizing finished command.
std::mutex mutex
Mutex to organize communication.
static void PrepareCommunicatorThread(MainThread *)
Prepare comm thread before start.
void Update()
Update all figures in all frames.
std::shared_ptr< std::thread > thread
std::thread which runs rendering resp. communication
bool double_buffering
Use of double buffering.
struct vtkfig::Frame::@2 parameter
Parameters to be passed between threads.
bool connection_open
State of connection to client.
static void PrepareRenderThread(MainThread *)
Prepare render thread before start.
virtual void OnMouseMove()
Overwrite mouse move.
Timer callback handling communication with render thread.
int debug_level
Debug level for client communication.
virtual void Execute(vtkObject *vtkNotUsed(caller), unsigned long eventId, void *vtkNotUsed(callData))
virtual void OnLeftButtonUp()
Overwrite left button up.
int number_in_frame_list
Number of this frame in global frame list.
Definition: vtkfigFrame.h:307
void Interact()
Blocking event loop demanding user interaction unblocked by space key.
void AddFrame(Frame *frame)
Add frame to be handeled by thread.
static void RenderThread(MainThread *)
Callback function for render thread.
Main communication thread.
bool try_running_multithreaded
Toggle multithreaded/single (at startup)
void RemoveFrame(Frame *frame)
Remove frame from thread.
Provide a framework wrapping window+interactor+renderers from vtk.
Definition: vtkfigFrame.h:38
std::string wintitle
Definition: vtkfigFrame.h:381
static void DeleteMainThread()
Kill the thread.
virtual void OnLeftButtonDown()
Overwrite left button down.
void RTResetCamera(SubFrame &sf)
reset camera to default position
void SendCommand(int iframe, const std::string from, Communicator::Command cmd)
Communication with render thread.
static void CommunicatorThread(MainThread *)
Callback function for communicator thread.
std::map< int, Frame * > framemap
Map of all frames handeled by thread.
std::set< Figure * > figures
List of all figures in frame.
Definition: vtkfigFrame.h:310
bool running_multithreaded
Thread state.
std::vector< SubFrame > subframes
List of subframes.
Definition: vtkfigFrame.h:361
int iframe
Frame number as parameter during communication.
vtkSmartPointer< vtkCornerAnnotation > title_actor
Actor for frame title annotation.
Definition: vtkfigFrame.h:417
Define Frame class providing a window for rendering.
static void CommunicatorThreadCallback(MainThread *)
Callback function for communicator thread if multithreading is off.
std::vector< Figure * > edited_figures
List of currently edited figures.
vtkfig specific keybord and mouse interaction
static void RTAddFrame(MainThread *mt, int iframe)
Add frame, to be called from render thread.
static constexpr const char * KeyboardHelp
Help string printed when pressing "h"/"?".
Definition: vtkfigFrame.h:256
bool single_subframe_view
Definition: vtkfigFrame.h:357