void mitk::Mesh::ExecuteOperation(Operation* operation) { //adding only the operations, that aren't implemented by the pointset. switch (operation->GetOperationType()) { case OpNOTHING: break; case OpNEWCELL: { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); // if no lineoperation, then call superclass pointSet if (lineOp == nullptr) { Superclass::ExecuteOperation(operation); } bool ok; int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); // if it doesn't already exist if (!ok) { cellAutoPointer.TakeOwnership( new PolygonType ); m_PointSetSeries[0]->SetCell(cellId, cellAutoPointer); CellDataType cellData; cellData.selected = true; cellData.selectedLines.clear(); cellData.closed = false; m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpDELETECELL: { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } m_PointSetSeries[0]->GetCells()->DeleteIndex((unsigned)lineOp->GetCellId()); m_PointSetSeries[0]->GetCellData()->DeleteIndex((unsigned)lineOp->GetCellId()); } break; case OpCLOSECELL: //sets the bolean flag closed from a specified cell to true. { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { //then search the selected cell!//TODO Superclass::ExecuteOperation(operation); } bool ok; int cellId = lineOp->GetCellId(); if (cellId<0)//cellId isn't set { cellId = this->SearchSelectedCell( 0 ); if (cellId < 0 )//still not found return; } CellAutoPointer cellAutoPointer; //get directly the celldata!TODO ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); cellData.closed = true; m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpOPENCELL: { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } bool ok; int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); cellData.closed = false;; m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpADDLINE: // inserts the ID of the selected point into the indexes of lines in the // selected cell afterwars the added line is selected { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); int cellId = -1; int pId = -1; if (lineOp == nullptr) { cellId = this->SearchSelectedCell( 0 ); if (cellId == -1) return; pId = this->SearchSelectedPoint( 0 ); if (pId == -1) return; } else { cellId = lineOp->GetCellId(); if (cellId == -1) return; pId = lineOp->GetPIdA(); if (pId == -1) return; } bool ok; CellAutoPointer cellAutoPointer; ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellType * cell = cellAutoPointer.GetPointer(); if( cell->GetType() == CellType::POLYGON_CELL ) { PolygonType * polygon = static_cast<PolygonType *>( cell ); // add the pointId to the Cell. filling the empty cell with // one id doesn't mean to add a line, it means, that the // initilal PointId is set. The next addition of a pointId adds // a line polygon->AddPointId(pId); // select the line, if we really added a line, so now have more than // 1 pointID in the cell CellDataType cellData; ok = m_PointSetSeries[0]->GetCellData(cellId, &cellData); if (ok) { // A line between point 0 and 1 has the Id 0. A line between // 1 and 2 has a Id = 1. So we add getnumberofpoints-2. if (polygon->GetNumberOfPoints()>1) cellData.selectedLines.push_back(polygon->GetNumberOfPoints()-2); } m_PointSetSeries[0]->SetCellData(cellId, cellData); m_PointSetSeries[0]->SetCell(cellId, cellAutoPointer); } } } break; case OpDELETELINE: { // deleted the last line through removing the index PIdA // (if set to -1, use the last point) in the given cellId mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); int cellId = -1; int pId = -1; if (lineOp == nullptr) { cellId = this->SearchSelectedCell( 0 ); if (cellId == -1) return; pId = this->SearchSelectedPoint( 0 ); } else { cellId = lineOp->GetCellId(); if (cellId == -1) return; pId = lineOp->GetPIdA(); } bool ok; CellAutoPointer cellAutoPointer; ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellType * cell = cellAutoPointer.GetPointer(); if( cell->GetType() == CellType::POLYGON_CELL ) { PolygonType * oldPolygon = static_cast<PolygonType *>( cell ); auto newPolygonCell = new PolygonType; CellAutoPointer newCell; newCell.TakeOwnership( newPolygonCell ); PointIdConstIterator it, oldend; oldend = oldPolygon->PointIdsEnd(); if(pId >= 0) { for(it = oldPolygon->PointIdsBegin(); it != oldend; ++it) { if((*it) != (MeshType::PointIdentifier)pId) { newPolygonCell->AddPointId(*it); } } } else { --oldend; for(it = oldPolygon->PointIdsBegin(); it != oldend; ++it) newPolygonCell->AddPointId(*it); } oldPolygon->SetPointIds(0, newPolygonCell->GetNumberOfPoints(), newPolygonCell->PointIdsBegin()); } } } break; case OpREMOVELINE: //Remove the given Index in the given cell through copying everything // into a new cell accept the one that has to be deleted. { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } bool ok; CellAutoPointer cellAutoPointer; int cellId = lineOp->GetCellId(); ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (!ok) return; CellType * cell = cellAutoPointer.GetPointer(); CellAutoPointer newCellAutoPointer; newCellAutoPointer.TakeOwnership( new PolygonType ); PolygonType * newPolygon = static_cast<PolygonType *>( cell ); PointIdIterator it = cell->PointIdsBegin(); PointIdIterator end = cell->PointIdsEnd(); int pointId = lineOp->GetPIdA(); if (pointId<0)//if not initialized!! return; while (it!=end) { if ((*it)==(unsigned int)pointId) { break; } else { newPolygon ->AddPointId(*it); } ++it; } while (it!=end) { newPolygon ->AddPointId(*it); it++; } m_PointSetSeries[0]->SetCell(cellId, newCellAutoPointer); } break; case OpINSERTLINE: // //insert line between two other points. ////before A--B after A--C--B // //the points A, B and C have to be in the pointset. // //needed: CellId, Id of C , Id A and Id B ////the cell has to exist! //{ //mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); // if (lineOp == NULL)//if no lineoperation, then call superclass pointSet // { // Superclass::ExecuteOperation(operation); // } // int cellId = lineOp->GetCellId(); // int pIdC = lineOp->GetPIdC(); // int pIdA = lineOp->GetPIdA(); // int pIdB = lineOp->GetPIdB(); // //the points of the given PointIds have to exist in the PointSet // bool ok; // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdA); // if (!ok) // return; // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdB); // if (!ok) // return; // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdC); // if (!ok) // return; // // so the points do exist. So now check, if there is already a cell // // with the given Id // DataType::CellAutoPointer cell; // ok = m_PointSetSeries[0]->GetCell(cellId, cell); // if (!ok) // return; // //pIdA and pIdB should exist in the cell // // PointIdIterator pit = cell->PointIdsBegin(); // PointIdIterator end = cell->PointIdsEnd(); // // //now arrange the new Ids in the cell like desired; pIdC between // // pIdA and pIdB // unsigned int nuPoints = cell->GetNumberOfPoints(); // std::vector<unsigned int> newPoints; // pit = cell->PointIdsBegin(); // end = cell->PointIdsEnd(); // int i = 0; // while( pit != end ) // { // if ((*pit) = pIdA) // { // //now we have found the place to add pIdC after // newPoints[i] = (*pit); // i++; // newPoints[i] = pIdC; // } // else // newPoints[i] = (*pit); // pit++; // } // //now we have the Ids, that existed before combined with the new ones // //so delete the old cell // //doesn't seem to be necessary! // //cell->ClearPoints(); // pit = cell->PointIdsBegin(); // cell->SetPointIds(pit); //} break; case OpMOVELINE://(moves two points) { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr) { mitk::StatusBar::GetInstance()->DisplayText( "Message from mitkMesh: Recieved wrong type of operation! See mitkMeshInteractor.cpp", 10000); return; } //create two operations out of the one operation and call superclass //through the transmitted pointIds get the koordinates of the points. //then add the transmitted vestor to them //create two operations and send them to superclass Point3D pointA, pointB; pointA.Fill(0.0); pointB.Fill(0.0); m_PointSetSeries[0]->GetPoint(lineOp->GetPIdA(), &pointA); m_PointSetSeries[0]->GetPoint(lineOp->GetPIdB(), &pointB); pointA[0] += lineOp->GetVector()[0]; pointA[1] += lineOp->GetVector()[1]; pointA[2] += lineOp->GetVector()[2]; pointB[0] += lineOp->GetVector()[0]; pointB[1] += lineOp->GetVector()[1]; pointB[2] += lineOp->GetVector()[2]; auto operationA = new mitk::PointOperation(OpMOVE, pointA, lineOp->GetPIdA()); auto operationB = new mitk::PointOperation(OpMOVE, pointB, lineOp->GetPIdB()); Superclass::ExecuteOperation(operationA); Superclass::ExecuteOperation(operationB); } break; case OpSELECTLINE://(select the given line) { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); SelectedLinesType *selectedLines = &(cellData.selectedLines); auto position = std::find(selectedLines->begin(), selectedLines->end(), (unsigned int) lineOp->GetId()); if (position == selectedLines->end())//if not alsready selected { cellData.selectedLines.push_back(lineOp->GetId()); } m_PointSetSeries[0]->SetCellData(lineOp->GetCellId(), cellData); } } break; case OpDESELECTLINE://(deselect the given line) { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr) { Superclass::ExecuteOperation(operation); } int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); SelectedLinesType *selectedLines = &(cellData.selectedLines); auto position = std::find(selectedLines->begin(), selectedLines->end(), (unsigned int) lineOp->GetId()); if (position != selectedLines->end())//if found { selectedLines->erase(position); } m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpSELECTCELL://(select the given cell) { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; //directly get the data!//TODO bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); cellData.selected = true; m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpDESELECTCELL://(deselect the given cell) { mitk::LineOperation *lineOp = dynamic_cast<mitk::LineOperation *>(operation); if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } int cellId = lineOp->GetCellId(); CellAutoPointer cellAutoPointer; bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (ok) { CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); cellData.selected = false; m_PointSetSeries[0]->SetCellData(cellId, cellData); } } break; case OpMOVECELL: //moves all Points of one cell according to the given vector { mitk::CellOperation *lineOp = dynamic_cast<mitk::CellOperation *>(operation); if (lineOp == nullptr)//if no celloperation, then call superclass pointSet { Superclass::ExecuteOperation(operation); } int cellId = lineOp->GetCellId(); Vector3D vector = lineOp->GetVector(); //get the cell CellAutoPointer cellAutoPointer; bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); if (!ok) return; CellDataType cellData; m_PointSetSeries[0]->GetCellData(cellId, &cellData); // iterate through the pointIds of the CellData and move those points in // the pointset PointIdIterator it = cellAutoPointer->PointIdsBegin(); PointIdIterator end = cellAutoPointer->PointIdsEnd(); while(it != end) { unsigned int position = (*it); PointType point; point.Fill(0); m_PointSetSeries[0]->GetPoint(position, &point); point = point + vector; m_PointSetSeries[0]->SetPoint(position, point); ++it; } } break; default: //if the operation couldn't be handled here, then send it to superclass Superclass::ExecuteOperation(operation); return; } //to tell the mappers, that the data is modifierd and has to be updated this->Modified(); mitk::OperationEndEvent endevent(operation); ((const itk::Object*)this)->InvokeEvent(endevent); // As discussed lately, don't mess with rendering from inside data structures //*todo has to be done here, cause of update-pipeline not working yet //mitk::RenderingManager::GetInstance()->RequestUpdateAll(); }
/* * mexFunction(): entry point for the mex function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // interface to deal with input arguments from Matlab enum InputIndexType {IN_TRI, IN_X, IN_RES, IN_SIZE, IN_ORIGIN, InputIndexType_MAX}; MatlabImportFilter::Pointer matlabImport = MatlabImportFilter::New(); matlabImport->ConnectToMatlabFunctionInput(nrhs, prhs); // check the number of input arguments matlabImport->CheckNumberOfArguments(2, InputIndexType_MAX); // register the inputs for this function at the import filter typedef MatlabImportFilter::MatlabInputPointer MatlabInputPointer; MatlabInputPointer inTRI = matlabImport->RegisterInput(IN_TRI, "TRI"); MatlabInputPointer inX = matlabImport->RegisterInput(IN_X, "X"); // (x, y, z) MatlabInputPointer inRES = matlabImport->RegisterInput(IN_RES, "RES"); // (r, c, s) MatlabInputPointer inSIZE = matlabImport->RegisterInput(IN_SIZE, "SIZE"); // (r, c, s) MatlabInputPointer inORIGIN = matlabImport->RegisterInput(IN_ORIGIN, "ORIGIN"); // (x, y, z) // interface to deal with outputs to Matlab enum OutputIndexType {OUT_IM, OutputIndexType_MAX}; MatlabExportFilter::Pointer matlabExport = MatlabExportFilter::New(); matlabExport->ConnectToMatlabFunctionOutput(nlhs, plhs); // check that the number of outputs the user is asking for is valid matlabExport->CheckNumberOfArguments(0, OutputIndexType_MAX); // register the outputs for this function at the export filter typedef MatlabExportFilter::MatlabOutputPointer MatlabOutputPointer; MatlabOutputPointer outIM = matlabExport->RegisterOutput(OUT_IM, "IM"); // if any input point set is empty, the outputs are empty too if (mxIsEmpty(inTRI->pm) || mxIsEmpty(inX->pm)) { matlabExport->CopyEmptyArrayToMatlab(outIM); return; } // get number of rows in inputs X and TRI mwSize nrowsX = mxGetM(inX->pm); mwSize nrowsTRI = mxGetM(inTRI->pm); // instantiate mesh MeshType::Pointer mesh = MeshType::New(); // read vertices PointSetType::Pointer xDef = PointSetType::New(); // default: empty point set PointSetType::Pointer x = PointSetType::New(); x->GetPoints()->CastToSTLContainer() = matlabImport->ReadVectorOfVectorsFromMatlab<PointType::CoordRepType, PointType> (inX, xDef->GetPoints()->CastToSTLContainer()); #ifdef DEBUG std::cout << "Number of X points read = " << x->GetNumberOfPoints() << std::endl; #endif // assertion check if (nrowsX != x->GetNumberOfPoints()) { mexErrMsgTxt(("Input " + inX->name + ": Number of points read different from number of points provided by user").c_str()); } // swap XY coordinates to make them compliant with ITK convention // (see important programming note at the help header above) matlabImport->SwapXYInVectorOfVectors<PointType::CoordRepType, std::vector<PointType> > (x->GetPoints()->CastToSTLContainer(), x->GetNumberOfPoints()); // populate mesh with vertices mesh->SetPoints(x->GetPoints()); // read triangles PointType triDef; triDef.Fill(mxGetNaN()); for (mwIndex i = 0; i < nrowsTRI; ++i) { PointType triangle = matlabImport->ReadRowVectorFromMatlab<CoordType, PointType>(inTRI, i, triDef); // create a triangle cell to read the vertex indices of the current input triangle CellAutoPointer cell; cell.TakeOwnership(new TriangleType); // assign to the 0, 1, 2 elements in the triangle cell the vertex // indices that we have just read. Note that we have to substract // 1 to convert Matlab's index convention 1, 2, 3, ... to C++ // convention 0, 1, 2, ... cell->SetPointId(0, triangle[0] - 1); cell->SetPointId(1, triangle[1] - 1); cell->SetPointId(2, triangle[2] - 1); // insert cell into the mesh mesh->SetCell(i, cell); } #ifdef DEBUG std::cout << "Number of triangles read = " << mesh->GetNumberOfCells() << std::endl; #endif // assertion check if (nrowsTRI != mesh->GetNumberOfCells()) { mexErrMsgTxt(("Input " + inTRI->name + ": Number of triangles read different from number of triangles provided by user").c_str()); } // get user input parameters for the output rasterization ImageType::SpacingType spacingDef; spacingDef.Fill(1.0); ImageType::SpacingType spacing = matlabImport-> ReadRowVectorFromMatlab<ImageType::SpacingValueType, ImageType::SpacingType>(inRES, spacingDef); ImageType::SizeType sizeDef; sizeDef.Fill(10); ImageType::SizeType size = matlabImport-> ReadRowVectorFromMatlab<ImageType::SizeValueType, ImageType::SizeType>(inSIZE, sizeDef); ImageType::PointType originDef; originDef.Fill(0.0); ImageType::PointType origin = matlabImport-> ReadRowVectorFromMatlab<ImageType::PointType::ValueType, ImageType::PointType>(inORIGIN, originDef); // (see important programming note at the help header above) matlabImport->SwapXYInVector<ImageType::PointType::ValueType, ImageType::PointType>(origin); // instantiate rasterization filter MeshFilterType::Pointer meshFilter = MeshFilterType::New(); // smallest voxel side length ImageType::SpacingValueType minSpacing = spacing[0]; for (mwIndex i = 1; i < Dimension; ++i) { minSpacing = std::min(minSpacing, spacing[i]); } // pass input parameters to the filter meshFilter->SetInput(mesh); meshFilter->SetSpacing(spacing); meshFilter->SetSize(size); meshFilter->SetOrigin(origin); meshFilter->SetTolerance(minSpacing / 10.0); meshFilter->SetInsideValue(1); meshFilter->SetOutsideValue(0); ImageType::IndexType start; start.Fill(0); meshFilter->SetIndex(start); // convert image size from itk::Size format to std::vector<mwSize> // so that we can use it in GraftItkImageOntoMatlab std::vector<mwSize> sizeStdVector(Dimension); for (unsigned int i = 0; i < Dimension; ++i) { sizeStdVector[i] = size[i]; } // graft ITK filter output onto Matlab output matlabExport->GraftItkImageOntoMatlab<PixelType, Dimension> (outIM, meshFilter->GetOutput(), sizeStdVector); #ifdef DEBUG std::cout << "Resolution (spacing) = " << meshFilter->GetSpacing() << std::endl; std::cout << "Size = " << meshFilter->GetSize() << std::endl; std::cout << "Origin = " << meshFilter->GetOrigin() << std::endl; #endif // run rasterization meshFilter->Update(); }