vtkXMLUnstructuredDataWriter.cxx 33.3 KB
Newer Older
1
2
3
4
5
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLUnstructuredDataWriter.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
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLUnstructuredDataWriter.h"
16

17
#include "vtkCellArray.h"
18
#include "vtkCellData.h"
19
#include "vtkCellIterator.h"
20
#include "vtkDataArray.h"
21
22
#include "vtkDataCompressor.h"
#include "vtkDataSetAttributes.h"
23
#include "vtkErrorCode.h"
24
#include "vtkIdTypeArray.h"
25
26
#include "vtkInformation.h"
#include "vtkInformationVector.h"
27
28
29
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPointSet.h"
30
#include "vtkPoints.h"
31
#include "vtkStreamingDemandDrivenPipeline.h"
32
#include "vtkUnsignedCharArray.h"
33
34
35
#define vtkXMLOffsetsManager_DoNotInclude
#include "vtkXMLOffsetsManager.h"
#undef  vtkXMLOffsetsManager_DoNotInclude
36

37
#include <cassert>
38

39
40
41
42
43
44
45
46
47
48
49

//----------------------------------------------------------------------------
vtkXMLUnstructuredDataWriter::vtkXMLUnstructuredDataWriter()
{
  this->NumberOfPieces = 1;
  this->WritePiece = -1;
  this->GhostLevel = 0;
  this->CellPoints = vtkIdTypeArray::New();
  this->CellOffsets = vtkIdTypeArray::New();
  this->CellPoints->SetName("connectivity");
  this->CellOffsets->SetName("offsets");
50
51

  this->CurrentPiece = 0;
52
53
54
55
  this->FieldDataOM->Allocate(0);
  this->PointsOM    = new OffsetsManagerGroup;
  this->PointDataOM = new OffsetsManagerArray;
  this->CellDataOM  = new OffsetsManagerArray;
56
57
58

  this->Faces = vtkIdTypeArray::New();
  this->FaceOffsets = vtkIdTypeArray::New();
59
60
  this->Faces->SetName("faces");
  this->FaceOffsets->SetName("faceoffsets");
61
62
63
64
65
66
67
}

//----------------------------------------------------------------------------
vtkXMLUnstructuredDataWriter::~vtkXMLUnstructuredDataWriter()
{
  this->CellPoints->Delete();
  this->CellOffsets->Delete();
68
69
  this->Faces->Delete();
  this->FaceOffsets->Delete();
70

71
72
73
  delete this->PointsOM;
  delete this->PointDataOM;
  delete this->CellDataOM;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n";
  os << indent << "WritePiece: " << this->WritePiece << "\n";
  os << indent << "GhostLevel: " << this->GhostLevel << "\n";
}

//----------------------------------------------------------------------------
vtkPointSet* vtkXMLUnstructuredDataWriter::GetInputAsPointSet()
{
88
  return static_cast<vtkPointSet*>(this->Superclass::GetInput());
89
90
91
}

//----------------------------------------------------------------------------
92
93
94
int vtkXMLUnstructuredDataWriter::ProcessRequest(vtkInformation* request,
                                                 vtkInformationVector** inputVector,
                                                 vtkInformationVector* outputVector)
95
{
96
97

  if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
98
    {
99
100
101
    if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
      {
      this->SetInputUpdateExtent(
102
        this->CurrentPiece, this->NumberOfPieces, this->GhostLevel);
103
104
105
106
      }
    else
      {
      this->SetInputUpdateExtent(
107
        this->WritePiece, this->NumberOfPieces, this->GhostLevel);
108
109
      }
    return 1;
110
    }
111

112
113
  // generate the data
  else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
114
    {
115
116
    this->SetErrorCode(vtkErrorCode::NoError);

117
    if(!this->Stream && !this->FileName && !this->WriteToOutputString)
118
119
      {
      this->SetErrorCode(vtkErrorCode::NoFileNameError);
120
121
      vtkErrorMacro("The FileName or Stream must be set first or "
        "the output must be written to a string.");
122
123
124
      return 0;
      }

125
126
127
    int numPieces = this->NumberOfPieces;

    if (this->WritePiece >= 0)
128
      {
129
      this->CurrentPiece = this->WritePiece;
130
      }
131
132
    else
      {
133
134
      float wholeProgressRange[2] = {0,1};
      this->SetProgressRange(wholeProgressRange, this->CurrentPiece, this->NumberOfPieces);
135
136
137
      }

    int result = 1;
138
    if ((this->CurrentPiece == 0 && this->CurrentTimeIndex == 0) || this->WritePiece >= 0)
139
140
141
142
143
144
145
      {
      // We are just starting to write.  Do not call
      // UpdateProgressDiscrete because we want a 0 progress callback the
      // first time.
      this->UpdateProgress(0);

      // Initialize progress range to entire 0..1 range.
146
147
148
149
150
      if (this->WritePiece >= 0)
        {
        float wholeProgressRange[2] = {0,1};
        this->SetProgressRange(wholeProgressRange, 0, 1);
        }
151

152
      if (!this->OpenStream())
153
154
155
156
        {
        this->NumberOfPieces = numPieces;
        return 0;
        }
157
158

      if (this->GetInputAsDataSet() != NULL &&
159
160
          (this->GetInputAsDataSet()->GetPointGhostArray() != NULL &&
           this->GetInputAsDataSet()->GetCellGhostArray() != NULL))
161
        {
162
163
        // use the current version for the file.
        this->UsePreviousVersion = false;
164
165
        }

166
167
168
169
170
171
172
173
174
175
176
177
      // Write the file.
      if (!this->StartFile())
        {
        this->NumberOfPieces = numPieces;
        return 0;
        }

      if (!this->WriteHeader())
        {
        this->NumberOfPieces = numPieces;
        return 0;
        }
178

179
      this->CurrentTimeIndex = 0;
180
      if( this->DataMode == vtkXMLWriter::Appended && this->FieldDataOM->GetNumberOfElements())
181
182
        {
        // Write the field data arrays.
183
        this->WriteFieldDataAppendedData(this->GetInput()->GetFieldData(),
184
          this->CurrentTimeIndex, this->FieldDataOM);
185
186
187
188
189
190
        if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
          {
          this->DeletePositionArrays();
          return 0;
          }
        }
191
192
      }

193
194
195
196
    if( !(this->UserContinueExecuting == 0)) //if user ask to stop do not try to write a piece
      {
      result = this->WriteAPiece();
      }
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

    if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
      {
      // Tell the pipeline to start looping.
      if (this->CurrentPiece == 0)
        {
        request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1);
        }
      this->CurrentPiece++;
      }

    if (this->CurrentPiece == this->NumberOfPieces || this->WritePiece >= 0)
      {
      request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING());
      this->CurrentPiece = 0;
Mathieu Malaterre's avatar
Mathieu Malaterre committed
212
      // We are done writing all the pieces, lets loop over time now:
213
      this->CurrentTimeIndex++;
214

215
      if( this->UserContinueExecuting != 1 )
216
        {
217
218
219
220
221
222
223
224
225
226
227
        if (!this->WriteFooter())
          {
          this->NumberOfPieces = numPieces;
          return 0;
          }

        if (!this->EndFile())
          {
          this->NumberOfPieces = numPieces;
          return 0;
          }
228

229
        this->CloseStream();
230
        this->CurrentTimeIndex = 0; // Reset
231
        }
232
233
234
      }
    this->NumberOfPieces = numPieces;

235
236
    // We have finished writing (at least this piece)
    this->SetProgressPartial(1);
237
238
239
    return result;
    }
  return this->Superclass::ProcessRequest(request, inputVector, outputVector);
240
241
242
}

//----------------------------------------------------------------------------
243
void vtkXMLUnstructuredDataWriter::AllocatePositionArrays()
244
{
245
  this->NumberOfPointsPositions = new vtkTypeInt64[this->NumberOfPieces];
246
247
248
249

  this->PointsOM->Allocate(this->NumberOfPieces, this->NumberOfTimeSteps);
  this->PointDataOM->Allocate(this->NumberOfPieces);
  this->CellDataOM->Allocate(this->NumberOfPieces);
250
251
252
253
254
255
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::DeletePositionArrays()
{
  delete [] this->NumberOfPointsPositions;
256
  this->NumberOfPointsPositions = 0;
257
}
258

259
260
261
262
263
//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataWriter::WriteHeader()
{
  vtkIndent indent = vtkIndent().GetNextIndent();

264
  ostream& os = *(this->Stream);
265

266
267
268
269
  if(!this->WritePrimaryElement(os, indent))
    {
    return 0;
    }
270

271
272
  this->WriteFieldData(indent.GetNextIndent());

273
  if(this->DataMode == vtkXMLWriter::Appended)
274
    {
275
276
277
278
279
    vtkIndent nextIndent = indent.GetNextIndent();

    this->AllocatePositionArrays();

    if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
280
      {
281
282
283
284
285
286
287
288
289
290
291
292
293
      // Loop over each piece and write its structure.
      int i;
      for(i=0; i < this->NumberOfPieces; ++i)
        {
        // Open the piece's element.
        os << nextIndent << "<Piece";
        this->WriteAppendedPieceAttributes(i);
        if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
          {
          this->DeletePositionArrays();
          return 0;
          }
        os << ">\n";
294

295
296
297
298
299
300
        this->WriteAppendedPiece(i, nextIndent.GetNextIndent());
        if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
          {
          this->DeletePositionArrays();
          return 0;
          }
301

302
303
304
305
306
307
308
        // Close the piece's element.
        os << nextIndent << "</Piece>\n";
        }
      }
    else
      {
      // Write just the requested piece.
309
310
      // Open the piece's element.
      os << nextIndent << "<Piece";
311
      this->WriteAppendedPieceAttributes(this->WritePiece);
312
313
      if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
        {
314
        this->DeletePositionArrays();
315
316
        return 0;
        }
317
      os << ">\n";
318

319
      this->WriteAppendedPiece(this->WritePiece, nextIndent.GetNextIndent());
320
321
      if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
        {
322
        this->DeletePositionArrays();
323
324
        return 0;
        }
325

326
      // Close the piece's element.
327
      os << nextIndent << "</Piece>\n";
328
      }
329
330
331
332
333
334
335
336
337
338

    // Close the primary element.
    os << indent << "</" << this->GetDataSetName() << ">\n";
    os.flush();
    if (os.fail())
      {
      this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
      this->DeletePositionArrays();
      return 0;
      }
339

340
    this->StartAppendedData();
341
342
    if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
      {
343
      this->DeletePositionArrays();
344
345
      return 0;
      }
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataWriter::WriteAPiece()
{
  vtkIndent indent = vtkIndent().GetNextIndent();

  int result=1;

  if(this->DataMode == vtkXMLWriter::Appended)
    {
    this->WriteAppendedPieceData(this->CurrentPiece);
    }
  else
    {
    result = this->WriteInlineMode(indent);
    }

  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    this->DeletePositionArrays();
    result = 0;
    }
  return result;
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataWriter::WriteFooter()
{
  vtkIndent indent = vtkIndent().GetNextIndent();

  ostream& os = *(this->Stream);
382

383
384
385
386
387
388
389
390
391
392
393
  if(this->DataMode == vtkXMLWriter::Appended)
    {
    this->DeletePositionArrays();
    this->EndAppendedData();
    }
  else
    {
    // Close the primary element.
    os << indent << "</" << this->GetDataSetName() << ">\n";
    os.flush();
    if (os.fail())
394
395
396
      {
      return 0;
      }
397
    }
398

399
400
401
402
403
404
405
406
  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLUnstructuredDataWriter::WriteInlineMode(vtkIndent indent)
{
  ostream& os = *(this->Stream);
  vtkIndent nextIndent = indent.GetNextIndent();
407

408
409
410
411
  // Open the piece's element.
  os << nextIndent << "<Piece";
  this->WriteInlinePieceAttributes();
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
412
413
414
    {
    return 0;
    }
415
  os << ">\n";
416

417
418
419
420
421
422
423
424
425
  this->WriteInlinePiece(nextIndent.GetNextIndent());
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return 0;
    }

  // Close the piece's element.
  os << nextIndent << "</Piece>\n";

426
  return 1;
427
428
429
430
431
432
433
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteInlinePieceAttributes()
{
  vtkPointSet* input = this->GetInputAsPointSet();
  this->WriteScalarAttribute("NumberOfPoints",
434
                             input->GetNumberOfPoints());
435
436
437
438
439
440
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteInlinePiece(vtkIndent indent)
{
  vtkPointSet* input = this->GetInputAsPointSet();
441

442
443
444
445
446
  // Split progress among point data, cell data, and point arrays.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[4];
  this->CalculateDataFractions(fractions);
447

448
  // Set the range of progress for the point data arrays.
449
450
  this->SetProgressRange(progressRange, 0, fractions);

451
  // Write the point data arrays.
452
  this->WritePointDataInline(input->GetPointData(), indent);
453
454
455
456
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
457

458
459
  // Set the range of progress for the cell data arrays.
  this->SetProgressRange(progressRange, 1, fractions);
460

461
  // Write the cell data arrays.
462
  this->WriteCellDataInline(input->GetCellData(), indent);
463
464
465
466
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
467

468
469
  // Set the range of progress for the point specification array.
  this->SetProgressRange(progressRange, 2, fractions);
470

471
472
  // Write the point specification array.
  this->WritePointsInline(input->GetPoints(), indent);
473
474
475
476
477
478
479
480
481
482
483
484
485
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteAppendedPieceAttributes(int index)
{
  this->NumberOfPointsPositions[index] =
    this->ReserveAttributeSpace("NumberOfPoints");
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteAppendedPiece(int index,
                                                      vtkIndent indent)
{
486
  vtkPointSet* input = this->GetInputAsPointSet();
487
488

  this->WritePointDataAppended(input->GetPointData(), indent,
489
    &this->PointDataOM->GetPiece(index));
490
491
492
493
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
494
495

  this->WriteCellDataAppended(input->GetCellData(), indent,
496
    &this->CellDataOM->GetPiece(index));
497
498
499
500
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
501
502

  this->WritePointsAppended(input->GetPoints(), indent,
503
    &this->PointsOM->GetPiece(index));
504
505
506
507
508
509
510
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteAppendedPieceData(int index)
{
  ostream& os = *(this->Stream);
  vtkPointSet* input = this->GetInputAsPointSet();
511

512
513
  std::streampos returnPosition = os.tellp();
  os.seekp(std::streampos(this->NumberOfPointsPositions[index]));
514
  vtkPoints* points = input->GetPoints();
515
  this->WriteScalarAttribute("NumberOfPoints",
516
                             (points?points->GetNumberOfPoints():0));
517
518
519
520
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
521
  os.seekp(returnPosition);
522

523
524
525
526
527
  // Split progress among point data, cell data, and point arrays.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
  float fractions[4];
  this->CalculateDataFractions(fractions);
528

529
530
  // Set the range of progress for the point data arrays.
  this->SetProgressRange(progressRange, 0, fractions);
531

532
  // Write the point data arrays.
533
534
  this->WritePointDataAppendedData(input->GetPointData(), this->CurrentTimeIndex,
                                  &this->PointDataOM->GetPiece(index));
535
536
537
538
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
539

540
541
  // Set the range of progress for the cell data arrays.
  this->SetProgressRange(progressRange, 1, fractions);
542
543

  // Write the cell data arrays.
544
545
  this->WriteCellDataAppendedData(input->GetCellData(), this->CurrentTimeIndex,
                                  &this->CellDataOM->GetPiece(index));
546
547
548
549
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
550

551
552
  // Set the range of progress for the point specification array.
  this->SetProgressRange(progressRange, 2, fractions);
553

554
  // Write the point specification array.
555
  // Since we are writing the point let save the Modified Time of vtkPoints:
556
557
  this->WritePointsAppendedData(input->GetPoints(), this->CurrentTimeIndex,
                                &this->PointsOM->GetPiece(index));
558
559
}

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsInline(
    const char *name, vtkCellIterator *cellIter, vtkIdType numCells,
    vtkIdType cellSizeEstimate, vtkIndent indent)
{
  this->ConvertCells(cellIter, numCells, cellSizeEstimate);

  // Faces are not supported via this method.
  this->Faces->SetNumberOfTuples(0);
  this->FaceOffsets->SetNumberOfTuples(0);

  vtkNew<vtkUnsignedCharArray> types;
  types->Allocate(numCells);
  for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
       cellIter->GoToNextCell())
    {
    types->InsertNextValue(static_cast<unsigned char>(cellIter->GetCellType()));
    }

  this->WriteCellsInlineWorker(name, types.GetPointer(), indent);
}

582
583
584
585
586
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsInline(const char* name,
                                                    vtkCellArray* cells,
                                                    vtkDataArray* types,
                                                    vtkIndent indent)
587
588
589
590
591
592
{
  this->WriteCellsInline(name, cells, types, NULL, NULL, indent);
}


//----------------------------------------------------------------------------
593
594
595
void vtkXMLUnstructuredDataWriter::WriteCellsInline(const char* name,
                        vtkCellArray* cells,  vtkDataArray* types,
                        vtkIdTypeArray* faces, vtkIdTypeArray* faceOffsets,
596
                        vtkIndent indent)
597
{
598
599
600
601
  if(cells)
    {
    this->ConvertCells(cells);
    }
602
  this->ConvertFaces(faces, faceOffsets);
603

604
605
606
607
608
609
610
  this->WriteCellsInlineWorker(name, types, indent);
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsInlineWorker(
    const char *name, vtkDataArray *types, vtkIndent indent)
{
611
612
  ostream& os = *(this->Stream);
  os << indent << "<" << name << ">\n";
613

614
615
616
  // Split progress by cell connectivity, offset, and type arrays.
  float progressRange[2] = {0,0};
  this->GetProgressRange(progressRange);
617
  float fractions[6];
618
  this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0);
619

620
621
  // Set the range of progress for the connectivity array.
  this->SetProgressRange(progressRange, 0, fractions);
622

623
  // Write the connectivity array.
Utkarsh Ayachit's avatar
ENH:    
Utkarsh Ayachit committed
624
  this->WriteArrayInline(this->CellPoints, indent.GetNextIndent());
625
626
627
628
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
629

630
631
  // Set the range of progress for the offsets array.
  this->SetProgressRange(progressRange, 1, fractions);
632

633
  // Write the offsets array.
Utkarsh Ayachit's avatar
ENH:    
Utkarsh Ayachit committed
634
  this->WriteArrayInline(this->CellOffsets, indent.GetNextIndent());
635
636
637
638
  if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
    {
    return;
    }
639

640
641
  if(types)
    {
642
643
    // Set the range of progress for the types array.
    this->SetProgressRange(progressRange, 2, fractions);
644

645
    // Write the types array.
Utkarsh Ayachit's avatar
ENH:    
Utkarsh Ayachit committed
646
    this->WriteArrayInline(types, indent.GetNextIndent(), "types");
647
648
649
650
    if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
      {
      return;
      }
651
    }
652
653
654
655
656

  if (this->Faces->GetNumberOfTuples())
    {
    // Set the range of progress for the faces array.
    this->SetProgressRange(progressRange, 3, fractions);
657

658
659
660
661
662
663
664
    // Write the connectivity array.
    this->WriteArrayInline(this->Faces, indent.GetNextIndent(), "faces");
    if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
      {
      return;
      }
    }
665

666
667
668
669
  if (this->FaceOffsets->GetNumberOfTuples())
    {
    // Set the range of progress for the face offset array.
    this->SetProgressRange(progressRange, 4, fractions);
670

671
672
673
674
675
676
677
    // Write the face offsets array.
    this->WriteArrayInline(this->FaceOffsets, indent.GetNextIndent(), "faceoffsets");
    if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
      {
      return;
      }
    }
678

679
  os << indent << "</" << name << ">\n";
680
681
682
683
684
  os.flush();
  if (os.fail())
    {
    this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
    }
685
686
}

687
688
689
690
691
692
693
694
695
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsAppended(const char* name,
                                                      vtkDataArray* types,
                                                      vtkIndent indent,
                                                      OffsetsManagerGroup *cellsManager)
{
  this->WriteCellsAppended(name, types, 0, 0, indent, cellsManager);
}

696
//----------------------------------------------------------------------------
697
698
void vtkXMLUnstructuredDataWriter::WriteCellsAppended(const char* name,
                                                      vtkDataArray* types,
699
700
                                                      vtkIdTypeArray* faces,
                                                      vtkIdTypeArray* faceOffsets,
701
702
                                                      vtkIndent indent,
                                                      OffsetsManagerGroup *cellsManager)
703
{
704
  this->ConvertFaces(faces,faceOffsets);
705
706
  ostream& os = *(this->Stream);
  os << indent << "<" << name << ">\n";
707
708

  // Helper for the 'for' loop
709
  vtkDataArray *allcells[5];
710
711
712
  allcells[0] = this->CellPoints;
  allcells[1] = this->CellOffsets;
  allcells[2] = types;
713
714
  allcells[3] = this->Faces->GetNumberOfTuples() ? this->Faces : 0;
  allcells[4] = this->FaceOffsets->GetNumberOfTuples() ? this->FaceOffsets : 0;
715
  const char *names[] = {NULL, NULL, "types", NULL, NULL};
716
717

  for(int t=0; t<this->NumberOfTimeSteps; t++)
718
    {
719
    for(int i=0; i<5; i++)
720
      {
721
      if(allcells[i])
722
        {
Utkarsh Ayachit's avatar
ENH:    
Utkarsh Ayachit committed
723
724
        this->WriteArrayAppended(allcells[i], indent.GetNextIndent(),
          cellsManager->GetElement(i), names[i], 0, t);
725
726
727
728
729
        if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
          {
          return;
          }
        }
730
      }
731
732
    }
  os << indent << "</" << name << ">\n";
733
734
735
736
  os.flush();
  if (os.fail())
    {
    this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
737
    return;
738
    }
739

740
741
}

742
743
744
745
746
747
748
749
750
751
752
753
754
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsAppended(
    const char *name, vtkCellIterator *cellIter, vtkIdType numCells,
    vtkIndent indent, OffsetsManagerGroup *cellsManager)
{
  vtkNew<vtkUnsignedCharArray> types;
  types->Allocate(numCells);
  for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
       cellIter->GoToNextCell())
    {
    types->InsertNextValue(static_cast<unsigned char>(cellIter->GetCellType()));
    }

755
  this->WriteCellsAppended(name, types.GetPointer(), 0, 0, indent, cellsManager);
756
757
}

758
759
760
761
//----------------------------------------------------------------------------
void
vtkXMLUnstructuredDataWriter::WriteCellsAppendedData(vtkCellArray* cells,
                                                     vtkDataArray* types,
762
763
                                                     int timestep,
                                                     OffsetsManagerGroup *cellsManager)
764
765
766
767
{
  this->WriteCellsAppendedData(cells, types, NULL, NULL, timestep, cellsManager);
}

768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsAppendedData(
    vtkCellIterator *cellIter, vtkIdType numCells, vtkIdType cellSizeEstimate,
    int timestep, OffsetsManagerGroup *cellsManager)
{
  this->ConvertCells(cellIter, numCells, cellSizeEstimate);

  // Faces are not supported by this method:
  this->Faces->SetNumberOfTuples(0);
  this->FaceOffsets->SetNumberOfTuples(0);

  vtkNew<vtkUnsignedCharArray> types;
  types->Allocate(this->CellOffsets->GetNumberOfTuples() + 1);

  for(cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
      cellIter->GoToNextCell())
    {
    types->InsertNextValue(static_cast<unsigned char>(cellIter->GetCellType()));
    }

  this->WriteCellsAppendedDataWorker(types.GetPointer(), timestep,
                                     cellsManager);
}

792
793
794
795
796
797
798
799
//----------------------------------------------------------------------------
void
vtkXMLUnstructuredDataWriter::WriteCellsAppendedData(vtkCellArray* cells,
                                                     vtkDataArray* types,
                                                     vtkIdTypeArray* faces,
                                                     vtkIdTypeArray* faceOffsets,
                                                     int timestep,
                                                     OffsetsManagerGroup *cellsManager)
800
{
801
802
803
804
  if (cells)
    {
    this->ConvertCells(cells);
    }
805

806
  this->ConvertFaces(faces, faceOffsets);
807
808
  this->WriteCellsAppendedDataWorker(types, timestep, cellsManager);
}
809

810
811
812
813
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::WriteCellsAppendedDataWorker(
    vtkDataArray *types, int timestep, OffsetsManagerGroup *cellsManager)
{
814
  // Split progress by cell connectivity, offset, and type arrays.
815
  float progressRange[5] = {0,0,0,0,0};
816
  this->GetProgressRange(progressRange);
817
  float fractions[6];
818
  this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0);
819

820
  // Helper for the 'for' loop
821
  vtkDataArray *allcells[5];
822
823
824
  allcells[0] = this->CellPoints;
  allcells[1] = this->CellOffsets;
  allcells[2] = types;
825
826
  allcells[3] = this->Faces->GetNumberOfTuples() ? this->Faces : 0;
  allcells[4] = this->FaceOffsets->GetNumberOfTuples() ? this->FaceOffsets : 0;
827

828
  for(int i=0; i<5; i++)
829
    {
830
    if(allcells[i])
831
      {
832
833
      // Set the range of progress for the connectivity array.
      this->SetProgressRange(progressRange, i, fractions);
834

835
836
837
838
839
840
841
      unsigned long mtime = allcells[i]->GetMTime();
      unsigned long &cellsMTime = cellsManager->GetElement(i).GetLastMTime();
      // Only write cells if MTime has changed
      if( cellsMTime != mtime )
        {
        cellsMTime = mtime;
        // Write the connectivity array.
842
        this->WriteArrayAppendedData(allcells[i],
843
844
845
846
847
848
849
850
851
          cellsManager->GetElement(i).GetPosition(timestep),
          cellsManager->GetElement(i).GetOffsetValue(timestep));
        if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
          {
          return;
          }
        }
      else
        {
852
        // One timestep must have already been written or the
853
        // mtime would have changed and we would not be here.
854
        assert( timestep > 0 );
855
        cellsManager->GetElement(i).GetOffsetValue(timestep) =
856
857
858
859
860
          cellsManager->GetElement(i).GetOffsetValue(timestep-1);
        this->ForwardAppendedDataOffset(cellsManager->GetElement(i).GetPosition(timestep),
                                        cellsManager->GetElement(i).GetOffsetValue(timestep),
                                        "offset" );
        }
861
      }
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
  }
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::ConvertCells(
    vtkCellIterator *cellIter, vtkIdType numCells, vtkIdType cellSizeEstimate)
{
  this->CellPoints->Allocate(numCells * cellSizeEstimate);
  this->CellOffsets->Allocate(numCells);

  for (cellIter->InitTraversal(); !cellIter->IsDoneWithTraversal();
       cellIter->GoToNextCell())
    {
    vtkIdType *begin = cellIter->GetPointIds()->GetPointer(0);
    vtkIdType *end = begin + cellIter->GetNumberOfPoints();
    while (begin != end)
      {
      this->CellPoints->InsertNextValue(*begin++);
      }

    this->CellOffsets->InsertNextValue(this->CellPoints->GetNumberOfTuples());
883
    }
884
885
886

  this->CellPoints->Squeeze();
  this->CellOffsets->Squeeze();
887
888
889
890
891
892
893
894
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::ConvertCells(vtkCellArray* cells)
{
  vtkIdTypeArray* connectivity = cells->GetData();
  vtkIdType numberOfCells = cells->GetNumberOfCells();
  vtkIdType numberOfTuples = connectivity->GetNumberOfTuples();
895

896
897
  this->CellPoints->SetNumberOfTuples(numberOfTuples - numberOfCells);
  this->CellOffsets->SetNumberOfTuples(numberOfCells);
898

899
900
901
902
  vtkIdType* inCell = connectivity->GetPointer(0);
  vtkIdType* outCellPointsBase = this->CellPoints->GetPointer(0);
  vtkIdType* outCellPoints = outCellPointsBase;
  vtkIdType* outCellOffset = this->CellOffsets->GetPointer(0);
903

904
905
906
907
908
909
910
911
912
913
  vtkIdType i;
  for(i=0;i < numberOfCells; ++i)
    {
    vtkIdType numberOfPoints = *inCell++;
    memcpy(outCellPoints, inCell, sizeof(vtkIdType)*numberOfPoints);
    outCellPoints += numberOfPoints;
    inCell += numberOfPoints;
    *outCellOffset++ = outCellPoints - outCellPointsBase;
    }
}
914

915
916
917
918
919
920
921
922
923
924
925
926
//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::ConvertFaces(vtkIdTypeArray* faces,
                                                vtkIdTypeArray* faceOffsets)
{
  if (!faces || !faces->GetNumberOfTuples() ||
      !faceOffsets || !faceOffsets->GetNumberOfTuples())
    {
    this->Faces->SetNumberOfTuples(0);
    this->FaceOffsets->SetNumberOfTuples(0);
    return;
    }

927
928
929
930
931
932
933
934
  // copy faces stream.
  this->Faces->SetNumberOfTuples(faces->GetNumberOfTuples());
  vtkIdType * fromPtr = faces->GetPointer(0);
  vtkIdType * toPtr = this->Faces->GetPointer(0);
  for (vtkIdType i = 0; i < faces->GetNumberOfTuples(); i++)
    {
    *toPtr++ = *fromPtr++;
    }
935
936
937

  // this->FaceOffsets point to the face arrays of cells. Specifically
  // FaceOffsets[i] points to the end of the i-th cell's faces + 1. While
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  // input faceOffsets[i] points to the beginning of the i-th cell. Note
  // that for both arrays, a non-polyhedron cell has an offset of -1.
  vtkIdType numberOfCells = faceOffsets->GetNumberOfTuples();
  this->FaceOffsets->SetNumberOfTuples(numberOfCells);
  vtkIdType* newOffsetPtr = this->FaceOffsets->GetPointer(0);
  vtkIdType* oldOffsetPtr = faceOffsets->GetPointer(0);
  vtkIdType* facesPtr = this->Faces->GetPointer(0);
  bool foundPolyhedronCell = false;
  for (vtkIdType i = 0; i < numberOfCells; i++)
    {
    if (oldOffsetPtr[i] < 0) //non-polyhedron cell
      {
      newOffsetPtr[i] = -1;
      }
    else // polyhedron cell
      {
      foundPolyhedronCell = true;
      // read numberOfFaces in a cell
      vtkIdType currLoc = oldOffsetPtr[i];
      vtkIdType numberOfCellFaces = facesPtr[currLoc];
      currLoc += 1;
      for (vtkIdType j = 0; j < numberOfCellFaces; j++)
        {
        // read numberOfPoints in a face
        vtkIdType numberOfFacePoints = facesPtr[currLoc];
        currLoc += numberOfFacePoints + 1;
        }
965
      newOffsetPtr[i] = currLoc;
966
967
      }
    }
968

969
970
971
972
973
974
975
976
977
  if (!foundPolyhedronCell)
    {
    this->Faces->SetNumberOfTuples(0);
    this->FaceOffsets->SetNumberOfTuples(0);
    }

  return;
}

978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//----------------------------------------------------------------------------
vtkIdType vtkXMLUnstructuredDataWriter::GetNumberOfInputPoints()
{
  vtkPointSet* input = this->GetInputAsPointSet();
  vtkPoints* points = input->GetPoints();
  return points?points->GetNumberOfPoints():0;
}

//----------------------------------------------------------------------------
void vtkXMLUnstructuredDataWriter::CalculateDataFractions(float* fractions)
{
  // Calculate the fraction of point/cell data and point
  // specifications contributed by each component.
  vtkPointSet* input = this->GetInputAsPointSet();
  int pdArrays = input->GetPointData()->GetNumberOfArrays();
  int cdArrays = input->GetCellData()->GetNumberOfArrays();
  vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints();
  vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells();
  int total = (pdSize+cdSize+this->GetNumberOfInputPoints());
  if(total == 0)
    {
    total = 1;
    }