diff --git a/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.cpp b/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.cpp index d86130b17f..58c464dbb3 100644 --- a/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.cpp +++ b/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.cpp @@ -1,562 +1,598 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include +#include #include #include +#include #include // Blueberry #include #include // Qmitk #include "SceneStreamingView.h" // Qt #include #include // MITK #include "mitkIGTLClient.h" #include "mitkIGTLMessageFactory.h" #include "mitkIGTLMessageProvider.h" #include "mitkIGTLServer.h" -#include #include "mitkSurface.h" #include "mitkUnstructuredGrid.h" +#include #include "igtlPolyDataMessage.h" #include "igtlServerSocket.h" #include "mitkIGTLMessage.h" #include "vtkCellArray.h" #include "vtkPointData.h" #include "vtkSmartPointer.h" #include "vtkTriangle.h" #include using namespace std::chrono_literals; using namespace std::chrono; +namespace fs = std::experimental::filesystem; + const std::string SceneStreamingView::VIEW_ID = "org.mitk.views.scenestreamingview"; void SceneStreamingView::SetFocus() {} void SceneStreamingView::CreateQtPartControl(QWidget *parent) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi(parent); m_Parent = parent; + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType(); + + connect(this, &SceneStreamingView::InvokeRenderUpdate, this, &SceneStreamingView::RenderUpdate); + auto ds = GetDataStorage(); - auto dataNodes = mitk::IOUtil::Load("C:\\Users\\steint\\Documents\\output\\output\\out0.vtu", *ds); + + m_SurfaceNode = mitk::DataNode::New(); + m_SurfaceNode->SetName("surface"); + ds->Add(m_SurfaceNode); + m_DataStorage = ds; m_TaskFuture = std::async([&] { RunServerLoop(); }); // std::thread tServer([&] { RunServer(); }); // std::thread tClient([&] { RunClient(); }); // tServer.join(); } +void SceneStreamingView::RenderUpdate(int count, mitk::BaseData* baseData) +{ + m_SurfaceNode->SetData(baseData); + if (count == 0) + { + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); + } + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); +} + void SceneStreamingView::RunServerLoop() { MITK_INFO << "Run server ..."; auto igtlServer = mitk::IGTLServer::New(true); igtlServer->SetName("Scene Streaming Server"); igtlServer->SetHostname("127.0.0.1"); igtlServer->SetPortNumber(35350); igtlServer->OpenConnection(); // create a new OpenIGTLinkExample Device source auto deviceSource = mitk::IGTLDeviceSource::New(); // set the server as the source for the device source deviceSource->SetIGTLDevice(igtlServer); deviceSource->RegisterAsMicroservice(); // create data // vtkSmartPointer polyData = CreatePolyData(); - auto node = GetDataStorage()->GetNamedNode("out0"); - mitk::UnstructuredGrid *polyData = - dynamic_cast(GetDataStorage()->GetNamedNode("out0")->GetData()); - auto mitkMessage = CreatePolyMessage(polyData->GetVtkUnstructuredGrid()); + + std::vector filePaths; + auto path = "C:/Users/steint/Documents/output/output"; + for (const auto &entry : fs::directory_iterator(path)) + { + filePaths.push_back(entry.path().generic_u8string()); + } + auto baseDataList = mitk::IOUtil::Load(filePaths); + // create mitk message and send int count = 0; while (1) { - MITK_INFO << "send " << count << " ..."; - igtlServer->SendMessageA(mitkMessage); - std::this_thread::sleep_for(40ms); - count++; + for (mitk::BaseData *baseData : baseDataList) + { + mitk::UnstructuredGrid *polyData = dynamic_cast(baseData); + auto mitkMessage = CreatePolyMessage(polyData->GetVtkUnstructuredGrid()); + + MITK_INFO << "send " << count << " ..."; + igtlServer->SendMessageA(mitkMessage); + emit InvokeRenderUpdate(count, baseData); + std::this_thread::sleep_for(30ms); + count++; + } } } vtkSmartPointer SceneStreamingView::CreatePolyData() { // Setup points vtkSmartPointer points = vtkSmartPointer::New(); points->InsertNextPoint(1.0, 0.0, 0.0); points->InsertNextPoint(0.0, 0.0, 0.0); points->InsertNextPoint(0.0, 1.0, 0.0); vtkSmartPointer triangles = vtkSmartPointer::New(); vtkSmartPointer triangle = vtkSmartPointer::New(); triangle->GetPointIds()->SetId(0, 0); triangle->GetPointIds()->SetId(1, 1); triangle->GetPointIds()->SetId(2, 2); triangles->InsertNextCell(triangle); vtkSmartPointer polydata = vtkSmartPointer::New(); polydata->SetPoints(points); polydata->SetPolys(triangles); return polydata; } mitk::IGTLMessage::Pointer SceneStreamingView::CreatePolyMessage(vtkSmartPointer polyData) { // create message igtl::PolyDataMessage::Pointer polyDataMsg; polyDataMsg = igtl::PolyDataMessage::New(); // set points igtl::PolyDataPointArray::Pointer pointArray; pointArray = igtl::PolyDataPointArray::New(); for (unsigned int i = 0; i < polyData->GetNumberOfPoints(); ++i) { igtlFloat32 point[3]; double p[3]; polyData->GetPoints()->GetPoint(i, p); for (unsigned k = 0; k < 3; ++k) { point[k] = p[k]; } pointArray->AddPoint(point); } polyDataMsg->SetPoints(pointArray); // Create polygon array igtl::PolyDataCellArray::Pointer polyArray; polyArray = igtl::PolyDataCellArray::New(); for (unsigned int i = 0; i < polyData->GetNumberOfCells(); i++) { auto cell = polyData->GetCell(i); vtkSmartPointer connectedVertices = cell->GetPointIds(); auto numConnectedVerts = cell->GetNumberOfPoints(); igtlUint32 *polygonIds = new igtlUint32[numConnectedVerts]; for (unsigned int k = 0; k < numConnectedVerts; ++k) // expect a polygon of three vetices { polygonIds[k] = connectedVertices->GetId(k); } polyArray->AddCell(numConnectedVerts, polygonIds); // expect a polygon of three vetices } polyDataMsg->SetPolygons(polyArray); return mitk::IGTLMessage::New(polyDataMsg.GetPointer()); } void SceneStreamingView::RunClient() { char *hostname = "localhost"; int port = 7777; //------------------------------------------------------------ // Establish Connection igtl::ClientSocket::Pointer socket; socket = igtl::ClientSocket::New(); int r = socket->ConnectToServer(hostname, port); std::cout << "created client" << std::endl; if (r != 0) { std::cerr << "Cannot connect to the server." << std::endl; exit(0); } //------------------------------------------------------------ // loop for (int i = 0; i < 10; i++) { //------------------------------------------------------------ // Send request data igtl::GetPolyDataMessage::Pointer getPolyDataMsg; getPolyDataMsg = igtl::GetPolyDataMessage::New(); getPolyDataMsg->SetDeviceName("Client"); getPolyDataMsg->Pack(); socket->Send(getPolyDataMsg->GetPackPointer(), getPolyDataMsg->GetPackSize()); //------------------------------------------------------------ // Wait for a reply igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); headerMsg->InitPack(); int rs = socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize()); if (rs == 0) { std::cerr << "Connection closed." << std::endl; socket->CloseSocket(); exit(0); } if (rs != headerMsg->GetPackSize()) { std::cerr << "Message size information and actual data size don't match." << std::endl; exit(0); } headerMsg->Unpack(); if (strcmp(headerMsg->GetDeviceType(), "POLYDATA") == 0) { ReceivePolyData(socket, headerMsg); } else { std::cerr << "Invalid response from the server:" << headerMsg->GetDeviceName() << std::endl; exit(0); } std::this_thread::sleep_for(500ms); // wait } //------------------------------------------------------------ // Close connection socket->CloseSocket(); } void SceneStreamingView::RunServer() { int port = atoi("7777"); igtl::ServerSocket::Pointer serverSocket; serverSocket = igtl::ServerSocket::New(); int r = serverSocket->CreateServer(port); std::cout << "created server" << std::endl; if (r < 0) { std::cerr << "Cannot create a server socket." << std::endl; exit(0); } igtl::Socket::Pointer socket; while (1) { //------------------------------------------------------------ // Waiting for Connection socket = serverSocket->WaitForConnection(1000); if (socket.IsNotNull()) // if client connected { std::cerr << "A client is connected." << std::endl; // Create a message buffer to receive header igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); //------------------------------------------------------------ // loop for (int i = 0; i < 100; i++) { // Initialize receive buffer headerMsg->InitPack(); // Receive generic header from the socket int rs = socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize()); if (rs == 0) { socket->CloseSocket(); } if (rs != headerMsg->GetPackSize()) { continue; } // Deserialize the header headerMsg->Unpack(); // Check data type and receive data body if (strcmp(headerMsg->GetDeviceType(), "GET_POLYDATA") == 0) { std::cerr << "Received a GET_POLYDATA message." << std::endl; // socket->Skip(headerMsg->GetBodySizeToRead(), 0); SendPolyData(socket, headerMsg->GetDeviceName()); } else { // if the data type is unknown, skip reading. std::cerr << "Receiving : " << headerMsg->GetDeviceType() << std::endl; socket->Skip(headerMsg->GetBodySizeToRead(), 0); } } } } //------------------------------------------------------------ // Close connection (The example code never reaches to this section ...) socket->CloseSocket(); } int SceneStreamingView::SendPolyData(igtl::Socket::Pointer &socket, const char *name) { //------------------------------------------------------------ // Allocate Status Message Class igtl::PolyDataMessage::Pointer polyDataMsg; polyDataMsg = igtl::PolyDataMessage::New(); // NOTE: the server should send a message with the same device name // as the received query message. polyDataMsg->SetDeviceName(name); // Geometry data static igtlFloat32 pointsData[8][3] = { {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}}; static igtlUint32 polyData[6][4] = { {0, 3, 2, 1}, {4, 5, 6, 7}, {0, 1, 5, 4}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 0, 4, 7}}; static igtlFloat32 attributeData[8] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; // Create point array igtl::PolyDataPointArray::Pointer pointArray; pointArray = igtl::PolyDataPointArray::New(); for (unsigned int i = 0; i < 8; i++) { pointArray->AddPoint(pointsData[i]); } polyDataMsg->SetPoints(pointArray); // Create polygon array igtl::PolyDataCellArray::Pointer polyArray; polyArray = igtl::PolyDataCellArray::New(); for (unsigned int i = 0; i < 6; i++) { polyArray->AddCell(4, polyData[i]); } polyDataMsg->SetPolygons(polyArray); // Create attribute array igtl::PolyDataAttribute::Pointer attribute; attribute = igtl::PolyDataAttribute::New(); attribute->SetType(igtl::PolyDataAttribute::POINT_SCALAR); attribute->SetName("attr"); attribute->SetSize(8); attribute->SetData(attributeData); polyDataMsg->ClearAttributes(); polyDataMsg->AddAttribute(attribute); polyDataMsg->Pack(); std::cerr << "Size of pack: " << polyDataMsg->GetPackSize() << std::endl; std::cerr << "Name of type: " << polyDataMsg->GetDeviceType() << std::endl; std::cerr << "Sending a POLYDATA message..." << std::endl; socket->Send(polyDataMsg->GetPackPointer(), polyDataMsg->GetPackSize()); return 1; } int SceneStreamingView::ReceivePolyData(igtl::ClientSocket::Pointer &socket, igtl::MessageHeader::Pointer &header) { std::cerr << "Receiving POLYDATA data type." << std::endl; // Create a message buffer to receive transform data igtl::PolyDataMessage::Pointer PolyData; PolyData = igtl::PolyDataMessage::New(); PolyData->SetMessageHeader(header); PolyData->AllocatePack(); // Receive transform data from the socket socket->Receive(PolyData->GetPackBodyPointer(), PolyData->GetPackBodySize()); // Deserialize the transform data // If you want to skip CRC check, call Unpack() without argument. int c = PolyData->Unpack(1); if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK { igtl::PolyDataPointArray::Pointer pointsArray = PolyData->GetPoints(); igtl::PolyDataCellArray::Pointer verticesArray = PolyData->GetVertices(); igtl::PolyDataCellArray::Pointer linesArray = PolyData->GetLines(); igtl::PolyDataCellArray::Pointer polygonsArray = PolyData->GetPolygons(); igtl::PolyDataCellArray::Pointer triangleStripsArray = PolyData->GetTriangleStrips(); std::cerr << "========== PolyData Contents ==========" << std::endl; if (pointsArray.IsNotNull()) { std::cerr << " ------ Points ------" << std::endl; for (int i = 0; i < pointsArray->GetNumberOfPoints(); i++) { igtlFloat32 point[3]; pointsArray->GetPoint(i, point); std::cerr << " point[" << i << "] = (" << point[0] << ", " << point[1] << ", " << point[2] << ")" << std::endl; } } if (verticesArray.IsNotNull()) { std::cerr << " ------ Vertices ------" << std::endl; for (unsigned int i = 0; i < verticesArray->GetNumberOfCells(); i++) { std::list cell; verticesArray->GetCell(i, cell); std::list::iterator iter; iter = cell.begin(); if (iter != cell.end()) { std::cerr << " cell[" << i << "] = (" << *iter; for (; iter != cell.end(); iter++) { std::cerr << ", " << *iter; } std::cerr << ")" << std::endl; } } } if (linesArray.IsNotNull()) { std::cerr << " ------ Lines ------" << std::endl; for (unsigned int i = 0; i < linesArray->GetNumberOfCells(); i++) { std::list cell; linesArray->GetCell(i, cell); std::list::iterator iter; iter = cell.begin(); if (iter != cell.end()) { std::cerr << " cell[" << i << "] = (" << *iter; for (; iter != cell.end(); iter++) { std::cerr << ", " << *iter; } std::cerr << ")" << std::endl; } } } if (polygonsArray.IsNotNull()) { std::cerr << " ------ Polygons ------" << std::endl; for (unsigned int i = 0; i < polygonsArray->GetNumberOfCells(); i++) { std::list cell; polygonsArray->GetCell(i, cell); std::list::iterator iter; iter = cell.begin(); if (iter != cell.end()) { std::cerr << " cell[" << i << "] = (" << *iter; for (; iter != cell.end(); iter++) { std::cerr << ", " << *iter; } std::cerr << ")" << std::endl; } } } if (triangleStripsArray.IsNotNull()) { std::cerr << " ------ TriangleStrips ------" << std::endl; for (unsigned int i = 0; i < triangleStripsArray->GetNumberOfCells(); i++) { std::list cell; triangleStripsArray->GetCell(i, cell); std::list::iterator iter; iter = cell.begin(); if (iter != cell.end()) { std::cerr << " cell[" << i << "] = (" << *iter; for (; iter != cell.end(); iter++) { std::cerr << ", " << *iter; } std::cerr << ")" << std::endl; } } } unsigned int nAttr = PolyData->GetNumberOfAttributes(); for (unsigned int i = 0; i < nAttr; i++) { std::cerr << " ------ Attributes #" << i << " ------" << std::endl; igtl::PolyDataAttribute *p = PolyData->GetAttribute(i); if (p) { std::cerr << " Name = " << p->GetName() << std::endl; std::cerr << " Type = "; switch (p->GetType()) { case igtl::PolyDataAttribute::POINT_SCALAR: std::cerr << "POINT_SCALAR" << std::endl; break; case igtl::PolyDataAttribute::POINT_VECTOR: std::cerr << "POINT_VECTOR" << std::endl; break; case igtl::PolyDataAttribute::POINT_NORMAL: std::cerr << "POINT_NORMAL" << std::endl; break; case igtl::PolyDataAttribute::POINT_TENSOR: std::cerr << "POINT_TENSOR" << std::endl; break; case igtl::PolyDataAttribute::POINT_RGBA: std::cerr << "POINT_RGBA" << std::endl; break; case igtl::PolyDataAttribute::CELL_SCALAR: std::cerr << "CELL_SCALAR" << std::endl; break; case igtl::PolyDataAttribute::CELL_VECTOR: std::cerr << "CELL_VECTOR" << std::endl; break; case igtl::PolyDataAttribute::CELL_NORMAL: std::cerr << "CELL_NORMAL" << std::endl; break; case igtl::PolyDataAttribute::CELL_TENSOR: std::cerr << "CELL_TENSOR" << std::endl; break; case igtl::PolyDataAttribute::CELL_RGBA: std::cerr << "CELL_RGBA" << std::endl; break; } unsigned int size = p->GetSize(); unsigned int ncomp = p->GetNumberOfComponents(); igtlFloat32 *data = new igtlFloat32[ncomp]; for (unsigned int j = 0; j < size; j++) { p->GetNthData(j, data); std::cerr << " data[" << j << "] = (" << data[0]; for (unsigned int k = 1; k < ncomp; k++) { std::cerr << ", " << data[k]; } std::cerr << ")" << std::endl; } } } std::cerr << "================================" << std::endl; return 1; } return 0; } diff --git a/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.h b/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.h index 49d05767ad..2eb09665d2 100644 --- a/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.h +++ b/Plugins/org.mitk.gui.qt.scenestreaming/src/internal/SceneStreamingView.h @@ -1,76 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef SceneStreamingView_h #define SceneStreamingView_h #include #include #include "ui_SceneStreamingViewControls.h" #include "igtlClientSocket.h" #include "igtlMessageHeader.h" #include "igtlSocket.h" #include "mitkIGTLMessage.h" #include "vtkPolyData.h" #include "vtkUnstructuredGrid.h" #include /** @brief SceneStreamingView @author Tobias Stein \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class SceneStreamingView : public QmitkAbstractView { Q_OBJECT public: static const std::string VIEW_ID; +signals: + void InvokeRenderUpdate(int count, mitk::BaseData* baseData); + protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; Ui::SceneStreamingViewControls m_Controls; private: int SendPolyData(igtl::Socket::Pointer &socket, const char *name); int ReceivePolyData(igtl::ClientSocket::Pointer &socket, igtl::MessageHeader::Pointer &header); vtkSmartPointer CreatePolyData(); mitk::IGTLMessage::Pointer CreatePolyMessage(vtkSmartPointer polyData); void RunClient(); void RunServer(); void RunServerLoop(); + void RenderUpdate(int count, mitk::BaseData* baseData); + mitk::DataNode::Pointer m_SurfaceNode; std::future m_TaskFuture; + mitk::DataStorage::Pointer m_DataStorage; QWidget *m_Parent; }; #endif // SceneStreamingView_h