00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkDataStorage.h"
00019
00020 #include "mitkDataNode.h"
00021 #include "mitkProperties.h"
00022 #include "mitkNodePredicateBase.h"
00023 #include "mitkNodePredicateProperty.h"
00024 #include "mitkGroupTagProperty.h"
00025 #include "itkMutexLockHolder.h"
00026
00027 #include "itkCommand.h"
00028
00029
00030 mitk::DataStorage::DataStorage() : itk::Object()
00031 , m_BlockNodeModifiedEvents(false)
00032 {
00033 }
00034
00035
00036 mitk::DataStorage::~DataStorage()
00037 {
00039
00040
00041
00042
00043
00044 }
00045
00046
00047 void mitk::DataStorage::Add(mitk::DataNode* node, mitk::DataNode* parent)
00048 {
00049 mitk::DataStorage::SetOfObjects::Pointer parents = mitk::DataStorage::SetOfObjects::New();
00050 parents->InsertElement(0, parent);
00051 this->Add(node, parents);
00052 }
00053
00054
00055 void mitk::DataStorage::Remove(const mitk::DataStorage::SetOfObjects* nodes)
00056 {
00057 if (nodes == NULL)
00058 return;
00059 for (mitk::DataStorage::SetOfObjects::ConstIterator it = nodes->Begin(); it != nodes->End(); it++)
00060 this->Remove(it.Value());
00061 }
00062
00063
00064 mitk::DataStorage::SetOfObjects::ConstPointer mitk::DataStorage::GetSubset(const NodePredicateBase* condition) const
00065 {
00066 mitk::DataStorage::SetOfObjects::ConstPointer result = this->FilterSetOfObjects(this->GetAll(), condition);
00067 return result;
00068 }
00069
00070
00071 mitk::DataNode* mitk::DataStorage::GetNamedNode(const char* name) const
00072
00073 {
00074 if (name == NULL)
00075 return NULL;
00076
00077 mitk::StringProperty::Pointer s(mitk::StringProperty::New(name));
00078 mitk::NodePredicateProperty::Pointer p = mitk::NodePredicateProperty::New("name", s);
00079 mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetSubset(p);
00080 if (rs->Size() >= 1)
00081 return rs->GetElement(0);
00082 else
00083 return NULL;
00084 }
00085
00086
00087 mitk::DataNode* mitk::DataStorage::GetNode(const NodePredicateBase* condition) const
00088 {
00089 if (condition == NULL)
00090 return NULL;
00091
00092 mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetSubset(condition);
00093 if (rs->Size() >= 1)
00094 return rs->GetElement(0);
00095 else
00096 return NULL;
00097 }
00098
00099 mitk::DataNode* mitk::DataStorage::GetNamedDerivedNode(const char* name, const mitk::DataNode* sourceNode, bool onlyDirectDerivations) const
00100 {
00101 if (name == NULL)
00102 return NULL;
00103
00104 mitk::StringProperty::Pointer s(mitk::StringProperty::New(name));
00105 mitk::NodePredicateProperty::Pointer p = mitk::NodePredicateProperty::New("name", s);
00106 mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDerivations(sourceNode, p, onlyDirectDerivations);
00107 if (rs->Size() >= 1)
00108 return rs->GetElement(0);
00109 else
00110 return NULL;
00111 }
00112
00113
00114 void mitk::DataStorage::PrintSelf(std::ostream& os, itk::Indent indent) const
00115 {
00116
00117 mitk::DataStorage::SetOfObjects::ConstPointer all = this->GetAll();
00118 os << indent << "DataStorage " << this << " is managing " << all->Size() << " objects. List of objects:" << std::endl;
00119 for (mitk::DataStorage::SetOfObjects::ConstIterator allIt = all->Begin(); allIt != all->End(); allIt++)
00120 {
00121 std::string name;
00122 allIt.Value()->GetName(name);
00123 std::string datatype;
00124 if (allIt.Value()->GetData() != NULL)
00125 datatype = allIt.Value()->GetData()->GetNameOfClass();
00126 os << indent << " " << allIt.Value().GetPointer() << "<" << datatype << ">: " << name << std::endl;
00127 mitk::DataStorage::SetOfObjects::ConstPointer parents = this->GetSources(allIt.Value());
00128 if (parents->Size() > 0)
00129 {
00130 os << indent << " Direct sources: ";
00131 for (mitk::DataStorage::SetOfObjects::ConstIterator parentIt = parents->Begin(); parentIt != parents->End(); parentIt++)
00132 os << parentIt.Value().GetPointer() << ", ";
00133 os << std::endl;
00134 }
00135 mitk::DataStorage::SetOfObjects::ConstPointer derivations = this->GetDerivations(allIt.Value());
00136 if (derivations->Size() > 0)
00137 {
00138 os << indent << " Direct derivations: ";
00139 for (mitk::DataStorage::SetOfObjects::ConstIterator derivationIt = derivations->Begin(); derivationIt != derivations->End(); derivationIt++)
00140 os << derivationIt.Value().GetPointer() << ", ";
00141 os << std::endl;
00142 }
00143 }
00144 os << std::endl;
00145 }
00146
00147
00148 mitk::DataStorage::SetOfObjects::ConstPointer mitk::DataStorage::FilterSetOfObjects(const SetOfObjects* set, const NodePredicateBase* condition) const
00149 {
00150 if (set == NULL)
00151 return NULL;
00152
00153 mitk::DataStorage::SetOfObjects::Pointer result = mitk::DataStorage::SetOfObjects::New();
00154 for (mitk::DataStorage::SetOfObjects::ConstIterator it = set->Begin(); it != set->End(); it++)
00155 if (condition == NULL || condition->CheckNode(it.Value()) == true)
00156 result->InsertElement(result->Size(), it.Value());
00157
00158 return mitk::DataStorage::SetOfObjects::ConstPointer(result);
00159 }
00160
00161
00162 const mitk::DataNode::GroupTagList mitk::DataStorage::GetGroupTags() const
00163 {
00164 DataNode::GroupTagList result;
00165 SetOfObjects::ConstPointer all = this->GetAll();
00166 if (all.IsNull())
00167 return result;
00168
00169 for (mitk::DataStorage::SetOfObjects::ConstIterator nodeIt = all->Begin(); nodeIt != all->End(); nodeIt++)
00170 {
00171 mitk::PropertyList* pl = nodeIt.Value()->GetPropertyList();
00172 for (mitk::PropertyList::PropertyMap::const_iterator propIt = pl->GetMap()->begin(); propIt != pl->GetMap()->end(); propIt++)
00173 if (dynamic_cast<mitk::GroupTagProperty*>(propIt->second.first.GetPointer()) != NULL)
00174 result.insert(propIt->first);
00175 }
00176
00177 return result;
00178 }
00179
00180
00181 void mitk::DataStorage::EmitAddNodeEvent(const mitk::DataNode* node)
00182 {
00183 AddNodeEvent.Send(node);
00184 }
00185
00186
00187 void mitk::DataStorage::EmitRemoveNodeEvent(const mitk::DataNode* node)
00188 {
00189 RemoveNodeEvent.Send(node);
00190 }
00191
00192 void mitk::DataStorage::OnNodeModifiedOrDeleted( const itk::Object *caller, const itk::EventObject &event )
00193 {
00194 if(m_BlockNodeModifiedEvents)
00195 return;
00196
00197 const mitk::DataNode* _Node = dynamic_cast<const mitk::DataNode*>(caller);
00198 if(_Node)
00199 {
00200 const itk::ModifiedEvent* modEvent = dynamic_cast<const itk::ModifiedEvent*>(&event);
00201 if(modEvent)
00202 ChangedNodeEvent.Send(_Node);
00203 else
00204 DeleteNodeEvent.Send(_Node);
00205 }
00206 }
00207
00208
00209 void mitk::DataStorage::AddListeners( const mitk::DataNode* _Node )
00210 {
00211 itk::MutexLockHolder<itk::SimpleFastMutexLock> locked(m_MutexOne);
00212
00213 mitk::DataNode* NonConstNode = const_cast<mitk::DataNode*>(_Node);
00214 if(_Node && m_NodeModifiedObserverTags
00215 .find(NonConstNode) == m_NodeModifiedObserverTags.end())
00216 {
00217 itk::MemberCommand<mitk::DataStorage>::Pointer nodeModifiedCommand =
00218 itk::MemberCommand<mitk::DataStorage>::New();
00219 nodeModifiedCommand->SetCallbackFunction(this
00220 , &mitk::DataStorage::OnNodeModifiedOrDeleted);
00221 m_NodeModifiedObserverTags[NonConstNode]
00222 = NonConstNode->AddObserver(itk::ModifiedEvent(), nodeModifiedCommand);
00223
00224
00225 itk::MemberCommand<mitk::DataStorage>::Pointer deleteCommand =
00226 itk::MemberCommand<mitk::DataStorage>::New();
00227 deleteCommand->SetCallbackFunction(this, &mitk::DataStorage::OnNodeModifiedOrDeleted);
00228
00229 m_NodeDeleteObserverTags[NonConstNode]
00230 = NonConstNode->AddObserver(itk::DeleteEvent(), deleteCommand);
00231 }
00232 }
00233
00234
00235 void mitk::DataStorage::RemoveListeners( const mitk::DataNode* _Node )
00236 {
00237 itk::MutexLockHolder<itk::SimpleFastMutexLock> locked(m_MutexOne) ;
00238
00239 mitk::DataNode* NonConstNode = const_cast<mitk::DataNode*>(_Node);
00240 if(_Node && m_NodeModifiedObserverTags
00241 .find(NonConstNode) != m_NodeModifiedObserverTags.end())
00242 {
00243
00244
00245 NonConstNode->RemoveObserver(m_NodeModifiedObserverTags
00246 .find(NonConstNode)->second);
00247 NonConstNode->RemoveObserver(m_NodeDeleteObserverTags
00248 .find(NonConstNode)->second);
00249 m_NodeModifiedObserverTags.erase(NonConstNode);
00250 m_NodeDeleteObserverTags.erase(NonConstNode);
00251 }
00252 }
00253
00254 mitk::TimeSlicedGeometry::Pointer mitk::DataStorage::ComputeBoundingGeometry3D( const SetOfObjects* input, const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
00255 {
00256 if (input == NULL)
00257 throw std::invalid_argument("DataStorage: input is invalid");
00258
00259 BoundingBox::PointsContainer::Pointer pointscontainer=BoundingBox::PointsContainer::New();
00260
00261 BoundingBox::PointIdentifier pointid=0;
00262 Point3D point;
00263
00264 Vector3D minSpacing;
00265 minSpacing.Fill(ScalarTypeNumericTraits::max());
00266
00267 ScalarType stmin, stmax;
00268 stmin= ScalarTypeNumericTraits::NonpositiveMin();
00269 stmax= ScalarTypeNumericTraits::max();
00270
00271 ScalarType minimalIntervallSize = stmax;
00272 ScalarType minimalTime = stmax;
00273 ScalarType maximalTime = 0;
00274
00275
00276 mitk::ScalarType nullpoint[]={0,0,0,0,0,0};
00277 BoundingBox::BoundsArrayType itkBoundsZero(nullpoint);
00278
00279 for (SetOfObjects::ConstIterator it = input->Begin(); it != input->End(); ++it)
00280 {
00281 DataNode::Pointer node = it->Value();
00282 if((node.IsNotNull()) && (node->GetData() != NULL) &&
00283 (node->GetData()->IsEmpty()==false) &&
00284 node->IsOn(boolPropertyKey, renderer) &&
00285 node->IsOn(boolPropertyKey2, renderer)
00286 )
00287 {
00288 const TimeSlicedGeometry* geometry = node->GetData()->GetUpdatedTimeSlicedGeometry();
00289 if (geometry != NULL )
00290 {
00291
00292 BoundingBox::BoundsArrayType itkBounds = geometry->GetBoundingBox()->GetBounds();
00293 if (itkBounds == itkBoundsZero)
00294 {
00295 continue;
00296 }
00297
00298 unsigned char i;
00299 for(i=0; i<8; ++i)
00300 {
00301 point = geometry->GetCornerPoint(i);
00302 if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < large)
00303 pointscontainer->InsertElement( pointid++, point);
00304 else
00305 {
00306 itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. Node: " << node );
00307 }
00308 }
00309
00310 try
00311 {
00312 AffineTransform3D::Pointer inverseTransform = AffineTransform3D::New();
00313 geometry->GetIndexToWorldTransform()->GetInverse(inverseTransform);
00314 vnl_vector< AffineTransform3D::MatrixType::ValueType > unitVector(3);
00315 int axis;
00316 for(axis = 0; axis < 3; ++axis)
00317 {
00318 unitVector.fill(0);
00319 unitVector[axis] = 1.0;
00320 ScalarType mmPerPixel = 1.0/(inverseTransform->GetMatrix()*unitVector).magnitude();
00321 if(minSpacing[axis] > mmPerPixel)
00322 {
00323 minSpacing[axis] = mmPerPixel;
00324 }
00325 }
00326
00327
00328
00329 TimeBounds minTB = geometry->GetTimeBounds();
00330 for (unsigned int i=0; i<geometry->GetTimeSteps(); i++)
00331 {
00332 const TimeBounds & curTimeBounds = node->GetData()->GetGeometry(i)->GetTimeBounds();
00333
00334 if ((curTimeBounds[0]<minimalTime)&&(curTimeBounds[0]>stmin))
00335 {
00336 minimalTime=curTimeBounds[0];
00337 }
00338
00339 if ((curTimeBounds[1]>maximalTime)&&(curTimeBounds[1]<stmax))
00340 {
00341 maximalTime = curTimeBounds[1];
00342 }
00343
00344 if (curTimeBounds[1]-curTimeBounds[0]<minTB[1]-minTB[0])
00345 {
00346 minTB = curTimeBounds;
00347 }
00348 }
00349
00350 if (minTB[1]-minTB[0]<minimalIntervallSize)
00351 {
00352 minimalIntervallSize = minTB[1]-minTB[0];
00353 }
00354 }
00355 catch(itk::ExceptionObject e)
00356 {
00357 MITK_ERROR << e << std::endl;
00358 }
00359 }
00360 }
00361 }
00362
00363 BoundingBox::Pointer result = BoundingBox::New();
00364 result->SetPoints(pointscontainer);
00365 result->ComputeBoundingBox();
00366
00367
00368 TimeBounds minTimeBounds;
00369 minTimeBounds[0] = 0;
00370 minTimeBounds[1] = 1;
00371
00372 unsigned int numberOfTimeSteps = 1;
00373 if (maximalTime!=0)
00374 {
00375 minTimeBounds[0] = minimalTime;
00376 minTimeBounds[1] = minimalTime + minimalIntervallSize;
00377 numberOfTimeSteps = (maximalTime-minimalTime)/minimalIntervallSize;
00378 }
00379
00380 TimeSlicedGeometry::Pointer timeSlicedGeometry = NULL;
00381 if ( result->GetPoints()->Size()>0 )
00382 {
00383
00384 Geometry3D::Pointer geometry = Geometry3D::New();
00385 geometry->Initialize();
00386
00387
00388 BoundingBox::BoundsArrayType bounds = result->GetBounds();
00389 int i;
00390 for(i = 0; i < 6; ++i)
00391 {
00392 bounds[i] /= minSpacing[i/2];
00393 }
00394 geometry->SetBounds(bounds);
00395 geometry->SetSpacing(minSpacing);
00396 geometry->SetTimeBounds(minTimeBounds);
00397
00398 timeSlicedGeometry = TimeSlicedGeometry::New();
00399 timeSlicedGeometry->InitializeEvenlyTimed(geometry,numberOfTimeSteps);
00400 }
00401 return timeSlicedGeometry;
00402 }
00403
00404 mitk::TimeSlicedGeometry::Pointer mitk::DataStorage::ComputeBoundingGeometry3D( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
00405 {
00406 return this->ComputeBoundingGeometry3D(this->GetAll(), boolPropertyKey, renderer, boolPropertyKey2);
00407 }
00408
00409 mitk::TimeSlicedGeometry::Pointer mitk::DataStorage::ComputeVisibleBoundingGeometry3D( mitk::BaseRenderer* renderer, const char* boolPropertyKey )
00410 {
00411 return ComputeBoundingGeometry3D( "visible", renderer, boolPropertyKey );
00412 }
00413
00414
00415 mitk::BoundingBox::Pointer mitk::DataStorage::ComputeBoundingBox( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
00416 {
00417 BoundingBox::PointsContainer::Pointer pointscontainer=BoundingBox::PointsContainer::New();
00418
00419 BoundingBox::PointIdentifier pointid=0;
00420 Point3D point;
00421
00422
00423 mitk::ScalarType nullpoint[]={0,0,0,0,0,0};
00424 BoundingBox::BoundsArrayType itkBoundsZero(nullpoint);
00425
00426 SetOfObjects::ConstPointer all = this->GetAll();
00427 for (SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
00428 {
00429 DataNode::Pointer node = it->Value();
00430 if((node.IsNotNull()) && (node->GetData() != NULL) &&
00431 (node->GetData()->IsEmpty()==false) &&
00432 node->IsOn(boolPropertyKey, renderer) &&
00433 node->IsOn(boolPropertyKey2, renderer)
00434 )
00435 {
00436 const Geometry3D* geometry = node->GetData()->GetUpdatedTimeSlicedGeometry();
00437 if (geometry != NULL )
00438 {
00439
00440 BoundingBox::BoundsArrayType itkBounds = geometry->GetBoundingBox()->GetBounds();
00441 if (itkBounds == itkBoundsZero)
00442 {
00443 continue;
00444 }
00445
00446 unsigned char i;
00447 for(i=0; i<8; ++i)
00448 {
00449 point = geometry->GetCornerPoint(i);
00450 if(point[0]*point[0]+point[1]*point[1]+point[2]*point[2] < large)
00451 pointscontainer->InsertElement( pointid++, point);
00452 else
00453 {
00454 itkGenericOutputMacro( << "Unrealistically distant corner point encountered. Ignored. Node: " << node );
00455 }
00456 }
00457 }
00458 }
00459
00460 }
00461
00462 BoundingBox::Pointer result = BoundingBox::New();
00463 result->SetPoints(pointscontainer);
00464 result->ComputeBoundingBox();
00465
00466 return result;
00467 }
00468
00469
00470 mitk::TimeBounds mitk::DataStorage::ComputeTimeBounds( const char* boolPropertyKey, mitk::BaseRenderer* renderer, const char* boolPropertyKey2)
00471 {
00472 TimeBounds timeBounds;
00473
00474 ScalarType stmin, stmax, cur;
00475
00476 stmin= ScalarTypeNumericTraits::NonpositiveMin();
00477 stmax= ScalarTypeNumericTraits::max();
00478
00479 timeBounds[0]=stmax; timeBounds[1]=stmin;
00480
00481 SetOfObjects::ConstPointer all = this->GetAll();
00482 for (SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
00483 {
00484 DataNode::Pointer node = it->Value();
00485 if((node.IsNotNull()) && (node->GetData() != NULL) &&
00486 (node->GetData()->IsEmpty()==false) &&
00487 node->IsOn(boolPropertyKey, renderer) &&
00488 node->IsOn(boolPropertyKey2, renderer)
00489 )
00490 {
00491 const Geometry3D* geometry = node->GetData()->GetUpdatedTimeSlicedGeometry();
00492 if (geometry != NULL )
00493 {
00494 const TimeBounds & curTimeBounds = geometry->GetTimeBounds();
00495 cur=curTimeBounds[0];
00496
00497 if((cur > stmin) && (cur < timeBounds[0]))
00498 timeBounds[0] = cur;
00499
00500 cur=curTimeBounds[1];
00501
00502 if((cur < stmax) && (cur > timeBounds[1]))
00503 timeBounds[1] = cur;
00504 }
00505 }
00506 }
00507 if(!(timeBounds[0] < stmax))
00508 {
00509 timeBounds[0] = stmin;
00510 timeBounds[1] = stmax;
00511 }
00512 return timeBounds;
00513 }