/*========================================================================= Program: Visualization Toolkit Module: vtkXMLHyperOctreeWriter.cxx 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. =========================================================================*/ //TODO: // Add support for timesteps // Add streaming support. #include "vtkXMLHyperOctreeWriter.h" #include "vtkObjectFactory.h" #include "vtkInformation.h" #include "vtkCellData.h" #include "vtkPointData.h" #include "vtkHyperOctree.h" #include "vtkHyperOctreeCursor.h" #include "vtkIntArray.h" #include "vtkErrorCode.h" #define vtkXMLOffsetsManager_DoNotInclude #include "vtkXMLOffsetsManager.h" #undef vtkXMLOffsetsManager_DoNotInclude vtkStandardNewMacro(vtkXMLHyperOctreeWriter); //---------------------------------------------------------------------------- vtkXMLHyperOctreeWriter::vtkXMLHyperOctreeWriter() { VTK_LEGACY_BODY(vtkXMLHyperOctreeWriter, "VTK 8.1"); this->TopologyArray = nullptr; this->TopologyOM = new OffsetsManagerGroup; this->PointDataOM = new OffsetsManagerGroup; this->CellDataOM = new OffsetsManagerGroup; this->TopologyOM->Allocate(1, 1); } //---------------------------------------------------------------------------- vtkXMLHyperOctreeWriter::~vtkXMLHyperOctreeWriter() { if (this->TopologyArray) { this->TopologyArray->Delete(); } delete this->TopologyOM; delete this->PointDataOM; delete this->CellDataOM; } //---------------------------------------------------------------------------- void vtkXMLHyperOctreeWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); } //---------------------------------------------------------------------------- vtkHyperOctree* vtkXMLHyperOctreeWriter::GetInput() { return static_cast(this->Superclass::GetInput()); } //---------------------------------------------------------------------------- const char* vtkXMLHyperOctreeWriter::GetDefaultFileExtension() { return "vto"; } //---------------------------------------------------------------------------- const char* vtkXMLHyperOctreeWriter::GetDataSetName() { return "HyperOctree"; } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::FillInputPortInformation( int, vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkHyperOctree"); return 1; } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::WriteData() { //write XML header and VTK file header and file attributes if (!this->StartFile()) { return 0; } vtkIndent indent = vtkIndent().GetNextIndent(); if (!this->StartPrimElement(indent)) { return 0; } if (!this->WriteTopology(indent.GetNextIndent())) { return 0; } if (!this->WriteAttributeData(indent.GetNextIndent())) { return 0; } this->WriteFieldData(indent.GetNextIndent()); if (!this->FinishPrimElement(indent)) { return 0; } if (this->GetDataMode() == vtkXMLWriter::Appended) { float progressRange[2] = { 0.f, 0.f }; this->GetProgressRange(progressRange); //Part spent serializing and writing assumed to be roughly equal. float fractions[5] = { 0.f, 0.25f, 0.5f, 0.75f, 1.f }; this->SetProgressRange(progressRange, 0, fractions); this->StartAppendedData(); //write out the data arrays in the appended data block while going back //and filling in empty offset space in previously written entries this->WriteArrayAppendedData (this->TopologyArray, this->TopologyOM->GetElement(0).GetPosition(0), this->TopologyOM->GetElement(0).GetOffsetValue(0)); double *range = this->TopologyArray->GetRange(-1); this->ForwardAppendedDataDouble (this->TopologyOM->GetElement(0).GetRangeMinPosition(0), range[0],"RangeMin" ); this->ForwardAppendedDataDouble (this->TopologyOM->GetElement(0).GetRangeMaxPosition(0), range[1],"RangeMax" ); this->SetProgressRange(progressRange, 1, fractions); this->WritePointDataAppendedData(this->GetInput()->GetPointData(), 0, this->PointDataOM); this->SetProgressRange(progressRange, 2, fractions); this->WriteCellDataAppendedData(this->GetInput()->GetCellData(), 0, this->CellDataOM); this->SetProgressRange(progressRange, 3, fractions); this->WriteFieldDataAppendedData(this->GetInput()->GetFieldData(), 0, this->FieldDataOM); this->EndAppendedData(); } this->TopologyArray->Delete(); this->TopologyArray = nullptr; if (!this->EndFile()) { return 0; } return 1; } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::StartPrimElement(vtkIndent indent) { ostream& os = *(this->Stream); return (!this->WritePrimaryElement(os, indent)) ? 0 : 1; } //---------------------------------------------------------------------------- void vtkXMLHyperOctreeWriter::WritePrimaryElementAttributes(ostream &os, vtkIndent indent) { this->Superclass::WritePrimaryElementAttributes(os, indent); vtkHyperOctree* input = this->GetInput(); this->WriteScalarAttribute("Dimension", input->GetDimension()); this->WriteVectorAttribute("Size", 3, input->GetSize()); this->WriteVectorAttribute("Origin", 3, input->GetOrigin()); } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::WriteTopology(vtkIndent indent) { if (this->TopologyArray) { this->TopologyArray->Delete(); } this->TopologyArray = vtkIntArray::New(); this->TopologyArray->SetNumberOfComponents(1); vtkHyperOctree* input = this->GetInput(); vtkHyperOctreeCursor *cursor=input->NewCellCursor(); cursor->ToRoot(); //record structure into an array float progressRange[2] = { 0.f, 0.f }; this->GetProgressRange(progressRange); //Part spent serializing and writing assumed to be roughly equal. float fractions[3] = { 0.f, 0.5f, 1.f }; this->SetProgressRange(progressRange, 0, fractions); this->SerializeTopology(cursor, cursor->GetNumberOfChildren()); //write out the array this->SetProgressRange(progressRange, 1, fractions); ostream& os = *(this->Stream); os << indent << "<" << "Topology" << ">\n"; os.flush(); if (os.fail()) { this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); return 0; } //...,1) to save length of array for easy recovery by reader if (this->GetDataMode() == vtkXMLWriter::Appended) { this->WriteArrayAppended(this->TopologyArray, indent.GetNextIndent(), this->TopologyOM->GetElement(0), "Topology", 1, 0); } else { this->WriteArrayInline(this->TopologyArray, indent.GetNextIndent(), "Topology", 1); } os << indent << "\n"; os.flush(); if (os.fail()) { this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); return 0; } cursor->Delete(); return 1; } //---------------------------------------------------------------------------- void vtkXMLHyperOctreeWriter::SerializeTopology( vtkHyperOctreeCursor *cursor, int nchildren) { if (cursor->CurrentIsLeaf()) { //this node is a leaf, we must stop now this->TopologyArray->InsertNextValue(1); } /* else if (cursor->CurrentIsTerminalNode()) { //this node has 'nchildren' children, //all of which are leaves, so we can stop now too this->TopologyArray->InsertNextValue(2); } */ else { //this node has 'nchildren' children, //some of which are internal nodes, so we must continue down this->TopologyArray->InsertNextValue(0); int i = 0; while (i < nchildren) { cursor->ToChild(i); this->SerializeTopology(cursor, nchildren); cursor->ToParent(); ++i; } } } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::WriteAttributeData(vtkIndent indent) { // Write the point data and cell data arrays. vtkDataSet* input = this->GetInputAsDataSet(); // Split progress between point data and cell data arrays. float progressRange[2] = { 0.f, 0.f }; this->GetProgressRange(progressRange); int pdArrays = input->GetPointData()->GetNumberOfArrays(); int cdArrays = input->GetCellData()->GetNumberOfArrays(); int total = (pdArrays+cdArrays)? (pdArrays+cdArrays):1; float fractions[3] = { 0.f, static_cast(pdArrays) / total, 1.f }; // Set the range of progress for the point data arrays. this->SetProgressRange(progressRange, 0, fractions); if (this->GetDataMode() == vtkXMLWriter::Appended) { this->WritePointDataAppended( input->GetPointData(), indent, this->PointDataOM); } else { this->WritePointDataInline(input->GetPointData(), indent); } if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) { return 0; } // Set the range of progress for the cell data arrays. this->SetProgressRange(progressRange, 1, fractions); if (this->GetDataMode() == vtkXMLWriter::Appended) { this->WriteCellDataAppended( input->GetCellData(), indent, this->CellDataOM); } else { this->WriteCellDataInline(input->GetCellData(), indent); } return 1; } //---------------------------------------------------------------------------- int vtkXMLHyperOctreeWriter::FinishPrimElement(vtkIndent indent) { ostream& os = *(this->Stream); // End the primary element. os << indent << "GetDataSetName() << ">\n"; os.flush(); if (os.fail()) { this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError); return 0; } return 1; }