vtkXMLHyperOctreeReader.cxx 8.69 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLHyperOctreeReader.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 "vtkXMLHyperOctreeReader.h"

#include "vtkDataArray.h"
#include "vtkObjectFactory.h"
#include "vtkHyperOctree.h"
#include "vtkHyperOctreeCursor.h"
#include "vtkXMLDataElement.h"
#include "vtkXMLDataParser.h"
#include "vtkInformation.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkIntArray.h"
#include "vtkFieldData.h"

vtkStandardNewMacro(vtkXMLHyperOctreeReader);

//----------------------------------------------------------------------------
vtkXMLHyperOctreeReader::vtkXMLHyperOctreeReader()
{
}

//----------------------------------------------------------------------------
vtkXMLHyperOctreeReader::~vtkXMLHyperOctreeReader()
{
}

//----------------------------------------------------------------------------
void vtkXMLHyperOctreeReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
vtkHyperOctree* vtkXMLHyperOctreeReader::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkHyperOctree* vtkXMLHyperOctreeReader::GetOutput(int idx)
{
60
  return vtkHyperOctree::SafeDownCast(this->GetOutputDataObject(idx));
61 62 63 64 65 66 67 68 69 70 71
}

//----------------------------------------------------------------------------
const char* vtkXMLHyperOctreeReader::GetDataSetName()
{
  return "HyperOctree";
}

//----------------------------------------------------------------------------
void vtkXMLHyperOctreeReader::SetupEmptyOutput()
{
72
  this->GetCurrentOutput()->Initialize();
73 74 75 76 77 78 79 80 81 82
}

//----------------------------------------------------------------------------
int vtkXMLHyperOctreeReader::FillOutputPortInformation(int, vtkInformation *info)
{
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkHyperOctree");
  return 1;
}

//----------------------------------------------------------------------------
83
vtkIdType vtkXMLHyperOctreeReader::GetNumberOfPoints()
84
{
Berk Geveci's avatar
Berk Geveci committed
85 86 87 88 89 90 91
  vtkIdType numPts = 0;
  vtkDataSet* output = vtkDataSet::SafeDownCast(this->GetCurrentOutput());
  if (output)
    {
    numPts = output->GetNumberOfPoints();
    }
  return numPts;
92 93 94 95 96
}

//----------------------------------------------------------------------------
vtkIdType vtkXMLHyperOctreeReader::GetNumberOfCells()
{
Berk Geveci's avatar
Berk Geveci committed
97 98 99 100 101 102 103
  vtkIdType numCells = 0;
  vtkDataSet* output = vtkDataSet::SafeDownCast(this->GetCurrentOutput());
  if (output)
    {
    numCells = output->GetNumberOfCells();
    }
  return numCells;
104 105 106 107
}

//----------------------------------------------------------------------------
int vtkXMLHyperOctreeReader::ReadArrayForPoints(vtkXMLDataElement* da,
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
108
                                                vtkAbstractArray* outArray)
109 110 111 112
{
  vtkIdType components = outArray->GetNumberOfComponents();
  vtkIdType numberOfTuples = this->GetNumberOfPoints();
  outArray->SetNumberOfTuples(numberOfTuples);
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
113
  return this->ReadArrayValues(da, 0, outArray, 0, numberOfTuples*components);
114 115 116 117
}

//----------------------------------------------------------------------------
int vtkXMLHyperOctreeReader::ReadArrayForCells(vtkXMLDataElement* da,
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
118
                                               vtkAbstractArray* outArray)
119 120 121 122
{
  vtkIdType components = outArray->GetNumberOfComponents();
  vtkIdType numberOfTuples = this->GetNumberOfCells();
  outArray->SetNumberOfTuples(numberOfTuples);
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
123
  return this->ReadArrayValues(da, 0, outArray, 0, numberOfTuples*components);
124

125 126 127 128 129
}

//----------------------------------------------------------------------------
void vtkXMLHyperOctreeReader::ReadXMLData()
{
130

131 132 133 134 135 136
  //1) vtkXMLReader grandparent class checks if this timestep needs to SetupOutputData, and if so initializes the output.
  //2) vtkXMLDataReader parent class reads fielddata
  this->Superclass::ReadXMLData();

  //3) For Other XML readers, vtkXMLUnstructuredDataReader or vtkXMLStructuredDataReader parent classes use pipeline info to determines what pieces to read and then ReadPieceData is called to read only part of the data. Since HyperOctree is not streamed yet, I'll just read the whole file here instead.

137
  vtkXMLDataElement *ePrimary =
138 139
    this->XMLParser->GetRootElement()->GetNestedElement(0);

140 141 142
  int dimension;
  double size[3];
  double origin[3];
143

144
  if (!ePrimary->GetScalarAttribute("Dimension", dimension))
145
    {
146
    dimension = 3;
147 148
    }

149
  if (ePrimary->GetVectorAttribute("Size", 3, size) != 3)
150
    {
151 152 153
    size[0] = 1;
    size[1] = 1;
    size[2] = 1;
154 155
    }

156
  if (ePrimary->GetVectorAttribute("Origin", 3, origin) != 3)
157
    {
158 159 160
    origin[0] = 0;
    origin[1] = 0;
    origin[2] = 0;
161
    }
162

163 164
  vtkHyperOctree *output = vtkHyperOctree::SafeDownCast(
      this->GetCurrentOutput());
165 166 167
  output->SetDimension(dimension);
  output->SetSize(size);
  output->SetOrigin(origin);
168

169 170 171 172 173
  // Find the topology element, which defines the structure of the HyperOctree
  // Rebuild the HyperOctree from that.
  // This needs to happen before ReadPieceData so that numPoints and numCells
  // will be defined.
  int numNested = ePrimary->GetNumberOfNestedElements();
174
  for (int i = 0; i < numNested; ++i)
175 176
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
177
    if (strcmp(eNested->GetName(), "Topology") == 0)
178
      {
179 180 181 182 183 184 185
      this->ReadTopology(eNested);
      break;
      }
    }

  //Read the pointdata and celldata attribute data.
  //We only have one piece so this will suffice.
186
  this->ReadPieceData();
187 188 189 190 191 192
}

//----------------------------------------------------------------------------
void vtkXMLHyperOctreeReader::ReadTopology(vtkXMLDataElement *elem)
{

193
  float progressRange[2] = { 0.f, 0.f };
194 195
  this->GetProgressRange(progressRange);
  //Part spent reading and reconstructing assumed to be roughly equal.
196
  float fractions[3] = { 0.f, 0.5f, 1.f };
197 198 199 200
  this->SetProgressRange(progressRange, 0, fractions);

  //Find the topology array and read it into a vtkIntArray
  int numNested = elem->GetNumberOfNestedElements();
201
  if (numNested != 1)
202 203 204
    {
    return;
    }
205 206 207

  vtkXMLDataElement* tElem = elem->GetNestedElement(0);

Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
208 209 210
  // Since topology is a vtkIntArray.
  vtkAbstractArray* a = this->CreateArray(tElem);
  vtkDataArray *tda = vtkDataArray::SafeDownCast(a);
211
  if (!tda)
212
    {
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
213 214 215 216
    if (a)
      {
      a->Delete();
      }
217 218
    return;
    }
219

220
  int numTuples;
221
  if (!tElem->GetScalarAttribute("NumberOfTuples", numTuples))
222 223 224 225
    {
    tda->Delete();
    return;
    }
226

227
  tda->SetNumberOfTuples(numTuples);
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
228
  if (!this->ReadArrayValues(tElem, 0, tda, 0, numTuples* tda->GetNumberOfComponents())
229 230

   /* this->ReadData(tElem, tda->GetVoidPointer(0), tda->GetDataType(),
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
231
                      0, numTuples*tda->GetNumberOfComponents())*/)
232 233 234 235 236
    {
    tda->Delete();
    return;
    }

237
  vtkIntArray *ta = vtkIntArray::SafeDownCast(tda);
238
  if (!ta)
239
    {
240 241 242 243 244 245 246
    tda->Delete();
    return;
    }

  this->SetProgressRange(progressRange, 1, fractions);

  //Restore the topology from the vtkIntArray. Do it recursively, cell by cell.
247
  vtkHyperOctreeCursor *cursor=vtkHyperOctree::SafeDownCast(
248
    this->GetCurrentOutput())->NewCellCursor();
249 250
  cursor->ToRoot();
  //Where in the array we need to read from next.
251
  this->ArrayIndex = 0;
252 253 254 255
  if (!this->BuildNextCell(ta, cursor, cursor->GetNumberOfChildren()))
    {
    vtkErrorMacro( << "Problem reading topology. ");
    ta->Delete();
256 257
    return ;
    }
258 259 260 261 262 263 264 265

  //Cleanup
  cursor->Delete();
  ta->Delete();
}

//----------------------------------------------------------------------------
int vtkXMLHyperOctreeReader::BuildNextCell(
266
  vtkIntArray *ta, vtkHyperOctreeCursor *cursor, int nchildren)
267 268
{

269
  int nodeType = ta->GetValue(this->ArrayIndex);
270 271 272 273 274 275 276 277 278 279

  if (nodeType == 1)
    {
    //leaf, stop now
    }
/*
  else if (nodeType == 2)
    {
    //terminal node
    //subdivide but stop there
280
    vtkHyperOctree::SafeDownCast(this->GetCurrentOutput())->SubdivideLeaf(cursor);
281 282 283 284 285 286
    }
*/
  else
    {
    //internal node
    //subdivide
287
    vtkHyperOctree::SafeDownCast(this->GetCurrentOutput())->SubdivideLeaf(cursor);
288
    //then keep going down
289 290
    int i = 0;
    while (i < nchildren)
291 292
      {
      cursor->ToChild(i);
293

294
      this->ArrayIndex++;
295 296 297 298 299
      if (!this->BuildNextCell(ta, cursor, nchildren))
        {
        //IO failure somewhere below
        return 0;
        }
300

301 302 303 304 305 306
      cursor->ToParent();
      ++i;
      }
    }
  return 1;
}