/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Sante) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ #include "MeshManagerModel.h" // //HISTORY HANDLER // template HistoryHandler::HistoryHandler(int maxElements) { this->maxElements = maxElements; } template HistoryHandler::~HistoryHandler() { CleanHistory(); } template void HistoryHandler::CleanHistory() { for (T* element : redoStack) { delete element; } redoStack.clear(); for (T* element : undoStack) { delete element; } undoStack.clear(); } template T* HistoryHandler::Undo(T* state) { if(state == NULL) { return NULL; } if(!undoStack.empty()) { auto lastElem = undoStack.back(); undoStack.pop_back(); redoStack.push_back(state); return lastElem; }else{ delete state; } return NULL; } template T* HistoryHandler::Redo(T* state) { if(state == NULL) { return NULL; } if(!redoStack.empty()) { auto lastElem = redoStack.back(); redoStack.pop_back(); undoStack.push_back(state); return lastElem; }else{ delete state; return NULL; } } /** * To be used with RedoKeepCurrent * Will always maintain the current state in the undo stack as the first element * Useful when states are saved after actions and the initial state is saved. */ template T* HistoryHandler::UndoKeepCurrent() { if(undoStack.size() > 1) { auto lastElem = undoStack.back(); undoStack.pop_back(); redoStack.push_back(lastElem); return undoStack.back(); }else{ return NULL; } } /** * To be used with UndoKeepCurrent * Will always maintain the current state in the undo stack as the first element * Useful when states are saved after actions and the initial state is saved. */ template T* HistoryHandler::RedoKeepCurrent() { if(!redoStack.empty()) { auto lastElem = redoStack.back(); redoStack.pop_back(); undoStack.push_back(lastElem); return undoStack.back(); }else{ return NULL; } } template void HistoryHandler::Save(T* state) { undoStack.push_back(state); if(undoStack.size() > maxElements) { T* frontDel = undoStack.front(); undoStack.pop_front(); delete frontDel; } if(!redoStack.empty()) { for (T* element : redoStack) { delete element; } redoStack.clear(); } } template T* HistoryHandler::GetPrevious() { if(!undoStack.empty()) { return undoStack.back(); } return NULL; } template T* HistoryHandler::GetNext() { if(!redoStack.empty()) { return redoStack.back(); } return NULL; } template int HistoryHandler::UndoSize() { return undoStack.size(); } template int HistoryHandler::RedoSize() { return redoStack.size(); } //////////////////// /////////////////////// MESH MODEL //////////////////// MeshModel::MeshModel(int id) { _meshBase = NULL; _meshTemp = NULL; _meshId = id; _name = "mesh-" + std::to_string(id); } MeshModel::MeshModel(vtkPolyData* mesh, int id) { if(mesh != NULL) { _meshBase = vtkPolyData::New();//mesh; _meshBase->DeepCopy(mesh); _meshTemp = vtkPolyData::New(); _meshTemp->DeepCopy(_meshBase); _meshId = id; _name = "mesh-" + std::to_string(id); } } MeshModel::MeshModel(MeshModel* meshModel) { _meshBase = NULL; _meshTemp = NULL; if(meshModel->GetMeshBase() != NULL) { _meshBase = vtkPolyData::New(); _meshBase->DeepCopy(meshModel->GetMeshBase()); ResetMeshTemp_(); } _meshId = meshModel->GetId(); _name = "mesh-" + std::to_string(meshModel->GetId()); } MeshModel::~MeshModel() { if(_meshBase != NULL) { _meshBase->Delete(); } if(_meshTemp != NULL) { _meshTemp->Delete(); } } void MeshModel::ResetMeshTemp_() { if (_meshBase!=NULL) { if (_meshTemp!=NULL) { _meshTemp->Delete(); } // if _meshTemp = vtkPolyData::New(); _meshTemp->DeepCopy(_meshBase); } else { if (_meshTemp!=NULL) { _meshTemp->Delete(); _meshTemp = NULL; } } } void MeshModel::SetMeshBase(vtkPolyData* mesh) { if (mesh!=NULL) { if(_meshBase != NULL) { _meshBase->Delete(); } _meshBase = vtkPolyData::New(); _meshBase->DeepCopy(mesh); ResetMeshTemp_(); } // if mesh } void MeshModel::SetMeshMemoryMode(vtkPolyData* mesh) { if(_meshBase != NULL) { _meshBase->Delete(); _meshBase = NULL; } if(mesh != NULL) { _meshBase = vtkPolyData::New(); _meshBase->DeepCopy(mesh); } } void MeshModel::ResetMeshTemp() { ResetMeshTemp_(); } void MeshModel::CopySetMeshBase(vtkPolyData* mesh) { if (mesh!=NULL) { vtkPolyData *newMesh = vtkPolyData::New(); newMesh->DeepCopy( mesh ); SetMeshBase(newMesh); } // if mesh } vtkPolyData* MeshModel::GetMeshBase() { return _meshBase; } vtkPolyData* MeshModel::GetMeshTemp() { return _meshTemp; } int MeshModel::GetId() { return _meshId; } std::string MeshModel::GetName() { return _name; } //////////////////// /////////////////////// MESH MANAGER //////////////////// MeshManagerModel::MeshManagerModel() { currentMesh = 0; meshId = 0; history = new HistoryHandler(15); lastModified = 0; memoryMode = false; } MeshManagerModel::~MeshManagerModel() { DeleteAll(); history->CleanHistory(); delete history; } void MeshManagerModel::RefreshOutputs(bool signalBox) // virtual { } void MeshManagerModel::SetHistory(int maxCapacity) { if(history != NULL){ ResetHistory(); delete history; } history = new HistoryHandler(maxCapacity); } void MeshManagerModel::ResetHistory() { history->CleanHistory(); } int MeshManagerModel::GetNumberOfMeshes() { return _meshes.size(); } void MeshManagerModel::AddMesh_(vtkPolyData* mesh) { if(mesh != NULL) { _meshes.push_back(std::make_shared(mesh, meshId)); meshId++; }else{ printf("PG MeshManagerModel::AddMesh Mesh is null \n"); } } void MeshManagerModel::AddMesh(vtkPolyData* mesh) { Save(); AddMesh_(mesh); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::AddMeshes_(std::vector meshList) { if(!meshList.empty()) { MeshModel *meshModel; for(int i = 0; i < meshList.size(); i++){ _meshes.push_back(std::make_shared(meshList[i], meshId)); meshId++; } }else{ printf("PG MeshManagerModel::AddMeshes Empty list of meshes \n"); } } void MeshManagerModel::AddMeshes(std::vector meshList) { Save(); AddMeshes_(meshList); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::AddEmptyMesh_() { _meshes.push_back(std::make_shared(meshId)); meshId++; } void MeshManagerModel::AddEmptyMesh() { Save(); AddEmptyMesh_(); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::InsertMeshesAtCurrent_(std::vector meshList) { if(!meshList.empty()) { std::vector> tmpVect; MeshModel *meshModel; for(int i = 0; i < meshList.size(); i++){ tmpVect.push_back(std::make_shared(meshList[i], meshId)); meshId++; } _meshes.insert(_meshes.begin() + currentMesh, tmpVect.begin(), tmpVect.end()); }else{ printf("PG MeshManagerModel::InsertMeshesAtCurrent Empty list of meshes \n"); } } void MeshManagerModel::InsertMeshesAtCurrent(std::vector meshList) { Save(); InsertMeshesAtCurrent_(meshList); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::SelectMesh(int i) { if(i >= 0 && i < _meshes.size()) { int prevCurrent = currentMesh; currentMesh = i; if(prevCurrent != i) { RefreshOutputs(true); } } else{ printf("PG MeshManagerModel::SelectMesh index out of bounds \n"); } } void MeshManagerModel::SelectMeshByName(std::string meshName) { if(!_meshes.empty()) { bool found = false; for(int i = 0; i < _meshes.size() && !found; i++){ if(_meshes.at(i)->GetName() == meshName) { found = true; SelectMesh(i); } } } } void MeshManagerModel::DeleteMesh_(int position) { if(position >= 0 && position < _meshes.size()) { _meshes.erase(_meshes.begin() + position); currentMesh = currentMesh + (position <= currentMesh?-1:0); if(currentMesh < 0) { currentMesh = 0; } } } void MeshManagerModel::DeleteMesh(int position) { Save(); DeleteMesh_(position); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::DeleteMeshByName(std::string meshName) { if(!_meshes.empty()) { bool found = false; for(int i = 0; i < _meshes.size() && !found; i++){ if(_meshes.at(i)->GetName() == meshName) { found = true; DeleteMesh_(i); RefreshOutputs(true); } } } } void MeshManagerModel::DeleteCurrentMesh() { if(!_meshes.empty()) { Save(); DeleteMesh_(currentMesh); lastModified = currentMesh; RefreshOutputs(true); } } void MeshManagerModel::ReplaceMesh(std::vector meshList) { Save(); if(GetNumberOfMeshes() >= 1) { DeleteMesh_(currentMesh); } InsertMeshesAtCurrent_(meshList); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::DeleteAll_() { if(!_meshes.empty()) { currentMesh = 0; _meshes.clear(); RefreshOutputs(true); } } void MeshManagerModel::DeleteAll() { Save(); DeleteAll_(); lastModified = currentMesh; RefreshOutputs(true); } void MeshManagerModel::NextMesh() { currentMesh++; if(currentMesh >= _meshes.size()) { currentMesh = _meshes.size()-1; } RefreshOutputs(true); } void MeshManagerModel::PreviousMesh() { currentMesh--; if(currentMesh < 0) { currentMesh = 0; } RefreshOutputs(true); } std::shared_ptr MeshManagerModel::GetMeshModel() { return _meshes.at(currentMesh); } vtkPolyData* MeshManagerModel::GetMeshBase() { if(!_meshes.empty()) { return _meshes.at(currentMesh)->GetMeshBase(); } else{ return NULL; } } vtkPolyData* MeshManagerModel::GetMeshTemp() { if(!_meshes.empty()) { return _meshes.at(currentMesh)->GetMeshTemp(); } else{ return NULL; } } void MeshManagerModel::SetMeshBase(vtkPolyData* mesh) { if(!_meshes.empty()) { Save(); _meshes.at(currentMesh) = std::make_shared(_meshes.at(currentMesh).get()); _meshes.at(currentMesh)->SetMeshBase(mesh); lastModified = currentMesh; RefreshOutputs(true); }else{ printf("PG MeshManagerModel::SetMeshBase Mesh vector is empty \n"); } } void MeshManagerModel::MeshMemoryModeOn() { memoryMode = true; } void MeshManagerModel::MeshMemoryModeOff() { memoryMode = false; } void MeshManagerModel::SetMeshMemoryMode(vtkPolyData* mesh) { if(_meshes.size() > 1) { DeleteAll_(); } if(_meshes.size() == 0) { AddEmptyMesh_(); } _meshes.at(currentMesh)->SetMeshMemoryMode(mesh); ResetHistory(); SaveMemoryMode(); RefreshOutputs(true); } void MeshManagerModel::ResetMeshTemp() { if(!_meshes.empty()) { _meshes.at(currentMesh)->ResetMeshTemp(); RefreshOutputs(true); }else{ printf("PG MeshManagerModel::ResetMeshTemp Mesh vector is empty \n"); } } void MeshManagerModel::CopySetMeshBase(vtkPolyData* mesh) { if(!_meshes.empty()) { Save(); _meshes.at(currentMesh) = std::make_shared(_meshes.at(currentMesh).get()); _meshes.at(currentMesh)->CopySetMeshBase(mesh); lastModified = currentMesh; RefreshOutputs(true); } else{ printf("PG MeshManagerModel::CopySetMeshBase Mesh vector is empty \n"); } } std::vector MeshManagerModel::GetMeshNames() { std::vector names; for(int i = 0; i < _meshes.size(); i++){ names.push_back(_meshes.at(i)->GetName()); } return names; } std::vector MeshManagerModel::GetAllPolyDatas() { std::vector polydatas; for(int i = 0; i < _meshes.size(); i++){ polydatas.push_back(_meshes.at(i)->GetMeshBase()); } return polydatas; } int MeshManagerModel::GetCurrentMesh() { return currentMesh; } void MeshManagerModel::Undo() { if(history->UndoSize() > 0) { if(memoryMode == false){ RestoreState(history->Undo(new ManagerState(_meshes, meshId, lastModified))); RefreshOutputs(true); } else if(history->UndoSize() > 1){ RestoreStateMemoryMode(history->UndoKeepCurrent()); } } } void MeshManagerModel::Redo() { if(history->RedoSize() > 0) { if(memoryMode == false){ RestoreState(history->Redo(new ManagerState(_meshes, meshId, lastModified))); RefreshOutputs(true); } else{ RestoreStateMemoryMode(history->RedoKeepCurrent()); } } } void MeshManagerModel::Save() { history->Save(new ManagerState(_meshes, meshId, currentMesh)); } void MeshManagerModel::SaveMemoryMode() { if(_meshes.size() == 1 && memoryMode) { std::vector> savedMesh; savedMesh.push_back(std::make_shared(_meshes.at(0).get())); history->Save(new ManagerState(savedMesh, meshId, 0)); } else{ printf("PG MeshManagerModel::SaveMemoryMode WARNING Mesh vector has invalid size or memoryMode is not set \n"); } } void MeshManagerModel::RestoreState(ManagerState* state) { if(state != NULL) { _meshes = state->GetMeshes(); meshId = state->GetMeshId(); currentMesh = state->GetModifiedPos(); lastModified = state->GetModifiedPos(); delete state; } else{ printf("PG MeshManagerModel::RestoreState WARNING State is NULL \n"); } } void MeshManagerModel::RestoreStateMemoryMode(ManagerState* state){ if(_meshes.size() == 1 && state != NULL) { vtkPoints* statePoints = vtkPoints::New(); statePoints->DeepCopy(state->GetMeshes().at(0)->GetMeshBase()->GetPoints()); _meshes.at(0)->GetMeshBase()->SetPoints(statePoints); _meshes.at(0)->GetMeshBase()->GetPoints()->Modified(); _meshes.at(0)->GetMeshBase()->Modified(); }else{ printf("PG MeshManagerModel::RestoreStateMemoryMode WARNING Mesh vector has invalid size or state is NULL\n"); } } // //Manager State // MeshManagerModel::ManagerState::ManagerState(std::vector> meshesToSave, int meshId, int modifiedPos) { savedMeshes = meshesToSave; savedId = meshId; savedModifiedPos = modifiedPos; } MeshManagerModel::ManagerState::~ManagerState() { savedMeshes.clear(); } std::vector>& MeshManagerModel::ManagerState::GetMeshes() { return savedMeshes; } int MeshManagerModel::ManagerState::GetMeshId() { return savedId; } int MeshManagerModel::ManagerState::GetModifiedPos() { return savedModifiedPos; }