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; }
mitk::BaseGeometry::Pointer mitk::PointSetReaderService::ReadGeometry(TiXmlElement *parentElement) { TiXmlElement *geometryElem = parentElement->FirstChildElement("geometry3d"); if (!geometryElem) return nullptr; // data to generate AffineTransform3D::MatrixType matrix; AffineTransform3D::OffsetType offset; bool isImageGeometry(false); unsigned int frameOfReferenceID(0); BaseGeometry::BoundsArrayType bounds; bool somethingMissing(false); // find data in xml structure TiXmlElement *imageGeometryElem = geometryElem->FirstChildElement("image_geometry"); if (imageGeometryElem) { std::string igs = imageGeometryElem->GetText(); isImageGeometry = igs == "true" || igs == "TRUE" || igs == "1"; } else somethingMissing = true; TiXmlElement *frameOfReferenceElem = geometryElem->FirstChildElement("frame_of_reference_id"); if (frameOfReferenceElem) { frameOfReferenceID = atoi(frameOfReferenceElem->GetText()); } else somethingMissing = true; TiXmlElement *indexToWorldElem = geometryElem->FirstChildElement("index_to_world"); if (indexToWorldElem) { TiXmlElement *matrixElem = indexToWorldElem->FirstChildElement("matrix3x3"); TiXmlElement *offsetElem = indexToWorldElem->FirstChildElement("offset"); if (indexToWorldElem && offsetElem) { TiXmlElement *col0 = matrixElem->FirstChildElement("column_0"); TiXmlElement *col1 = matrixElem->FirstChildElement("column_1"); TiXmlElement *col2 = matrixElem->FirstChildElement("column_2"); if (col0 && col1 && col2) { somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("x", &matrix[0][0]); somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("y", &matrix[1][0]); somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("z", &matrix[2][0]); somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("x", &matrix[0][1]); somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("y", &matrix[1][1]); somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("z", &matrix[2][1]); somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("x", &matrix[0][2]); somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("y", &matrix[1][2]); somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("z", &matrix[2][2]); } else somethingMissing = true; somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("x", &offset[0]); somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("y", &offset[1]); somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("z", &offset[2]); } else somethingMissing = true; TiXmlElement *boundsElem = geometryElem->FirstChildElement("bounds"); if (boundsElem) { TiXmlElement *minBoundsElem = boundsElem->FirstChildElement("min"); TiXmlElement *maxBoundsElem = boundsElem->FirstChildElement("max"); if (minBoundsElem && maxBoundsElem) { somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("x", &bounds[0]); somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("y", &bounds[2]); somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("z", &bounds[4]); somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("x", &bounds[1]); somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("y", &bounds[3]); somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("z", &bounds[5]); } else somethingMissing = true; } else somethingMissing = true; } else somethingMissing = true; if (somethingMissing) { MITK_ERROR << "XML structure of geometry inside a PointSet file broken. Refusing to build Geometry3D"; return nullptr; } else { Geometry3D::Pointer g = Geometry3D::New(); g->SetImageGeometry(isImageGeometry); g->SetFrameOfReferenceID(frameOfReferenceID); g->SetBounds(bounds); AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetMatrix(matrix); transform->SetOffset(offset); g->SetIndexToWorldTransform(transform); return g.GetPointer(); } }