/*========================================================================= Program: Visualization Toolkit Module: vtkXdmfReaderInternal.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkXdmfReaderInternal * */ #ifndef vtkXdmfReaderInternal_h #define vtkXdmfReaderInternal_h // NAMING CONVENTION ********************************************************* // * all member variables of the type XdmfXml* begin with XML eg. XMLNode // * all non-member variables of the type XdmfXml* begin with xml eg. xmlNode // * all member variables of the type XdmfElement (and subclasses) begin with // XMF eg. XMFGrid // * all non-member variables of the type XdmfElement (and subclasses) begin // with xmf eg. xmfGrid // *************************************************************************** #include "vtkMutableDirectedGraph.h" #include "vtkSILBuilder.h" #include "vtk_xdmf2.h" #include VTKXDMF2_HEADER(XdmfArray.h) #include VTKXDMF2_HEADER(XdmfAttribute.h) #include VTKXDMF2_HEADER(XdmfDOM.h) //? #include VTKXDMF2_HEADER(XdmfDataDesc.h) //? #include VTKXDMF2_HEADER(XdmfDataItem.h) #include VTKXDMF2_HEADER(XdmfGrid.h) //? #include VTKXDMF2_HEADER(XdmfTopology.h) //? #include VTKXDMF2_HEADER(XdmfGeometry.h) //? #include VTKXDMF2_HEADER(XdmfTime.h) //? #include VTKXDMF2_HEADER(XdmfSet.h) #include #include #include #include #include #include #include #include #include class vtkXdmfDomain; class VTKIOXDMF2_EXPORT vtkXdmfDocument { public: //--------------------------------------------------------------------------- ///@{ /** * Parse an xmf file (or string). Both these methods use caching hence calling * these methods repeatedly with the same argument will NOT result in * re-parsing of the xmf. */ bool Parse(const char* xmffilename); bool ParseString(const char* xmfdata, size_t length); ///@} //--------------------------------------------------------------------------- /** * Returns the names for available domains. */ const std::vector& GetDomains() { return this->Domains; } //--------------------------------------------------------------------------- ///@{ /** * Set the active domain. This will result in processing of the domain xmf if * the selected domain is different from the active one. */ bool SetActiveDomain(const char* domainname); bool SetActiveDomain(int index); ///@} //--------------------------------------------------------------------------- /** * Returns the active domain. */ vtkXdmfDomain* GetActiveDomain() { return this->ActiveDomain; } //--------------------------------------------------------------------------- ///@{ /** * Constructor/Destructor */ vtkXdmfDocument(); ~vtkXdmfDocument(); ///@} private: // Populates the list of domains. void UpdateDomains(); private: int ActiveDomainIndex; xdmf2::XdmfDOM XMLDOM; vtkXdmfDomain* ActiveDomain; std::vector Domains; char* LastReadContents; size_t LastReadContentsLength; std::string LastReadFilename; }; // I don't use vtkDataArraySelection since it's very slow when it comes to large // number of arrays. class vtkXdmfArraySelection : public std::map { public: void Merge(const vtkXdmfArraySelection& other) { vtkXdmfArraySelection::const_iterator iter = other.begin(); for (; iter != other.end(); ++iter) { (*this)[iter->first] = iter->second; } } void AddArray(const char* name, bool status = true) { (*this)[name] = status; } bool ArrayIsEnabled(const char* name) { vtkXdmfArraySelection::iterator iter = this->find(name); if (iter != this->end()) { return iter->second; } // don't know anything about this array, enable it by default. return true; } bool HasArray(const char* name) { vtkXdmfArraySelection::iterator iter = this->find(name); return (iter != this->end()); } int GetArraySetting(const char* name) { return this->ArrayIsEnabled(name) ? 1 : 0; } void SetArrayStatus(const char* name, bool status) { this->AddArray(name, status); } const char* GetArrayName(int index) { int cc = 0; for (vtkXdmfArraySelection::iterator iter = this->begin(); iter != this->end(); ++iter) { if (cc == index) { return iter->first.c_str(); } cc++; } return nullptr; } int GetNumberOfArrays() { return static_cast(this->size()); } }; //*************************************************************************** class VTKIOXDMF2_EXPORT vtkXdmfDomain { private: XdmfInt64 NumberOfGrids; xdmf2::XdmfGrid* XMFGrids; XdmfXmlNode XMLDomain; xdmf2::XdmfDOM* XMLDOM; unsigned int GridsOverflowCounter; // these are node indices used when building the SIL. vtkIdType SILBlocksRoot; std::map GridCenteredAttrbuteRoots; std::map> GridCenteredAttrbuteValues; vtkSILBuilder* SILBuilder; vtkMutableDirectedGraph* SIL; vtkXdmfArraySelection* PointArrays; vtkXdmfArraySelection* CellArrays; vtkXdmfArraySelection* Grids; vtkXdmfArraySelection* Sets; std::map TimeSteps; //< Only discrete timesteps are currently // supported. std::map TimeStepsRev; public: //--------------------------------------------------------------------------- // does not take ownership of the DOM, however the xmlDom must exist as long // as the instance is in use. vtkXdmfDomain(xdmf2::XdmfDOM* xmlDom, int domain_index); //--------------------------------------------------------------------------- /** * After instantiating, check that the domain is valid. If this returns false, * it means that the specified domain could not be located. */ bool IsValid() { return (this->XMLDomain != 0); } //--------------------------------------------------------------------------- vtkGraph* GetSIL() { return this->SIL; } //--------------------------------------------------------------------------- /** * Returns the number of top-level grids present in this domain. */ XdmfInt64 GetNumberOfGrids() { return this->NumberOfGrids; } //--------------------------------------------------------------------------- /** * Provides access to a top-level grid from this domain. */ xdmf2::XdmfGrid* GetGrid(XdmfInt64 cc); //--------------------------------------------------------------------------- /** * Returns the VTK data type need for this domain. If the domain has only 1 * grid, then a vtkDataSet-type is returned, otherwise a vtkMultiBlockDataSet * is required. * Returns -1 on error. */ int GetVTKDataType(); //--------------------------------------------------------------------------- /** * Returns the timesteps. */ const std::map& GetTimeSteps() { return this->TimeSteps; } const std::map& GetTimeStepsRev() { return this->TimeStepsRev; } //--------------------------------------------------------------------------- /** * Given a time value, returns the index. */ int GetIndexForTime(double time); //--------------------------------------------------------------------------- ///@{ /** * Returns the time value at the given index. */ XdmfFloat64 GetTimeForIndex(int index) { std::map::iterator iter = this->TimeStepsRev.find(index); return (iter != this->TimeStepsRev.end()) ? iter->second : 0.0; } ///@} //--------------------------------------------------------------------------- /** * If xmfGrid is a temporal collection, returns the child-grid matching the * requested time. */ xdmf2::XdmfGrid* GetGrid(xdmf2::XdmfGrid* xmfGrid, double time); //--------------------------------------------------------------------------- /** * Returns true if the grids is a structured dataset. */ bool IsStructured(xdmf2::XdmfGrid*); //--------------------------------------------------------------------------- /** * Returns the whole extents for the dataset if the grid if IsStructured() * returns true for the given grid. Returns true if the extents are valid. * NOTE: returned extents are always (0, dimx-1, 0, dimy-1, 0, dimz-1). */ bool GetWholeExtent(xdmf2::XdmfGrid*, int extents[6]); //--------------------------------------------------------------------------- /** * Returns the spacing and origin for the grid if the grid topology == * XDMF_2DCORECTMESH or XDMF_3DCORECTMESH i.e. image data. Returns true if * the extents are valid. */ bool GetOriginAndSpacing(xdmf2::XdmfGrid*, double origin[3], double spacing[3]); //--------------------------------------------------------------------------- ~vtkXdmfDomain(); // Returns VTK data type based on grid type and topology. // Returns -1 on error. int GetVTKDataType(xdmf2::XdmfGrid* xmfGrid); // Returns the dimensionality (or rank) of the topology for the given grid. // Returns -1 is the xmfGrid is not a uniform i.e. is a collection or a tree. static int GetDataDimensionality(xdmf2::XdmfGrid* xmfGrid); vtkXdmfArraySelection* GetPointArraySelection() { return this->PointArrays; } vtkXdmfArraySelection* GetCellArraySelection() { return this->CellArrays; } vtkXdmfArraySelection* GetGridSelection() { return this->Grids; } vtkXdmfArraySelection* GetSetsSelection() { return this->Sets; } private: /** * There are a few meta-information that we need to collect from the domain * * number of data-arrays so that the user can choose which to load. * * grid-structure so that the user can choose the hierarchy * * time information so that reader can report the number of timesteps * available. * This does another book-keeping task of ensuring that all grids have valid * names. If a grid is not named, then we make up a name. * TODO: We can use GRID centered attributes to create hierarchies in the SIL. */ void CollectMetaData(); // Used by CollectMetaData(). void CollectMetaData(xdmf2::XdmfGrid* xmfGrid, vtkIdType silParent); // Used by CollectMetaData(). void CollectNonLeafMetaData(xdmf2::XdmfGrid* xmfGrid, vtkIdType silParent); // Used by CollectMetaData(). void CollectLeafMetaData(xdmf2::XdmfGrid* xmfGrid, vtkIdType silParent); ///@{ /** * Use this to add an association with the grid attribute with the node for * the grid in the SIL if applicable. Returns true if the attribute was added. */ bool UpdateGridAttributeInSIL(xdmf2::XdmfAttribute* xmfAttribute, vtkIdType gridSILId); ///@} }; #endif // VTK-HeaderTest-Exclude: vtkXdmfReaderInternal.h