mitk::ProportionalTimeGeometry::Pointer mitk::ProportionalTimeGeometryToXML::FromXML(TiXmlElement *timeGeometryElement)
{
  if (!timeGeometryElement)
  {
    MITK_ERROR << "Cannot deserialize ProportionalTimeGeometry from nullptr.";
    return nullptr;
  }

  int numberOfTimeSteps = 0;

  if (TIXML_SUCCESS != timeGeometryElement->QueryIntAttribute("NumberOfTimeSteps", &numberOfTimeSteps))
  {
    MITK_WARN << "<ProportionalTimeGeometry> found without NumberOfTimeSteps attribute. Counting...";
  }

  // might be missing!
  TimePointType firstTimePoint;
  std::string firstTimePoint_s;
  TimePointType stepDuration;
  std::string stepDuration_s;
  try
  {
    if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("FirstTimePoint", &firstTimePoint_s))
    {
      firstTimePoint = boost::lexical_cast<double>(firstTimePoint_s);
    }
    else
    {
      firstTimePoint = -std::numeric_limits<TimePointType>::max();
    }

    if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("StepDuration", &stepDuration_s))
    {
      stepDuration = boost::lexical_cast<double>(stepDuration_s);
    }
    else
    {
      stepDuration = std::numeric_limits<TimePointType>::infinity();
    }
  }
  catch (boost::bad_lexical_cast &e)
  {
    MITK_ERROR << "Could not parse string as number: " << e.what();
    return nullptr;
  }

  // list of all geometries with their time steps
  std::multimap<TimeStepType, BaseGeometry::Pointer> allReadGeometries;

  int indexForUnlabeledTimeStep(-1);
  for (TiXmlElement *currentElement = timeGeometryElement->FirstChildElement(); currentElement != nullptr;
       currentElement = currentElement->NextSiblingElement())
  {
    // different geometries could have been inside a ProportionalTimeGeometry.
    // By now, we only support Geometry3D
    std::string tagName = currentElement->Value();
    if (tagName == "Geometry3D")
    {
      Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement);
      if (restoredGeometry.IsNotNull())
      {
        int timeStep(-1);
        if (TIXML_SUCCESS != currentElement->QueryIntAttribute("TimeStep", &timeStep))
        {
          timeStep = indexForUnlabeledTimeStep--; // decrement index for next one
          MITK_WARN << "Found <Geometry3D> without 'TimeStep' attribute in <ProportionalTimeGeometry>. No guarantees "
                       "on order anymore.";
        }

        if (allReadGeometries.count(static_cast<TimeStepType>(timeStep)) > 0)
        {
          MITK_WARN << "Found <Geometry3D> tags with identical 'TimeStep' attribute in <ProportionalTimeGeometry>. No "
                       "guarantees on order anymore.";
        }

        allReadGeometries.insert(std::make_pair(static_cast<TimeStepType>(timeStep), restoredGeometry.GetPointer()));
      }
    }
    else
    {
      MITK_WARN << "Found unsupported tag <" << tagName << "> inside <ProportionalTimeGeometry>. Ignoring.";
    }
  }

  // now add all BaseGeometries that were read to a new instance
  // of ProportionalTimeGeometry
  ProportionalTimeGeometry::Pointer newTimeGeometry = ProportionalTimeGeometry::New();
  newTimeGeometry->SetFirstTimePoint(firstTimePoint);
  newTimeGeometry->SetStepDuration(stepDuration);
  newTimeGeometry->ReserveSpaceForGeometries(allReadGeometries.size());

  TimeStepType t(0);
  for (auto entry : allReadGeometries)
  {
    // We add items with newly assigned time steps.
    // This avoids great confusion when a file contains
    // bogus numbers.
    newTimeGeometry->SetTimeStepGeometry(entry.second, t++);
  }

  // Need to re-calculate global bounding box.
  // This is neither stored in a file, nor done by SetTimeStepGeometry
  newTimeGeometry->UpdateBoundingBox();

  return newTimeGeometry;
}
bool
RenderingManager
::InitializeViews( const Geometry3D * dataGeometry, RequestType type, bool preserveRoughOrientationInWorldSpace )
{
    MITK_DEBUG << "initializing views";

    bool boundingBoxInitialized = false;

    Geometry3D::ConstPointer geometry = dataGeometry;

    if (dataGeometry && preserveRoughOrientationInWorldSpace)
    {

        // clone the input geometry
        Geometry3D::Pointer modifiedGeometry = dynamic_cast<Geometry3D*>( dataGeometry->Clone().GetPointer() );
        assert(modifiedGeometry.IsNotNull());

        // construct an affine transform from it
        AffineGeometryFrame3D::TransformType::Pointer transform = AffineGeometryFrame3D::TransformType::New();
        assert( modifiedGeometry->GetIndexToWorldTransform() );
        transform->SetMatrix( modifiedGeometry->GetIndexToWorldTransform()->GetMatrix() );
        transform->SetOffset( modifiedGeometry->GetIndexToWorldTransform()->GetOffset() );

        // get transform matrix
        AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType& oldMatrix =
            const_cast< AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType& > ( transform->GetMatrix().GetVnlMatrix() );
        AffineGeometryFrame3D::TransformType::MatrixType::InternalMatrixType newMatrix(oldMatrix);

        // get offset and bound
        Vector3D offset = modifiedGeometry->GetIndexToWorldTransform()->GetOffset();
        Geometry3D::BoundsArrayType oldBounds = modifiedGeometry->GetBounds();
        Geometry3D::BoundsArrayType newBounds = modifiedGeometry->GetBounds();

        // get rid of rotation other than pi/2 degree
        for ( unsigned int i = 0; i < 3; ++i )
        {

            // i-th column of the direction matrix
            Vector3D currentVector;
            currentVector[0] = oldMatrix(0,i);
            currentVector[1] = oldMatrix(1,i);
            currentVector[2] = oldMatrix(2,i);

            // matchingRow will store the row that holds the biggest
            // value in the column
            unsigned int matchingRow = 0;

            // maximum value in the column
            float max = std::numeric_limits<float>::min();

            // sign of the maximum value (-1 or 1)
            int sign = 1;

            // iterate through the column vector
            for (unsigned int dim = 0; dim < 3; ++dim)
            {
                if ( fabs(currentVector[dim]) > max )
                {
                    matchingRow = dim;
                    max = fabs(currentVector[dim]);
                    if(currentVector[dim]<0)
                        sign = -1;
                    else
                        sign = 1;
                }
            }

            // in case we found a negative maximum,
            // we negate the column and adjust the offset
            // (in order to run through the dimension in the opposite direction)
            if(sign == -1)
            {
                currentVector *= sign;
                offset += modifiedGeometry->GetAxisVector(i);
            }


            // matchingRow is now used as column index to place currentVector
            // correctly in the new matrix
            vnl_vector<ScalarType> newMatrixColumn(3);
            newMatrixColumn[0] = currentVector[0];
            newMatrixColumn[1] = currentVector[1];
            newMatrixColumn[2] = currentVector[2];
            newMatrix.set_column( matchingRow, newMatrixColumn );

            // if a column is moved, we also have to adjust the bounding
            // box accordingly, this is done here
            newBounds[2*matchingRow  ] = oldBounds[2*i  ];
            newBounds[2*matchingRow+1] = oldBounds[2*i+1];
        }

        // set the newly calculated bounds array
        modifiedGeometry->SetBounds(newBounds);

        // set new offset and direction matrix
        AffineGeometryFrame3D::TransformType::MatrixType newMatrixITK( newMatrix );
        transform->SetMatrix( newMatrixITK );
        transform->SetOffset( offset );
        modifiedGeometry->SetIndexToWorldTransform( transform );
        geometry = modifiedGeometry;

    }

    int warningLevel = vtkObject::GetGlobalWarningDisplay();
    vtkObject::GlobalWarningDisplayOff();

    if ( (geometry.IsNotNull() ) && (const_cast< mitk::BoundingBox * >(
                                         geometry->GetBoundingBox())->GetDiagonalLength2() > mitk::eps) )
    {
        boundingBoxInitialized = true;
    }

    if (geometry.IsNotNull() )
    {   // make sure bounding box has an extent bigger than zero in any direction
        // clone the input geometry
        Geometry3D::Pointer modifiedGeometry = dynamic_cast<Geometry3D*>( dataGeometry->Clone().GetPointer() );
        assert(modifiedGeometry.IsNotNull());
        Geometry3D::BoundsArrayType newBounds = modifiedGeometry->GetBounds();
        for( unsigned int dimension = 0; ( 2 * dimension ) < newBounds.Size() ; dimension++ )
        {
            //check for equality but for an epsilon
            if( Equal( newBounds[ 2 * dimension ], newBounds[ 2 * dimension + 1 ] ) )
            {
                newBounds[ 2 * dimension + 1 ] += 1;
            }
        }

        // set the newly calculated bounds array
        modifiedGeometry->SetBounds(newBounds);

        geometry = modifiedGeometry;
    }

    RenderWindowList::iterator it;
    for ( it = m_RenderWindowList.begin(); it != m_RenderWindowList.end(); ++it )
    {
        mitk::BaseRenderer *baseRenderer =
            mitk::BaseRenderer::GetInstance( it->first );

        baseRenderer->GetDisplayGeometry()->SetConstrainZoomingAndPanning(m_ConstrainedPaddingZooming);

        int id = baseRenderer->GetMapperID();
        if ( ((type == REQUEST_UPDATE_ALL)
                || ((type == REQUEST_UPDATE_2DWINDOWS) && (id == 1))
                || ((type == REQUEST_UPDATE_3DWINDOWS) && (id == 2)))
           )
        {
            this->InternalViewInitialization( baseRenderer, geometry,
                                              boundingBoxInitialized, id );
        }
    }

    if ( m_TimeNavigationController != NULL )
    {
        if ( boundingBoxInitialized )
        {
            m_TimeNavigationController->SetInputWorldGeometry( geometry );
        }
        m_TimeNavigationController->Update();
    }

    this->RequestUpdateAll( type );

    vtkObject::SetGlobalWarningDisplay( warningLevel );

    // Inform listeners that views have been initialized
    this->InvokeEvent( mitk::RenderingManagerViewsInitializedEvent() );


    return boundingBoxInitialized;
}
std::vector<itk::SmartPointer<mitk::BaseData>> mitk::GeometryDataReaderService::Read()
{
  // Switch the current locale to "C"
  LocaleSwitch localeSwitch("C");

  std::vector<itk::SmartPointer<BaseData>> result;

  InputStream stream(this);

  TiXmlDocument doc;
  stream >> doc;
  if (!doc.Error())
  {
    TiXmlHandle docHandle(&doc);

    for (TiXmlElement *geomDataElement = docHandle.FirstChildElement("GeometryData").ToElement();
         geomDataElement != nullptr;
         geomDataElement = geomDataElement->NextSiblingElement())
    {
      for (TiXmlElement *currentElement = geomDataElement->FirstChildElement(); currentElement != nullptr;
           currentElement = currentElement->NextSiblingElement())
      {
        // different geometries could have been serialized from a GeometryData
        // object:
        std::string tagName = currentElement->Value();
        if (tagName == "Geometry3D")
        {
          Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement);
          if (restoredGeometry.IsNotNull())
          {
            GeometryData::Pointer newGeometryData = GeometryData::New();
            newGeometryData->SetGeometry(restoredGeometry);
            result.push_back(newGeometryData.GetPointer());
          }
          else
          {
            MITK_ERROR << "Invalid <Geometry3D> tag encountered. Skipping.";
          }
        }
        else if (tagName == "ProportionalTimeGeometry")
        {
          ProportionalTimeGeometry::Pointer restoredTimeGeometry =
            ProportionalTimeGeometryToXML::FromXML(currentElement);
          if (restoredTimeGeometry.IsNotNull())
          {
            GeometryData::Pointer newGeometryData = GeometryData::New();
            newGeometryData->SetTimeGeometry(restoredTimeGeometry);
            result.push_back(newGeometryData.GetPointer());
          }
          else
          {
            MITK_ERROR << "Invalid <ProportionalTimeGeometry> tag encountered. Skipping.";
          }
        }
      } // for child of <GeometryData>
    }   // for <GeometryData>
  }
  else
  {
    mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc();
  }

  if (result.empty())
  {
    mitkThrow() << "Did not read a single GeometryData object from input.";
  }

  return result;
}
Example #4
0
std::vector<itk::SmartPointer<mitk::BaseData>> mitk::PointSetReaderService::Read()
{
    // Switch the current locale to "C"
    LocaleSwitch localeSwitch("C");

    std::vector<itk::SmartPointer<mitk::BaseData>> result;

    InputStream stream(this);

    TiXmlDocument doc;
    stream >> doc;
    if (!doc.Error())
    {
        TiXmlHandle docHandle(&doc);
        // unsigned int pointSetCounter(0);
        for (TiXmlElement *currentPointSetElement =
                    docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement();
                currentPointSetElement != NULL;
                currentPointSetElement = currentPointSetElement->NextSiblingElement())
        {
            mitk::PointSet::Pointer newPointSet = mitk::PointSet::New();

            // time geometry assembled for addition after all points
            // else the SetPoint method would already transform the points that we provide it
            mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New();

            if (currentPointSetElement->FirstChildElement("time_series") != NULL)
            {
                for (TiXmlElement *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement();
                        currentTimeSeries != NULL;
                        currentTimeSeries = currentTimeSeries->NextSiblingElement())
                {
                    unsigned int currentTimeStep(0);
                    TiXmlElement *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id");

                    currentTimeStep = atoi(currentTimeSeriesID->GetText());

                    timeGeometry->Expand(currentTimeStep + 1); // expand (default to identity) in any case
                    TiXmlElement *geometryElem = currentTimeSeries->FirstChildElement("Geometry3D");
                    if (geometryElem)
                    {
                        Geometry3D::Pointer geometry = Geometry3DToXML::FromXML(geometryElem);
                        if (geometry.IsNotNull())
                        {
                            timeGeometry->SetTimeStepGeometry(geometry, currentTimeStep);
                        }
                        else
                        {
                            MITK_ERROR << "Could not deserialize Geometry3D element.";
                        }
                    }
                    else
                    {
                        MITK_WARN << "Fallback to legacy behavior: defining PointSet geometry as identity";
                    }

                    newPointSet = this->ReadPoints(newPointSet, currentTimeSeries, currentTimeStep);
                }
            }
            else
            {
                newPointSet = this->ReadPoints(newPointSet, currentPointSetElement, 0);
            }

            newPointSet->SetTimeGeometry(timeGeometry);

            result.push_back(newPointSet.GetPointer());
        }
    }
    else
    {
        mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc();
    }

    return result;
}