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> 34 for (
auto & subframe: frame.second->subframes)
35 subframe.renderer->RemoveAllViewProps();
36 frame.second->window->Finalize();
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");
69 if (multi_string!=0 && atoi(multi_string))
72 cout <<
"overriding multithreading default (off) on APPLE" << endl;
77 if (multi_string!=0 && !atoi(multi_string))
80 cout <<
"overriding multithreading default (on) on" << endl;
89 wtime=atoi(wtime_string);
94 int port=atoi(port_string);
96 throw std::runtime_error(
"Invalid port number for server");
107 cout << sc<<
" try running multithreaded" << endl;
109 cout << sc<<
" try running single threaded" << endl;
118 cout <<
"Server start listening on port "<< port << endl;
124 cout <<
"Server connected" << endl;
127 cout <<
"Nobody is listening ... giving up" << endl;
128 throw std::runtime_error(
"Server connection failed");
137 cout <<
" ~mt" << endl;
140 std::this_thread::sleep_for(std::chrono::milliseconds(10));
142 std::this_thread::sleep_for(std::chrono::milliseconds(10));
214 std::this_thread::sleep_for (std::chrono::milliseconds(10));
226 cout <<
"mt " << from <<
" " << number_in_frame_list << endl;
230 this->
iframe=number_in_frame_list;
233 std::unique_lock<std::mutex> lock(this->
mutex);
257 bool edit_mode =
false;
260 bool left_button_down=
false;
291 for (
auto & figure: frame->
figures)
293 for (
auto & actor: figure->ctxactors)
294 actor->GetScene()->SetDirty(
true);
296 vtkInteractorStyleTrackballCamera::OnConfigure();
308 this->left_button_down=
true;
309 lastx=this->Interactor->GetEventPosition()[0];
310 lasty=this->Interactor->GetEventPosition()[1];
313 vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
319 for (
auto &figure: frame->
figures)
322 if (frame->
subframes[figure->framepos].renderer==this->CurrentRenderer)
323 figure->RTShowActive();
325 figure->RTShowInActive();
330 if (this->left_button_down)
331 this->left_button_down=
false;
333 vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
342 if (this->left_button_down)
346 int thisx=this->Interactor->GetEventPosition()[0];
347 int thisy=this->Interactor->GetEventPosition()[1];
352 for (
auto figure:this->edited_figures)
353 figure->RTProcessMove(dx,dy);
356 this->Interactor->Render();
363 vtkInteractorStyleTrackballCamera::OnMouseMove();
370 std::string key = this->Interactor->GetKeySym();
386 for (
auto & subframe: this->frame->
subframes)
388 if (subframe.renderer==this->CurrentRenderer)
393 this->Interactor->Render();
399 for (
auto &figure: this->frame->
figures)
400 if (this->frame->
subframes[figure->framepos].renderer==this->CurrentRenderer)
402 figure->state.wireframe=!figure->state.wireframe;
403 if (figure->state.wireframe)
404 for (
auto & actor: figure->actors) actor->GetProperty()->SetRepresentationToWireframe();
406 for (
auto& actor: figure->actors) actor->GetProperty()->SetRepresentationToSurface();
407 this->Interactor->Render();
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);
424 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
425 imgfilter->SetInput(frame->
window);
428 auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
429 pngwriter->SetInputConnection(imgfilter->GetOutputPort());
430 pngwriter->SetFileName(fname.c_str());
432 this->Interactor->Render();
435 cout <<
"Frame written to "<< fname << endl;
439 else if (key ==
"x" || key==
"y" || key==
"z" || key==
"l" || key==
"a")
441 if (!this->edit_mode)
444 this->edit_mode=
true;
448 for (
auto &figure: frame->
figures)
452 frame->
subframes[figure->framepos].renderer==this->CurrentRenderer
465 this->edited_figures.push_back(figure);
470 for (
auto figure : this->edited_figures)
471 figure->RTProcessKey(key);
472 this->Interactor->Render();
477 else if(key ==
"Left" || key==
"Down")
481 for (
auto figure : this->edited_figures)
482 figure->RTProcessMove(-1,-1);
483 this->Interactor->Render();
488 else if(key ==
"Right" || key==
"Up")
492 for (
auto figure : this->edited_figures)
493 figure->RTProcessMove(1,1);
494 this->Interactor->Render();
499 else if(key ==
"Return" || key==
"Delete")
503 for (
auto figure : this->edited_figures)
504 figure->RTProcessKey(key);
505 this->Interactor->Render();
510 else if(key ==
"Escape")
512 this->edit_mode=
false;
513 for (
auto figure : this->edited_figures)
515 figure->RTProcessKey(key);
516 figure->RTMessage(
"");
518 this->Interactor->Render();
519 this->edited_figures.resize(0);
520 this->Interactor->Render();
524 else if(key ==
"I" || key==
"L" || key ==
"E" || key ==
"S" || key ==
"slash" || key ==
"B" || key ==
"C" || key ==
"O"|| key ==
"A")
526 for (
auto &figure: frame->
figures)
527 if (frame->
subframes[figure->framepos].renderer==this->CurrentRenderer)
528 figure->RTProcessKey(key);
530 this->Interactor->Render();
534 else if (key==
"space")
546 else if (key==
"BackSpace")
554 else if (key==
"asterisk")
557 for(
int i=0;i<this->frame->
subframes.size();i++)
559 if (this->frame->
subframes[i].renderer==this->CurrentRenderer)
565 this->Interactor->Render();
572 this->Interactor->Render();
578 this->Interactor->Render();
584 else if(key ==
"h" or key ==
"question")
592 vtkInteractorStyleTrackballCamera::OnChar();
608 vtkSmartPointer<vtkRenderWindowInteractor> Interactor=0;
614 vtkObject *vtkNotUsed(caller),
615 unsigned long eventId,
616 void *vtkNotUsed(callData)
624 vtkCommand::TimerEvent == eventId
632 std::unique_lock<std::mutex> lock(this->mainthread->
mutex);
635 switch(mainthread->
cmd)
650 for (
auto & subframe: frame->subframes)
651 subframe.renderer->RemoveAllViewProps();
653 frame->window->Finalize();
655 mainthread->
framemap.erase(frame->number_in_frame_list);
665 for (
auto & framepair: mainthread->
framemap)
666 framepair.second->RTAddFigures();
670 for (
auto & framepair: mainthread->
framemap)
672 auto frame=framepair.second;
674 if(frame->mainthread->communication_blocked)
675 frame->title_actor->SetText(6,
"-|-");
677 frame->title_actor->SetText(6,
"---");
679 frame->title_actor->Modified();
683 frame->window->Render();
684 if (frame->videowriter && ! frame->mainthread->communication_blocked)
686 this->Interactor->Render();
687 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
688 imgfilter->SetInput(frame->window);
690 frame->videowriter->SetInputConnection(imgfilter->GetOutputPort());
691 this->Interactor->Render();
692 frame->videowriter->Write();
703 auto imgfilter = vtkSmartPointer<vtkWindowToImageFilter>::New();
704 auto pngwriter = vtkSmartPointer<vtkPNGWriter>::New();
706 pngwriter->SetInputConnection(imgfilter->GetOutputPort());
707 pngwriter->SetFileName(frame->parameter.filename.c_str());
709 imgfilter->SetInput(frame->window);
712 this->Interactor->Render();
722 frame->videowriter = vtkSmartPointer<vtkOggTheoraWriter>::New();
723 frame->videowriter->SetFileName(frame->parameter.filename.c_str());
724 frame->videowriter->Start();
731 frame->videowriter->End();
732 frame->videowriter=0;
739 frame->RTRemoveFigure(frame->parameter.current_figure);
747 frame->RTSetLayout(frame->parameter.nvpx,frame->parameter.nvpy);
748 frame->RTResetRenderers(
false);
755 frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
763 frame->RTSetActiveSubFrame(frame->parameter.active_subframe,
false);
771 auto& subframe=frame->subframes[frame->parameter.active_subframe];
772 frame->RTSetActiveSubFrameCameraViewAngle(subframe,frame->parameter.camera_view_angle);
780 auto& subframe=frame->subframes[frame->parameter.active_subframe];
781 frame->RTSetActiveSubFrameCameraPosition(subframe,frame->parameter.camera_position);
789 auto& subframe=frame->subframes[frame->parameter.active_subframe];
790 frame->RTSetActiveSubFrameCameraFocalPoint(subframe,frame->parameter.camera_focal_point);
797 frame->RTSetSingleView(frame->parameter.single_subframe_view);
807 frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
816 frame->title_actor->SetText(7,frame->parameter.frametitle.c_str());
817 frame->title_actor->Modified();
826 frame->window->SetWindowName(frame->parameter.wintitle.c_str());
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());
844 for (
auto & framepair: mainthread->
framemap)
845 framepair.second->window->Finalize();
849 this->Interactor->TerminateApp();
882 frame->window = vtkSmartPointer<vtkRenderWindow>::New();
883 frame->window->SetWindowName(
"vtkfig");
886 frame->window->DoubleBufferOn();
888 frame->window->DoubleBufferOff();
890 frame->window->SetSize(frame->parameter.winsize_x, frame->parameter.winsize_y);
891 frame->window->SetPosition(frame->parameter.winposition_x, frame->parameter.winposition_y);
893 frame->RTResetRenderers(
true);
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());
907 mainthread->
interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
908 auto style = vtkSmartPointer<MyInteractorStyle>::New();
909 style->SetFrame(frame);
910 mainthread->
interactor->SetInteractorStyle(style);
912 mainthread->
interactor->SetRenderWindow(frame->window);
914 auto callback = vtkSmartPointer<MyTimerCallback>::New();
917 mainthread->
interactor->AddObserver(vtkCommand::TimerEvent,callback);
950 std::this_thread::sleep_for (std::chrono::milliseconds(10));
971 std::unique_lock<std::mutex> lock(mainthread->
mutex);
974 cout <<
"s cmd: " <<
static_cast<int>(mainthread->
cmd) <<
" frame: " <<mainthread->
iframe<< endl;
980 switch(mainthread->
cmd)
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;
1002 mainthread->
communicator->SendInt(frame->parameter.active_subframe);
1014 for (
auto framepair: mainthread->
framemap)
1015 for (
auto & figure: framepair.second->figures)
1027 mainthread->
communicator->SendString(frame->parameter.filename);
1034 mainthread->
communicator->SendInt(frame->parameter.winsize_x);
1035 mainthread->
communicator->SendInt(frame->parameter.winsize_y);
1042 mainthread->
communicator->SendInt(frame->parameter.winposition_x);
1043 mainthread->
communicator->SendInt(frame->parameter.winposition_y);
1050 mainthread->
communicator->SendString(frame->parameter.frametitle);
1058 mainthread->
communicator->SendString(frame->parameter.wintitle);
1066 mainthread->
communicator->SendString(frame->parameter.current_figure->SubClassName());
1067 mainthread->
communicator->SendInt(frame->parameter.current_figure->framepos);
1074 mainthread->
communicator->SendString(frame->parameter.current_figure->SubClassName());
1075 mainthread->
communicator->SendInt(frame->parameter.current_figure->framepos);
1083 mainthread->
communicator->SendInt(frame->parameter.camlinkthisframepos);
1084 mainthread->
communicator->SendInt(frame->parameter.camlinkframenum);
1085 mainthread->
communicator->SendInt(frame->parameter.camlinkframepos);
1105 cout <<
"s term" << endl;
1116 cout <<
"s cmd: " <<
static_cast<int>(mainthread->
cmd) << endl;
1117 throw std::runtime_error(
"wrong command on server");
1139 std::this_thread::sleep_for (std::chrono::milliseconds(5));
void RTSetSingleView(bool single_viewport)
void Terminate(void)
Terminate thread.
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.
static MyTimerCallback * New()
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.
void OpenConnection(int port, int wtime)
Open connection to client.
virtual void OnConfigure()
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.
friend class MyInteractorStyle
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.
friend class MyTimerCallback
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.
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)
static MyInteractorStyle * New()
void RemoveFrame(Frame *frame)
Remove frame from thread.
Provide a framework wrapping window+interactor+renderers from vtk.
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.
bool running_multithreaded
Thread state.
std::vector< SubFrame > subframes
List of subframes.
int iframe
Frame number as parameter during communication.
vtkSmartPointer< vtkCornerAnnotation > title_actor
Actor for frame title annotation.
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"/"?".
bool single_subframe_view