vtkXMLUnstructuredDataReader.cxx 34.7 KB
Newer Older
1 2 3 4 5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLUnstructuredDataReader.cxx

6
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 8 9
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

10 11
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 13 14 15 16 17 18 19 20 21 22
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLUnstructuredDataReader.h"
#include "vtkObjectFactory.h"
#include "vtkXMLDataElement.h"
#include "vtkPoints.h"
#include "vtkIdTypeArray.h"
#include "vtkUnsignedCharArray.h"
#include "vtkCellArray.h"
#include "vtkPointSet.h"
23 24
#include "vtkInformation.h"
#include "vtkStreamingDemandDrivenPipeline.h"
25

26
#include <cassert>
27

28 29 30

//----------------------------------------------------------------------------
vtkXMLUnstructuredDataReader::vtkXMLUnstructuredDataReader()
31
{
32 33 34 35
  this->PointElements = 0;
  this->NumberOfPoints = 0;
  this->TotalNumberOfPoints = 0;
  this->TotalNumberOfCells = 0;
36 37

  this->PointsTimeStep = -1;  //invalid state
Francois Bertel's avatar
Francois Bertel committed
38
  this->PointsOffset = static_cast<unsigned long>(-1);
39 40 41 42 43
}

//----------------------------------------------------------------------------
vtkXMLUnstructuredDataReader::~vtkXMLUnstructuredDataReader()
{
44 45 46 47
  if(this->NumberOfPieces)
    {
    this->DestroyPieces();
    }
48 49 50 51 52 53 54 55 56 57 58
}

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

//----------------------------------------------------------------------------
vtkPointSet* vtkXMLUnstructuredDataReader::GetOutputAsPointSet()
{
59
  return vtkPointSet::SafeDownCast( this->GetOutputDataObject(0) );
60 61 62 63 64 65 66 67
}

//----------------------------------------------------------------------------
vtkXMLDataElement*
vtkXMLUnstructuredDataReader
::FindDataArrayWithName(vtkXMLDataElement* eParent, const char* name)
{
  // Find a nested element that represents a data array with the given name.
68
  // and proper TimeStep
69 70 71 72 73 74 75 76 77
  int i;
  for(i=0;i < eParent->GetNumberOfNestedElements(); ++i)
    {
    vtkXMLDataElement* eNested = eParent->GetNestedElement(i);
    if(strcmp(eNested->GetName(), "DataArray") == 0)
      {
      const char* aName = eNested->GetAttribute("Name");
      if(aName && (strcmp(aName, name) == 0))
        {
78
        int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
79
          this->NumberOfTimeSteps, this->TimeSteps);
80
        assert( numTimeSteps <= this->NumberOfTimeSteps );
81
        // Check if CurrentTimeStep is in the array and particular field is also:
82
        int isCurrentTimeInArray =
83 84 85 86 87 88
          vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
        // If no time is specified or if time is specified and match then read
        if( !numTimeSteps || isCurrentTimeInArray )
          {
          return eNested;
          }
89 90 91 92 93 94 95
        }
      }
    }
  return 0;
}

//----------------------------------------------------------------------------
96 97 98 99 100 101 102 103 104 105 106 107
template <class TIn, class TOut>
void vtkXMLUnstructuredDataReaderCopyArray(TIn* in, TOut* out,
                                           vtkIdType length)
{
  for(vtkIdType i = 0; i < length; ++i)
    {
    out[i] = static_cast<TOut>(in[i]);
    }
}

//----------------------------------------------------------------------------
vtkIdTypeArray*
108
vtkXMLUnstructuredDataReader::ConvertToIdTypeArray(vtkDataArray* a)
109
{
110 111 112
  // If it is already a vtkIdTypeArray, just return it.
  vtkIdTypeArray* ida = vtkIdTypeArray::SafeDownCast(a);
  if(ida)
113
    {
114
    return ida;
115
    }
116

117 118 119 120 121 122 123 124
  // Need to convert the data.
  ida = vtkIdTypeArray::New();
  ida->SetNumberOfComponents(a->GetNumberOfComponents());
  ida->SetNumberOfTuples(a->GetNumberOfTuples());
  vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples();
  vtkIdType* idBuffer = ida->GetPointer(0);
  switch (a->GetDataType())
    {
125 126
    vtkTemplateMacro(
      vtkXMLUnstructuredDataReaderCopyArray(
127
                      static_cast<VTK_TT*>(a->GetVoidPointer(0)),
128
                      idBuffer, length));
129 130 131 132 133 134 135 136 137 138 139 140
    default:
      vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType()
                    << " to vtkIdTypeArray.");
      ida->Delete();
      ida = 0;
    }
  a->Delete();
  return ida;
}

//----------------------------------------------------------------------------
vtkUnsignedCharArray*
141
vtkXMLUnstructuredDataReader::ConvertToUnsignedCharArray(vtkDataArray* a)
142 143 144 145 146 147 148
{
  // If it is already a vtkUnsignedCharArray, just return it.
  vtkUnsignedCharArray* uca = vtkUnsignedCharArray::SafeDownCast(a);
  if(uca)
    {
    return uca;
    }
149

150 151 152 153 154 155 156 157
  // Need to convert the data.
  uca = vtkUnsignedCharArray::New();
  uca->SetNumberOfComponents(a->GetNumberOfComponents());
  uca->SetNumberOfTuples(a->GetNumberOfTuples());
  vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples();
  unsigned char* ucBuffer = uca->GetPointer(0);
  switch (a->GetDataType())
    {
158 159 160 161
    vtkTemplateMacro(
      vtkXMLUnstructuredDataReaderCopyArray(
        static_cast<VTK_TT*>(a->GetVoidPointer(0)),
        ucBuffer, length));
162 163 164 165 166 167 168 169
    default:
      vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType()
                    << " to vtkUnsignedCharArray.");
      uca->Delete();
      uca = 0;
    }
  a->Delete();
  return uca;
170 171
}

172 173 174
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupEmptyOutput()
{
175
  this->GetCurrentOutput()->Initialize();
176 177
}

178 179 180 181
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupOutputTotals()
{
  this->TotalNumberOfPoints = 0;
182
  for(int i=this->StartPiece; i < this->EndPiece; ++i)
183 184
    {
    this->TotalNumberOfPoints += this->NumberOfPoints[i];
185
    }
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
  this->StartPoint = 0;
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupNextPiece()
{
  this->StartPoint += this->NumberOfPoints[this->Piece];
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupUpdateExtent(int piece,
                                                     int numberOfPieces,
                                                     int ghostLevel)
{
  this->UpdatePiece = piece;
  this->UpdateNumberOfPieces = numberOfPieces;
  this->UpdateGhostLevel = ghostLevel;
203

204 205 206 207 208 209
  // If more pieces are requested than available, just return empty
  // pieces for the extra ones.
  if(this->UpdateNumberOfPieces > this->NumberOfPieces)
    {
    this->UpdateNumberOfPieces = this->NumberOfPieces;
    }
210

211 212 213 214 215 216 217 218 219 220 221 222 223
  // Find the range of pieces to read.
  if(this->UpdatePiece < this->UpdateNumberOfPieces)
    {
    this->StartPiece = ((this->UpdatePiece*this->NumberOfPieces) /
                        this->UpdateNumberOfPieces);
    this->EndPiece = (((this->UpdatePiece+1)*this->NumberOfPieces) /
                      this->UpdateNumberOfPieces);
    }
  else
    {
    this->StartPiece = 0;
    this->EndPiece = 0;
    }
224

225
  // Find the total size of the output.
226
  this->SetupOutputTotals();
227 228 229 230
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::ReadXMLData()
231
{
232 233 234 235
  // Get the update request.
  int piece;
  int numberOfPieces;
  int ghostLevel;
236 237 238 239 240 241 242
  vtkInformation* outInfo = this->GetCurrentOutputInformation();
  piece = outInfo->Get(
      vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
  numberOfPieces = outInfo->Get(
      vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
  ghostLevel = outInfo->Get(
      vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
243

244 245
  vtkDebugMacro("Updating piece " << piece << " of " << numberOfPieces
                << " with ghost level " << ghostLevel);
246

247 248
  // Setup the range of pieces that will be read.
  this->SetupUpdateExtent(piece, numberOfPieces, ghostLevel);
249

250 251 252 253 254
  // If there are no data to read, stop now.
  if(this->StartPiece == this->EndPiece)
    {
    return;
    }
255

256
  vtkDebugMacro("Reading piece range [" << this->StartPiece
257 258
                << ", " << this->EndPiece << ") from file.");

259
  // Let superclasses read data.  This also allocates output data.
260 261
  this->Superclass::ReadXMLData();

262 263 264 265
  // Split current progress range based on fraction contributed by
  // each piece.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
266

267 268 269
  // Calculate the cumulative fraction of data contributed by each
  // piece (for progress).
  float* fractions = new float[this->EndPiece-this->StartPiece+1];
270
  int i;
271
  fractions[0] = 0;
272 273
  for(i=this->StartPiece; i < this->EndPiece; ++i)
    {
274 275
    int index = i-this->StartPiece;
    fractions[index+1] = (fractions[index] +
276
                          this->GetNumberOfPointsInPiece(i) +
277 278
                          this->GetNumberOfCellsInPiece(i));
    }
279 280 281 282
  if(fractions[this->EndPiece-this->StartPiece] == 0)
    {
    fractions[this->EndPiece-this->StartPiece] = 1;
    }
283 284 285 286 287
  for(i=this->StartPiece; i < this->EndPiece; ++i)
    {
    int index = i-this->StartPiece;
    fractions[index+1] = fractions[index+1] / fractions[this->EndPiece-this->StartPiece];
    }
288

289
  // Read the data needed from each piece.
290 291
  for(i=this->StartPiece; (i < this->EndPiece && !this->AbortExecute &&
                           !this->DataError); ++i)
292 293 294
    {
    // Set the range of progress for this piece.
    this->SetProgressRange(progressRange, i-this->StartPiece, fractions);
295

296 297 298 299 300
    if(!this->Superclass::ReadPieceData(i))
      {
      // An error occurred while reading the piece.
      this->DataError = 1;
      }
301 302
    this->SetupNextPiece();
    }
303

304
  delete [] fractions;
305 306 307 308 309 310 311 312
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupPieces(int numPieces)
{
  this->Superclass::SetupPieces(numPieces);
  this->NumberOfPoints = new vtkIdType[numPieces];
  this->PointElements = new vtkXMLDataElement*[numPieces];
313
  for(int i=0;i < numPieces; ++i)
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
    {
    this->PointElements[i] = 0;
    this->NumberOfPoints[i] = 0;
    }
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::DestroyPieces()
{
  delete [] this->PointElements;
  delete [] this->NumberOfPoints;
  this->PointElements = 0;
  this->NumberOfPoints = 0;
  this->Superclass::DestroyPieces();
}

//----------------------------------------------------------------------------
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPoints()
{
  return this->TotalNumberOfPoints;
}

//----------------------------------------------------------------------------
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfCells()
{
  return this->TotalNumberOfCells;
}

342 343 344 345 346 347
//----------------------------------------------------------------------------
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPieces()
{
  return this->NumberOfPieces;
}

348 349 350 351 352 353
//----------------------------------------------------------------------------
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPointsInPiece(int piece)
{
  return this->NumberOfPoints[piece];
}

354
//----------------------------------------------------------------------------
355 356
// Note that any changes (add or removing information) made to this method
// should be replicated in CopyOutputInformation
357
void vtkXMLUnstructuredDataReader::SetupOutputInformation(vtkInformation *outInfo)
358
{
359
  this->Superclass::SetupOutputInformation(outInfo);
360

361 362
  if (this->NumberOfPieces > 1)
    {
Berk Geveci's avatar
Berk Geveci committed
363
    outInfo->Set(CAN_HANDLE_PIECE_REQUEST(), 1);
364
    }
365 366
}

367 368 369

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::CopyOutputInformation(vtkInformation *outInfo, int port)
370
{
371
  this->Superclass::CopyOutputInformation(outInfo, port);
372
}
373 374


375 376 377 378 379
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataReader::SetupOutputData()
{
  this->Superclass::SetupOutputData();

380 381
  // Create the points array.
  vtkPoints* points = vtkPoints::New();
382

383 384
  // Use the configuration of the first piece since all are the same.
  vtkXMLDataElement* ePoints = this->PointElements[0];
385
  if (ePoints)
386 387
    {
    // Non-zero volume.
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
388 389
    vtkAbstractArray* aa = this->CreateArray(ePoints->GetNestedElement(0));
    vtkDataArray* a = vtkDataArray::SafeDownCast(aa);
390
    if (a)
391
      {
392 393
      // Allocate the points array.
      a->SetNumberOfTuples( this->GetNumberOfPoints() );
394 395 396 397 398
      points->SetData(a);
      a->Delete();
      }
    else
      {
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
399 400 401 402
      if (aa)
        {
        aa->Delete();
        }
403
      this->DataError = 1;
404
      }
405
    }
406

407
  vtkPointSet::SafeDownCast(this->GetCurrentOutput())->SetPoints(points);
408 409 410 411 412 413
  points->Delete();
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece)
{
414 415 416 417
  if(!this->Superclass::ReadPiece(ePiece))
    {
    return 0;
    }
418

419 420 421 422 423 424 425 426
  if(!ePiece->GetScalarAttribute("NumberOfPoints",
                                 this->NumberOfPoints[this->Piece]))
    {
    vtkErrorMacro("Piece " << this->Piece
                  << " is missing its NumberOfPoints attribute.");
    this->NumberOfPoints[this->Piece] = 0;
    return 0;
    }
427

428 429 430 431 432 433
  // Find the Points element in the piece.
  int i;
  this->PointElements[this->Piece] = 0;
  for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i)
    {
    vtkXMLDataElement* eNested = ePiece->GetNestedElement(i);
434
    if(strcmp(eNested->GetName(), "Points") == 0)
435
      {
436 437 438 439 440 441
      // make sure the XML file is somehow valid:
      if( (this->NumberOfTimeSteps > 0 && eNested->GetNumberOfNestedElements() >= 1) ||
          (this->NumberOfTimeSteps == 0 && eNested->GetNumberOfNestedElements() == 1))
        {
        this->PointElements[this->Piece] = eNested;
        }
442 443
      }
    }
444

445 446 447
  // If there are some points, we require a Points element.
  if(!this->PointElements[this->Piece] &&
     (this->NumberOfPoints[this->Piece] > 0))
448
    {
449 450
    vtkErrorMacro("A piece is missing its Points element "
                  "or element does not have exactly 1 array.");
451
    return 0;
452 453
    }

454 455 456 457 458 459
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::ReadPieceData()
{
460 461 462 463 464
  // The amount of data read by the superclass's ReadPieceData comes
  // from point/cell data (we read point specifications here).
  vtkIdType superclassPieceSize =
    (this->NumberOfPointArrays*this->GetNumberOfPointsInPiece(this->Piece)+
     this->NumberOfCellArrays*this->GetNumberOfCellsInPiece(this->Piece));
465

466 467 468 469 470 471 472 473
  // Total amount of data in this piece comes from point/cell data
  // arrays and the point specifications themselves.
  vtkIdType totalPieceSize =
    superclassPieceSize + 1*this->GetNumberOfPointsInPiece(this->Piece);
  if(totalPieceSize == 0)
    {
    totalPieceSize = 1;
    }
474

475 476 477 478 479 480 481 482 483 484
  // Split the progress range based on the approximate fraction of
  // data that will be read by each step in this method.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[3] =
    {
      0,
      float(superclassPieceSize)/totalPieceSize,
      1
    };
485

486 487
  // Set the range of progress for the superclass.
  this->SetProgressRange(progressRange, 0, fractions);
488

489
  // Let the superclass read its data.
490 491 492
  if(!this->Superclass::ReadPieceData())
    {
    return 0;
493
    }
494

495
  vtkPointSet* output = vtkPointSet::SafeDownCast(this->GetCurrentOutput());
496

497 498
  // Set the range of progress for the Points.
  this->SetProgressRange(progressRange, 1, fractions);
499

500 501
  // Read the points array.
  vtkXMLDataElement* ePoints = this->PointElements[this->Piece];
502
  if(ePoints)
503
    {
504 505
    for(int i=0;(i < ePoints->GetNumberOfNestedElements() &&
             !this->AbortExecute);++i)
506
      {
507
      vtkXMLDataElement* eNested = ePoints->GetNestedElement(i);
508
      if( strcmp(eNested->GetName(), "DataArray") != 0  &&
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
509 510 511 512 513 514
        strcmp(eNested->GetName(),"Array") != 0 )
        {
        vtkErrorMacro("Invalid Array.");
        this->DataError = 1;
        return 0;
        }
515 516 517 518 519 520 521 522 523 524 525 526
      int needToRead = this->PointsNeedToReadTimeStep(eNested);
      if( needToRead )
        {
        // Read the array.
        if(!this->ReadArrayForPoints(eNested, output->GetPoints()->GetData()))
          {
          vtkErrorMacro("Cannot read points array from " << ePoints->GetName()
            << " in piece " << this->Piece
            << ".  The data array in the element may be too short.");
          return 0;
          }
        }
527 528
      }
    }
529

530 531 532 533 534 535 536 537 538 539 540 541 542
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::ReadCellArray(vtkIdType numberOfCells,
                                                vtkIdType totalNumberOfCells,
                                                vtkXMLDataElement* eCells,
                                                vtkCellArray* outCells)
{
  if(numberOfCells <= 0)
    {
    return 1;
    }
543
  else
544
    {
Ken Martin's avatar
Ken Martin committed
545 546 547 548
    if(!eCells)
      {
      return 0;
      }
549
    }
550

551 552 553 554 555 556
  // Split progress range into 1/5 for offsets array and 4/5 for
  // connectivity array.  This assumes an average of 4 points per
  // cell.  Unfortunately, we cannot know the length of the
  // connectivity array ahead of time to calculate the real fraction.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
557
  float fractions[3] = {0, 0.2f, 1};
558

559 560
  // Set range of progress for offsets array.
  this->SetProgressRange(progressRange, 0, fractions);
561

562
  // Read the cell offsets.
563 564
  vtkXMLDataElement* eOffsets = this->FindDataArrayWithName(eCells, "offsets");
  if(!eOffsets)
565 566
    {
    vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
567 568 569 570
                  << " in piece " << this->Piece
                  << " because the \"offsets\" array could not be found.");
    return 0;
    }
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
571 572
  vtkAbstractArray* ac1 = this->CreateArray(eOffsets);
  vtkDataArray* c1 = vtkDataArray::SafeDownCast(ac1);
573 574 575 576 577 578
  if(!c1 || (c1->GetNumberOfComponents() != 1))
    {
    vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"offsets\" array could not be created"
                  << " with one component.");
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
579 580 581 582
    if (ac1)
      {
      ac1->Delete();
      }
583 584 585
    return 0;
    }
  c1->SetNumberOfTuples(numberOfCells);
586
  if(!this->ReadArrayValues(eOffsets, 0, c1,
587
                            0, numberOfCells, CELL_DATA))
588 589
    {
    vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
590 591 592
                  << " in piece " << this->Piece
                  << " because the \"offsets\" array is not long enough.");
    return 0;
593
    }
594 595 596 597 598 599 600
  vtkIdTypeArray* cellOffsets = this->ConvertToIdTypeArray(c1);
  if(!cellOffsets)
    {
    vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"offsets\" array could not be"
                  << " converted to a vtkIdTypeArray.");
601 602
    return 0;
    }
603 604 605 606

  // Check the contents of the cell offsets array.
  vtkIdType* coffset = cellOffsets->GetPointer(0);
  vtkIdType lastOffset = 0;
Brad King's avatar
Brad King committed
607 608
  vtkIdType i;
  for(i=0; i < numberOfCells; ++i)
609
    {
610
    if(coffset[i] < lastOffset)
611 612 613 614 615 616 617 618 619 620 621 622
      {
      vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
                    << " in piece " << this->Piece
                    << " because the \"offsets\" array is"
                    << " not monotonically increasing or starts with a"
                    << " value less than 1.");
      cellOffsets->Delete();
      return 0;
      }
    lastOffset = coffset[i];
    }

623 624
  // Set range of progress for connectivity array.
  this->SetProgressRange(progressRange, 1, fractions);
625

626
  // Read the cell point connectivity array.
627
  vtkIdType cpLength = cellOffsets->GetValue(numberOfCells-1);
628
  vtkXMLDataElement* eConn = this->FindDataArrayWithName(eCells, "connectivity");
Ken Martin's avatar
Ken Martin committed
629
  if(!eConn)
630 631 632 633
    {
    vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"connectivity\" array could not be found.");
634
    cellOffsets->Delete();
635 636
    return 0;
    }
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
637 638
  vtkAbstractArray* ac0 = this->CreateArray(eConn);
  vtkDataArray* c0 = vtkDataArray::SafeDownCast(ac0);
639
  if(!c0 || (c0->GetNumberOfComponents() != 1))
640 641
    {
    vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
642 643 644
                  << " in piece " << this->Piece
                  << " because the \"connectivity\" array could not be created"
                  << " with one component.");
645
    cellOffsets->Delete();
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
646
    if (ac0) { ac0->Delete(); }
647 648 649
    return 0;
    }
  c0->SetNumberOfTuples(cpLength);
650
  if(!this->ReadArrayValues(eConn, 0, c0, 0, cpLength, CELL_DATA))
651 652 653 654
    {
    vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"connectivity\" array is not long enough.");
655
    cellOffsets->Delete();
656 657 658 659
    return 0;
    }
  vtkIdTypeArray* cellPoints = this->ConvertToIdTypeArray(c0);
  if(!cellPoints)
660 661
    {
    vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
662 663 664
                  << " in piece " << this->Piece
                  << " because the \"connectivity\" array could not be"
                  << " converted to a vtkIdTypeArray.");
665
    cellOffsets->Delete();
666 667
    return 0;
    }
668

669

670 671
  // Allocate memory in the output connectivity array.
  vtkIdType curSize = 0;
672
  if (this->Piece > this->StartPiece && outCells->GetData())
673
    {
674 675 676 677 678
    // Refer to BUG #12202 and BUG #12690. The (this->Piece > this->StartPiece)
    // check ensures that when we are reading mulitple timesteps, we don't end
    // up appending to existing cell arrays infinitely. An earlier version of
    // the fix assumed that vtkXMLUnstructuredDataReader read only 1 piece at a
    // time, which was incorrect (and hence  BUG #12690).
679 680
    curSize = outCells->GetData()->GetNumberOfTuples();
    }
681

682 683 684
  vtkIdType newSize = curSize+numberOfCells+cellPoints->GetNumberOfTuples();
  vtkIdType* cptr = outCells->WritePointer(totalNumberOfCells, newSize);
  cptr += curSize;
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
  // Copy the connectivity data.
  vtkIdType previousOffset = 0;
  for(i=0; i < numberOfCells; ++i)
    {
    vtkIdType length = cellOffsets->GetValue(i)-previousOffset;
    *cptr++ = length;
    vtkIdType* sptr = cellPoints->GetPointer(previousOffset);
    // Copy the point indices, but increment them for the appended
    // version's index.
    vtkIdType j;
    for(j=0;j < length; ++j)
      {
      cptr[j] = sptr[j]+this->StartPoint;
      }
    cptr += length;
    previousOffset += length;
    }
703

704 705
  cellPoints->Delete();
  cellOffsets->Delete();
706

707 708 709
  return 1;
}

710 711 712 713 714 715 716 717 718 719 720
//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::ReadFaceArray(vtkIdType numberOfCells,
                                                vtkXMLDataElement* eCells,
                                                vtkIdTypeArray* outFaces,
                                                vtkIdTypeArray* outFaceOffsets)
{

  if(numberOfCells <= 0)
    {
    return 1;
    }
721
  else
722 723 724 725 726 727
    {
    if(!eCells || !outFaces || !outFaceOffsets)
      {
      return 0;
      }
    }
728

729 730
  // Split progress range into 1/5 for faces array and 4/5 for
  // faceoffsets array.  This assumes an average of 4 points per
731
  // face.  Unfortunately, we cannot know the length ahead of time
732 733 734
  // to calculate the real fraction.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
735
  float fractions[3] = {0, 0.2f, 1};
736

737 738
  // Set range of progress for offsets array.
  this->SetProgressRange(progressRange, 0, fractions);
739

740
  // Read the cell offsets.
741
  vtkXMLDataElement* efaceOffsets =
742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
    this->FindDataArrayWithName(eCells, "faceoffsets");
  if(!efaceOffsets)
    {
    vtkErrorMacro("Cannot read face offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faceoffsets\" array could not be found.");
    return 0;
    }
  vtkAbstractArray* ac1 = this->CreateArray(efaceOffsets);
  vtkDataArray* c1 = vtkDataArray::SafeDownCast(ac1);
  if(!c1 || (c1->GetNumberOfComponents() != 1))
    {
    vtkErrorMacro("Cannot read face offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faceoffsets\" array could not be created"
                  << " with one component.");
    if (ac1)
      {
      ac1->Delete();
      }
    return 0;
    }
  c1->SetNumberOfTuples(numberOfCells);
  if(!this->ReadArrayValues(efaceOffsets, 0, c1, 0, numberOfCells))
    {
    vtkErrorMacro("Cannot read face offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faceoffsets\" array is not long enough.");
    return 0;
771
    }
772 773 774 775 776 777 778 779 780 781 782
  vtkIdTypeArray* faceOffsets = this->ConvertToIdTypeArray(c1);
  if(!faceOffsets)
    {
    vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"offsets\" array could not be"
                  << " converted to a vtkIdTypeArray.");
    return 0;
    }

  // Note that faceOffsets[i] points to the end of the i-th cell's faces + 1. We
783 784 785
  // now Extract the size of the faces array from faceOffsets array. We compute
  // it by subtracting the size of outFaces from the maximum value of faceOffset
  // array element. The faceOffsets array is incremental, but contains -1 to
786 787 788 789 790 791 792 793 794 795 796
  // indicate a non-polyhedron cell.
  vtkIdType* faceoffsetPtr = faceOffsets->GetPointer(0);
  vtkIdType maxOffset = -1;
  for (vtkIdType i = numberOfCells-1; i >= 0; i--)
    {
    if (faceoffsetPtr[i] > -1)
      {
      maxOffset = faceoffsetPtr[i];
      break;
      }
    }
797

798 799 800
  // Paraview-BUG-13892. The facesArrayLength here should be relative
  // to the current piece being read, NOT the outFaces already read.
  vtkIdType facesArrayLength = maxOffset;
801

802 803 804 805 806 807
  // special handling of the case of all non-polyhedron cells
  if (facesArrayLength <= 0)
    {
    faceOffsets->Delete();
    return 1;
    }
808

809 810
  // Set range of progress for faces array.
  this->SetProgressRange(progressRange, 1, fractions);
811

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
  // Read the faces array.
  vtkXMLDataElement* efaces = this->FindDataArrayWithName(eCells, "faces");
  if(!efaces)
    {
    vtkErrorMacro("Cannot read faces from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faces\" array could not be found.");
    faceOffsets->Delete();
    return 0;
    }
  vtkAbstractArray* ac0 = this->CreateArray(efaces);
  vtkDataArray* c0 = vtkDataArray::SafeDownCast(ac0);
  if(!c0 || (c0->GetNumberOfComponents() != 1))
    {
    vtkErrorMacro("Cannot read faces from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faces\" array could not be created"
                  << " with one component.");
    faceOffsets->Delete();
    if (ac0) { ac0->Delete(); }
    return 0;
    }
  c0->SetNumberOfTuples(facesArrayLength);
  if(!this->ReadArrayValues(efaces, 0, c0, 0, facesArrayLength))
    {
    vtkErrorMacro("Cannot read faces from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faces\" array is not long enough.");
    faceOffsets->Delete();
    return 0;
    }
  vtkIdTypeArray* faces = this->ConvertToIdTypeArray(c0);
  if(!faces)
    {
    vtkErrorMacro("Cannot read faces from " << eCells->GetName()
                  << " in piece " << this->Piece
                  << " because the \"faces\" array could not be"
                  << " converted to a vtkIdTypeArray.");
    faceOffsets->Delete();
    return 0;
    }


  // Copy the contents of the faceoffsets array.
856 857 858
  // Note that faceOffsets[i] points to the end of the i-th cell + 1. While
  // vtkUnstructuredGrid::FaceLocations[i] points to the beginning of the
  // i-th cell. Need to convert. Also note that for both arrays, a
859 860 861 862 863
  // non-polyhedron cell has a offset of -1.
  vtkIdType* facesPtr = faces->GetPointer(0);
  vtkIdType startLoc = outFaceOffsets->GetNumberOfTuples();
  vtkIdType* outFaceOffsetsPtr = outFaceOffsets->WritePointer(startLoc, numberOfCells);
  vtkIdType currLoc = startLoc;
864 865 866 867 868

  // (Paraview-BUG-13892)
  // outFaceOffsets should point to the offset location in the outFaces array
  vtkIdType currFaceLoc = outFaces->GetNumberOfTuples();
  for(vtkIdType i = 0; i < numberOfCells; ++i, ++outFaceOffsetsPtr)
869 870 871
    {
    if (faceoffsetPtr[i] < 0)
      {
872
      *outFaceOffsetsPtr = -1;
873 874 875
      }
    else
      {
876
      *outFaceOffsetsPtr = currFaceLoc;
877 878 879 880
      // find next offset
      // read numberOfFaces in a cell
      vtkIdType numberOfCellFaces = facesPtr[currLoc - startLoc];
      currLoc += 1;
881
      currFaceLoc++;
882 883 884
      for (vtkIdType j = 0; j < numberOfCellFaces; j++)
        {
        // read numberOfPoints in a face
885 886 887 888 889 890 891 892 893 894
        vtkIdType tmpLoc = currLoc - startLoc;
        vtkIdType numberOfFacePoints = facesPtr[tmpLoc];
        // update the point ids with StartPoint (Paraview-BUG-13892)
        if(this->StartPoint > 0)
          {
          for (vtkIdType pidx = tmpLoc+1; pidx < tmpLoc+1+numberOfFacePoints; pidx++)
            {
            facesPtr[pidx] += this->StartPoint;
            }
          }
895
        currLoc += numberOfFacePoints + 1;
896
        currFaceLoc += numberOfFacePoints + 1;
897 898 899
        }
      }
    }
900

901 902 903 904 905 906 907 908 909 910
  // sanity check
  if (currLoc - startLoc != facesArrayLength)
    {
    vtkErrorMacro("Cannot read faces from " << eCells->GetName()
                  << " in piece " << this->Piece << " because the \"faces\" and"
                  << " \"faceoffsets\" arrays don't match.");
    faceOffsets->Delete();
    return 0;
    }

911
  // Copy the contents of the faces array.
912 913 914
  startLoc = outFaces->GetNumberOfTuples();
  vtkIdType length = faces->GetNumberOfTuples();
  vtkIdType* outFacesPtr = outFaces->WritePointer(startLoc, length);
915
  for(vtkIdType i = 0; i < length; ++i, ++outFacesPtr)
916
    {
917
    *outFacesPtr = facesPtr[i];
918 919 920 921 922 923 924 925
    }

  faces->Delete();
  faceOffsets->Delete();

  return 1;
}

926 927
//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::ReadArrayForPoints(vtkXMLDataElement* da,
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
928
                                                     vtkAbstractArray* outArray)
929 930
{
  vtkIdType startPoint = this->StartPoint;
931
  vtkIdType numPoints = this->NumberOfPoints[this->Piece];
932
  vtkIdType components = outArray->GetNumberOfComponents();
Utkarsh Ayachit's avatar
ENH:  
Utkarsh Ayachit committed
933
  return this->ReadArrayValues(da, startPoint*components,outArray,
934
                               0, numPoints*components, POINT_DATA);
935
}
936 937 938 939 940

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataReader::PointsNeedToReadTimeStep(vtkXMLDataElement *eNested)
{
  // Easy case no timestep:
941
  int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
942
    this->NumberOfTimeSteps, this->TimeSteps);
943 944
  assert( numTimeSteps <= this->NumberOfTimeSteps );
  if (!numTimeSteps && !this->NumberOfTimeSteps)
945
    {
946
    assert( this->PointsTimeStep == -1 ); //No timestep in this file
947
    return 1;
948
    }
949
  // else TimeStep was specified but no TimeValues associated were found
950
  assert( this->NumberOfTimeSteps );
951 952

  // case numTimeSteps > 1
953
  int isCurrentTimeInArray =
954
    vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
955
  if( !isCurrentTimeInArray && numTimeSteps)
956 957 958
    {
    return 0;
    }
959 960
  // we know that time steps are specified and that CurrentTimeStep is in the array
  // we need to figure out if we need to read the array or if it was forwarded
961 962 963 964 965 966
  // Need to check the current 'offset'
  unsigned long offset;
  if( eNested->GetScalarAttribute("offset", offset) )
    {
    if( this->PointsOffset != offset )
      {
967 968
      // save the pointsOffset we are about to read
      assert( this->PointsTimeStep == -1 ); //cannot have mixture of binary and appended
969 970 971 972 973 974
      this->PointsOffset = offset;
      return 1;
      }
    }
  else
    {
975 976
    // No offset is specified this is a binary file
    // First thing to check if numTimeSteps == 0:
977 978
    if( !numTimeSteps && this->NumberOfTimeSteps && this->PointsTimeStep == -1)
      {
979 980
      // Update last PointsTimeStep read
      this->PointsTimeStep = this->CurrentTimeStep;
981 982
      return 1;
      }
983
    int isLastTimeInArray =
984 985
      vtkXMLReader::IsTimeStepInArray(this->PointsTimeStep, this->TimeSteps, numTimeSteps);
     // If no time is specified or if time is specified and match then read
986
    if (isCurrentTimeInArray && !isLastTimeInArray)
987
      {
988
      // CurrentTimeStep is in TimeSteps but Last is not := need to read
989 990 991 992 993
      // Update last PointsTimeStep read
      this->PointsTimeStep = this->CurrentTimeStep;
      return 1;
      }
    }
994
  // all other cases we don't need to read:
995 996 997 998 999 1000 1001 1002 1003
  return 0;
}

//----------------------------------------------------------------------------
// Returns true if we need to read the data for the current time step
int vtkXMLUnstructuredDataReader::CellsNeedToReadTimeStep(vtkXMLDataElement *eNested,
  int &cellstimestep, unsigned long &cellsoffset)
{
  // Easy case no timestep:
1004
  int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
1005
    this->NumberOfTimeSteps, this->TimeSteps);
1006 1007
  assert( numTimeSteps <= this->NumberOfTimeSteps );
  if (!numTimeSteps && !this->NumberOfTimeSteps)
1008
    {
1009
    assert( cellstimestep == -1 ); //No timestep in this file
1010
    return 1;
1011
    }
1012
  // else TimeStep was specified but no TimeValues associated were found
1013
  assert( !this->NumberOfTimeSteps );
1014 1015

  // case numTimeSteps > 1
1016
  int isCurrentTimeInArray =
1017
    vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
1018
  if( !isCurrentTimeInArray && numTimeSteps)
1019 1020 1021
    {
    return 0;
    }
1022 1023
  // we know that time steps are specified and that CurrentTimeStep is in the array
  // we need to figure out if we need to read the array or if it was forwarded
1024 1025 1026 1027 1028 1029
  // Need to check the current 'offset'
  unsigned long offset;
  if( eNested->GetScalarAttribute("offset", offset) )
    {
    if( cellsoffset != offset )
      {
1030 1031
      // save the cellsOffset we are about to read
      assert( cellstimestep == -1 ); //cannot have mixture of binary and appended
1032 1033 1034 1035 1036 1037
      cellsoffset = offset;
      return 1;
      }
    }
  else
    {
1038 1039 1040
    // No offset is specified this is a binary file
    // First thing to check if numTimeSteps == 0:
    if( !numTimeSteps && this->NumberOfTimeSteps && cellstimestep == -1)
1041
      {
1042 1043
      // Update last PointsTimeStep read
      cellstimestep = this->CurrentTimeStep;
1044 1045
      return 1;
      }
1046
    int isLastTimeInArray =
1047 1048
      vtkXMLReader::IsTimeStepInArray(cellstimestep, this->TimeSteps, numTimeSteps);
     // If no time is specified or if time is specified and match then read
1049
    if (isCurrentTimeInArray && !isLastTimeInArray)
1050
      {
1051
      // CurrentTimeStep is in TimeSteps but Last is not := need to read
1052 1053 1054 1055 1056
      // Update last cellstimestep read
      cellstimestep = this->CurrentTimeStep;
      return 1;
      }
    }
1057
  // all other cases we don't need to read:
1058 1059 1060
  return 0;
}