1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkChacoReader.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 /*----------------------------------------------------------------------------
17 Copyright (c) Sandia Corporation
18 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
19 ----------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "vtkChacoReader.h"
24 #include "vtkCellArray.h"
25 #include "vtkCellData.h"
26 #include "vtkPointData.h"
27 #include "vtkDoubleArray.h"
28 #include "vtkInformation.h"
29 #include "vtkInformationDoubleVectorKey.h"
30 #include "vtkInformationVector.h"
31 #include "vtkIntArray.h"
32 #include "vtkObjectFactory.h"
33 #include "vtkStreamingDemandDrivenPipeline.h"
34 #include "vtkUnstructuredGrid.h"
35
36 vtkStandardNewMacro(vtkChacoReader);
37
38 //----------------------------------------------------------------------------
39 // Description:
40 // Instantiate object with NULL filename.
vtkChacoReader()41 vtkChacoReader::vtkChacoReader()
42 {
43 this->BaseName = NULL;
44 this->GenerateGlobalElementIdArray = 1;
45 this->GenerateGlobalNodeIdArray = 1;
46 this->GenerateVertexWeightArrays = 0;
47 this->GenerateEdgeWeightArrays = 0;
48 this->EarrayName = NULL;
49 this->VarrayName = NULL;
50 this->Dimensionality = -1;
51 this->NumberOfVertices = 0;
52 this->NumberOfEdges = 0;
53 this->NumberOfVertexWeights = 0;
54 this->NumberOfEdgeWeights = 0;
55 this->GraphFileHasVertexNumbers = 0;
56
57 this->NumberOfPointWeightArrays = 0;
58 this->NumberOfCellWeightArrays = 0;
59
60 this->CurrentGeometryFP = NULL;
61 this->CurrentGraphFP = NULL;
62 this->CurrentBaseName = NULL;
63
64 this->DataCache = vtkUnstructuredGrid::New();
65 this->RemakeDataCacheFlag = 1;
66
67 this->Line_length = 200;
68 this->Line = new char [200];
69 this->Offset = 0;
70 this->Break_pnt = 200;
71 this->Save_pnt = 0;
72
73 this->SetNumberOfInputPorts(0);
74 }
75
76 //----------------------------------------------------------------------------
~vtkChacoReader()77 vtkChacoReader::~vtkChacoReader()
78 {
79 this->SetBaseName(NULL);
80 this->SetCurrentBaseName(NULL);
81
82 this->ClearWeightArrayNames();
83
84 this->DataCache->Delete();
85 this->DataCache = NULL;
86
87 delete [] this->Line;
88 }
89
90 //----------------------------------------------------------------------------
ClearWeightArrayNames()91 void vtkChacoReader::ClearWeightArrayNames()
92 {
93 int i=0;
94 if (this->VarrayName)
95 {
96 for (i=0; i<this->NumberOfVertexWeights; i++)
97 {
98 delete [] this->VarrayName[i];
99 }
100 delete [] this->VarrayName;
101 this->VarrayName = NULL;
102 }
103
104 if (this->EarrayName)
105 {
106 for (i=0; i<this->NumberOfEdgeWeights; i++)
107 {
108 delete [] this->EarrayName[i];
109 }
110 delete [] this->EarrayName;
111 this->EarrayName = NULL;
112 }
113 }
114
115 //----------------------------------------------------------------------------
MakeWeightArrayNames(int nv,int ne)116 void vtkChacoReader::MakeWeightArrayNames(int nv, int ne)
117 {
118 int i=0;
119 if (nv > 0)
120 {
121 this->VarrayName = new char *[nv];
122 for (i=0; i<nv; i++)
123 {
124 this->VarrayName[i] = new char [64];
125 sprintf(this->VarrayName[i], "VertexWeight%d", i+1);
126 }
127 }
128 if (ne > 0)
129 {
130 this->EarrayName = new char *[ne];
131 for (i=0; i<ne; i++)
132 {
133 this->EarrayName[i] = new char [64];
134 sprintf(this->EarrayName[i], "EdgeWeight%d", i+1);
135 }
136 }
137 }
138
139 //----------------------------------------------------------------------------
GetVertexWeightArrayName(int weight)140 const char *vtkChacoReader::GetVertexWeightArrayName(int weight)
141 {
142 if (this->GetGenerateVertexWeightArrays() &&
143 (weight > 0) &&
144 (weight <= this->NumberOfVertexWeights))
145 {
146 return this->VarrayName[weight-1];
147 }
148
149 return NULL;
150 }
151
152 //----------------------------------------------------------------------------
GetEdgeWeightArrayName(int weight)153 const char *vtkChacoReader::GetEdgeWeightArrayName(int weight)
154 {
155 if (this->GetGenerateEdgeWeightArrays() &&
156 (weight > 0) &&
157 (weight <= this->NumberOfEdgeWeights))
158 {
159 return this->EarrayName[weight-1];
160 }
161
162 return NULL;
163 }
164
165 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * vtkNotUsed (outputVector))166 int vtkChacoReader::RequestInformation(
167 vtkInformation *vtkNotUsed(request),
168 vtkInformationVector **vtkNotUsed(inputVector),
169 vtkInformationVector *vtkNotUsed(outputVector))
170 {
171 double x, y, z;
172
173 if (!this->BaseName)
174 {
175 vtkErrorMacro(<< "No BaseName specified");
176 return 0;
177 }
178
179 int newFile =
180 ((this->CurrentBaseName == NULL) ||
181 strcmp(this->CurrentBaseName, this->BaseName));
182
183 if ( !newFile )
184 {
185 return 1;
186 }
187
188 if ( this->OpenCurrentFile() != 1 )
189 {
190 return 0;
191 }
192
193 // Get the dimension of the coordinates from the vertex file
194
195 int rc = this->InputGeom(1, 0, &x, &y, &z);
196
197 this->ResetInputBuffers();
198
199 if (rc)
200 {
201 // Get the number of vertices and edges, and number of
202 // vertex weights and edge weights from the graph file.
203
204 rc = this->InputGraph1();
205
206 this->ResetInputBuffers();
207
208 if (rc)
209 {
210 this->MakeWeightArrayNames(
211 this->NumberOfVertexWeights, this->NumberOfEdgeWeights);
212 }
213 }
214
215 // Close the file
216 this->CloseCurrentFile();
217
218 this->RemakeDataCacheFlag = 1;
219
220 return rc;
221 }
222
223 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)224 int vtkChacoReader::RequestData(
225 vtkInformation *vtkNotUsed(request),
226 vtkInformationVector **vtkNotUsed(inputVector),
227 vtkInformationVector *outputVector)
228 {
229 if (!this->BaseName)
230 {
231 vtkErrorMacro(<< "No BaseName specified");
232 return 0;
233 }
234
235 vtkInformation* outInfo = outputVector->GetInformationObject(0);
236
237 vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
238 outInfo->Get(vtkDataObject::DATA_OBJECT()));
239
240 int retVal = this->BuildOutputGrid(output);
241
242 return retVal;
243 }
244
245 //----------------------------------------------------------------------------
BuildOutputGrid(vtkUnstructuredGrid * output)246 int vtkChacoReader::BuildOutputGrid(vtkUnstructuredGrid *output)
247 {
248 int i=0;
249 if ( this->OpenCurrentFile() != 1 )
250 {
251 vtkWarningMacro(<< "Can't open file");
252 return 0;
253 }
254
255 int ncells = this->DataCache->GetNumberOfCells();
256 int haveVertexWeightArrays = 0;
257 int haveEdgeWeightArrays = 0;
258
259 if (ncells && (this->NumberOfVertexWeights > 0))
260 {
261 vtkDoubleArray *da = vtkDoubleArray::SafeDownCast(
262 this->DataCache->GetPointData()->GetArray(this->VarrayName[0]));
263
264 haveVertexWeightArrays = (da != NULL);
265 }
266
267 if (ncells && (this->NumberOfEdgeWeights > 0))
268 {
269 vtkDoubleArray *da = vtkDoubleArray::SafeDownCast(
270 this->DataCache->GetCellData()->GetArray(this->EarrayName[0]));
271
272 haveEdgeWeightArrays = (da != NULL);
273 }
274
275 if (!this->RemakeDataCacheFlag &&
276 ((!haveVertexWeightArrays && this->GenerateVertexWeightArrays) ||
277 (!haveEdgeWeightArrays && this->GenerateEdgeWeightArrays)))
278 {
279 this->RemakeDataCacheFlag = 1;
280 }
281
282 if (this->RemakeDataCacheFlag)
283 {
284 output->Initialize();
285 int rc = this->ReadFile(output);
286
287 if (rc == 0)
288 {
289 this->CloseCurrentFile();
290 return 0;
291 }
292
293 if (this->GenerateGlobalElementIdArray)
294 {
295 this->AddElementIds(output);
296 }
297
298 if (this->GenerateGlobalNodeIdArray)
299 {
300 this->AddNodeIds(output);
301 }
302
303 // Save the output. Next time we execute, it may be simply
304 // because they turned off vertex or edge weights, or decided they
305 // do or do not want element or point IDs. For these we can just
306 // modify the DataCache, rather than reading in the whole file
307 // and creating a vtkUnstructuredGrid from it.
308
309 this->DataCache->Initialize();
310 this->DataCache->ShallowCopy(output);
311
312 this->RemakeDataCacheFlag = 0;
313 }
314 else
315 {
316 // Just copy the output we calculated last time, after checking
317 // to see if any parameters have changed
318
319 if (haveVertexWeightArrays && !this->GenerateVertexWeightArrays)
320 {
321 for (i=0; i<this->NumberOfVertexWeights; i++)
322 {
323 this->DataCache->GetPointData()->RemoveArray(this->VarrayName[i]);
324 }
325
326 this->NumberOfPointWeightArrays = 0;
327 }
328
329 if (haveEdgeWeightArrays && !this->GenerateEdgeWeightArrays)
330 {
331 for (i=0; i<this->NumberOfEdgeWeights; i++)
332 {
333 this->DataCache->GetCellData()->RemoveArray(this->EarrayName[i]);
334 }
335
336 this->NumberOfCellWeightArrays = 0;
337 }
338
339 vtkIntArray *ia = vtkIntArray::SafeDownCast(
340 this->DataCache->GetCellData()->GetArray(this->GetGlobalElementIdArrayName()));
341
342 if (!ia && this->GenerateGlobalElementIdArray)
343 {
344 this->AddElementIds(this->DataCache);
345 }
346 else if (ia && !this->GenerateGlobalElementIdArray)
347 {
348 this->DataCache->GetCellData()->RemoveArray(this->GetGlobalElementIdArrayName());
349 }
350
351 ia = vtkIntArray::SafeDownCast(
352 this->DataCache->GetPointData()->GetArray(this->GetGlobalNodeIdArrayName()));
353
354 if (!ia && this->GenerateGlobalNodeIdArray)
355 {
356 this->AddNodeIds(this->DataCache);
357 }
358 else if (ia && !this->GenerateGlobalNodeIdArray)
359 {
360 this->DataCache->GetPointData()->RemoveArray(this->GetGlobalNodeIdArrayName());
361 }
362
363 output->ShallowCopy(this->DataCache);
364 }
365
366 // This just makes sure the arrays are the same size as the number
367 // of nodes or cell
368 output->CheckAttributes();
369
370 // We may have some mem that can be condensed
371 output->Squeeze();
372
373 this->CloseCurrentFile();
374
375 return 1;
376 }
377
378 //----------------------------------------------------------------------------
ReadFile(vtkUnstructuredGrid * output)379 int vtkChacoReader::ReadFile(vtkUnstructuredGrid* output)
380 {
381 int i=0;
382 vtkIdType id=0;
383
384 // Reset the entire unstructured grid
385 output->Reset();
386
387 this->NumberOfPointWeightArrays = 0;
388 this->NumberOfCellWeightArrays = 0;
389
390 // Read in the points. Maintain the order in the original file.
391 // The order indicates the global node ID.
392
393 vtkPoints *ptarray = vtkPoints::New();
394 ptarray->SetNumberOfPoints(this->NumberOfVertices);
395 ptarray->SetDataTypeToDouble();
396
397 int memoryOK = 1;
398
399 double *x = new double [this->NumberOfVertices];
400 double *y = NULL;
401 double *z = NULL;
402
403 if (!x)
404 {
405 memoryOK = 0;
406 }
407 else if (this->Dimensionality > 1)
408 {
409 y = new double [this->NumberOfVertices];
410 if (!y)
411 {
412 memoryOK = 0;
413 }
414 else if (this->Dimensionality > 2)
415 {
416 z = new double [this->NumberOfVertices];
417 if (!z)
418 {
419 memoryOK = 0;
420 }
421 }
422 }
423
424 if (!memoryOK)
425 {
426 vtkErrorMacro(<< "ReadFile memory allocation failure");
427 delete [] x;
428 delete [] y;
429 return 0;
430 }
431
432 int rc = this->InputGeom(this->NumberOfVertices, this->Dimensionality, x, y, z);
433
434 this->ResetInputBuffers();
435
436 if (rc == 0)
437 {
438 delete [] x;
439 delete [] y;
440 delete [] z;
441 return 0;
442 }
443
444 if (this->Dimensionality == 3)
445 {
446 for (id=0; id<this->NumberOfVertices; id++)
447 {
448 ptarray->InsertNextPoint(x[id], y[id], z[id]);
449 }
450 }
451 else if (this->Dimensionality == 2)
452 {
453 for (id=0; id<this->NumberOfVertices; id++)
454 {
455 ptarray->InsertNextPoint(x[id], y[id], 0.0);
456 }
457 }
458 else if (this->Dimensionality == 1)
459 {
460 for (id=0; id<this->NumberOfVertices; id++)
461 {
462 ptarray->InsertNextPoint(x[id], 0.0, 0.0);
463 }
464 }
465
466 output->SetPoints(ptarray);
467
468 delete [] x;
469 delete [] y;
470 delete [] z;
471 ptarray->Delete();
472
473 // Read in cell topology and possibly cell and point weights.
474 // (The unstructured grid "cells" are the Chaco "edges".)
475 //
476 // Note: The order in which point and cell arrays appear in the
477 // output must be fixed. This is because this reader is called
478 // by vtkPChacoReader, and all processes must create output
479 // ugrids with the cell arrays and point arrays in the same
480 // order. The order we choose for point arrays is:
481 // vertex weight arrays, if any, in order they appear in file
482 // global point IDs, if any
483 //
484 // The order for cell arrays is:
485 // edge weight arrays, if any, in order they appear in file
486 // global element IDs, if any
487
488 int retVal = 1;
489
490 vtkIdType *idx = NULL;
491 vtkIdType *nbors = NULL;
492 double *vweights = NULL;
493 double *eweights = NULL;
494
495 double **vw = NULL;
496 double **ew = NULL;
497
498 if (this->GetGenerateVertexWeightArrays() && (this->NumberOfVertexWeights > 0))
499 {
500 vw = &vweights;
501 }
502
503 if (this->GetGenerateEdgeWeightArrays() && (this->NumberOfEdgeWeights > 0))
504 {
505 ew = &eweights;
506 }
507
508 rc = this->InputGraph2(&idx, &nbors, vw, ew);
509
510 this->ResetInputBuffers();
511
512 if (rc == 0)
513 {
514 return 0;
515 }
516
517 vtkDoubleArray **varrays = NULL;
518 vtkDoubleArray **earrays = NULL;
519 double *vwgt = NULL;
520 double *ewgt = NULL;
521
522 if (vw)
523 {
524 varrays = new vtkDoubleArray * [this->NumberOfVertexWeights];
525 for (i=0; i<this->NumberOfVertexWeights; i++)
526 {
527 varrays[i] = vtkDoubleArray::New();
528 varrays[i]->SetNumberOfValues(this->NumberOfVertices);
529 varrays[i]->SetName(this->VarrayName[i]);
530 }
531 vwgt = vweights;
532 }
533
534 if (ew)
535 {
536 earrays = new vtkDoubleArray * [this->NumberOfEdgeWeights];
537 for (i=0; i<this->NumberOfEdgeWeights; i++)
538 {
539 earrays[i] = vtkDoubleArray::New();
540 earrays[i]->SetNumberOfValues(this->NumberOfEdges);
541 earrays[i]->SetName(this->EarrayName[i]);
542 }
543 ewgt = eweights;
544 }
545
546 vtkIdTypeArray *ca = vtkIdTypeArray::New();
547
548 if (idx == NULL)
549 {
550 // Special case: there are no edges in this graph. Every
551 // vertex will be a cell.
552
553 ca->SetNumberOfValues(2*this->NumberOfVertices);
554 vtkIdType *captr = ca->GetPointer(0);
555
556 for (id=0; id<this->NumberOfVertices; id++)
557 {
558 *captr++ = 1; // number of vertices in cell
559 *captr++ = id; // internal ID of vertex
560
561 if (vw)
562 {
563 for (int w=0; w<this->NumberOfVertexWeights; w++)
564 {
565 varrays[w]->SetValue(id, *vwgt++);
566 }
567 }
568 }
569 vtkCellArray *cells = vtkCellArray::New();
570 cells->SetCells(this->NumberOfVertices, ca);
571 output->SetCells(VTK_VERTEX, cells);
572 cells->Delete();
573 }
574 else
575 {
576 // The usual case: most or all vertices are connected to
577 // other vertices.
578
579 ca->SetNumberOfValues(3 * this->NumberOfEdges);
580 vtkIdType *captr = ca->GetPointer(0);
581
582 vtkIdType edgeNum = -1;
583
584 for (id=0; id < this->NumberOfVertices; id++)
585 {
586 // Each edge in the Chaco file is listed twice, for each
587 // vertex. We only save the edge once.
588
589 for (int n=idx[id]; n < idx[id+1]; n++)
590 {
591 vtkIdType nbor = nbors[n] - 1; // internal id
592
593 // Save each edge connected to this vertex, if it hasn't
594 // been saved already.
595
596 if (nbor > id)
597 {
598 edgeNum++;
599
600 if (edgeNum == this->NumberOfEdges)
601 {
602 vtkErrorMacro(<< "Too many edges in Chaco file");
603 retVal = 0;
604 break;
605 }
606
607 *captr++ = 2; // size of cell
608 *captr++ = id; // first vertex
609 *captr++ = nbor; // second vertex
610
611 if (ew)
612 {
613 // Save the edge weights associated with this edge
614
615 for (i=0; i<this->NumberOfEdgeWeights; i++)
616 {
617 earrays[i]->SetValue(edgeNum, *ewgt++);
618 }
619 }
620 }
621 else if (ew)
622 {
623 ewgt += this->NumberOfEdgeWeights; // Skip duplicate edge weights
624 }
625 }
626
627 if (!retVal) break;
628
629 // Save the weights associated with this vertex
630
631 if (vw)
632 {
633 for (i=0; i<this->NumberOfVertexWeights; i++)
634 {
635 varrays[i]->SetValue(id, *vwgt++);
636 }
637 }
638 }
639
640 if (edgeNum != this->NumberOfEdges - 1)
641 {
642 vtkErrorMacro(<< "Too few edges in Chaco file");
643 retVal = 0;
644 }
645
646 delete [] idx;
647 delete [] nbors;
648
649 if (retVal)
650 {
651 vtkCellArray *cells = vtkCellArray::New();
652 cells->SetCells(this->NumberOfEdges, ca);
653 output->SetCells(VTK_LINE, cells);
654 cells->Delete();
655 }
656 else
657 {
658 output->Initialize();
659 }
660 }
661
662 ca->Delete();
663
664 if (retVal == 1)
665 {
666 this->NumberOfPointWeightArrays = this->NumberOfVertexWeights;
667 this->NumberOfCellWeightArrays = this->NumberOfEdgeWeights;
668 }
669
670 if (vw)
671 {
672 delete [] vweights;
673 for (i=0; i<this->NumberOfVertexWeights; i++)
674 {
675 if (retVal)
676 {
677 output->GetPointData()->AddArray(varrays[i]);
678 }
679 varrays[i]->Delete();
680 }
681
682 delete [] varrays;
683 }
684
685 if (ew)
686 {
687 delete [] eweights;
688 for (i=0; i<this->NumberOfEdgeWeights; i++)
689 {
690 if (retVal)
691 {
692 output->GetCellData()->AddArray(earrays[i]);
693 }
694 earrays[i]->Delete();
695 }
696
697 delete [] earrays;
698 }
699
700 if (retVal)
701 {
702 output->Squeeze();
703 }
704
705 return retVal;
706 }
707 //----------------------------------------------------------------------------
AddElementIds(vtkUnstructuredGrid * output)708 void vtkChacoReader::AddElementIds(vtkUnstructuredGrid* output)
709 {
710 // We arbitrarily assign the element ids, since Chaco files do
711 // not have the notion of Element IDs.
712
713 vtkIdType len = output->GetNumberOfCells();
714
715 vtkIntArray *ia = vtkIntArray::New();
716 ia->SetName(this->GetGlobalElementIdArrayName());
717 ia->SetNumberOfValues(len);
718
719 for (vtkIdType i=0; i<len; i++)
720 {
721 ia->SetValue(i, i+1);
722 }
723
724 output->GetCellData()->AddArray(ia);
725 ia->Delete();
726 }
727
728 //----------------------------------------------------------------------------
AddNodeIds(vtkUnstructuredGrid * output)729 void vtkChacoReader::AddNodeIds(vtkUnstructuredGrid* output)
730 {
731 // The vertex IDs in a Chaco file begin at 1 for the first
732 // vertex in the .coords file, and increase by 1 thereafter.
733
734 vtkIdType len = output->GetNumberOfPoints();
735
736 vtkIntArray *ia = vtkIntArray::New();
737 ia->SetName(this->GetGlobalNodeIdArrayName());
738 ia->SetNumberOfValues(len);
739
740 for (vtkIdType i=0; i<len; i++)
741 {
742 ia->SetValue(i, i+1);
743 }
744
745 output->GetPointData()->AddArray(ia);
746 ia->Delete();
747 }
748
749 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)750 void vtkChacoReader::PrintSelf(ostream& os, vtkIndent indent)
751 {
752 int i=0;
753 this->Superclass::PrintSelf(os,indent);
754
755 if (this->GenerateGlobalElementIdArray)
756 {
757 os << indent << "GenerateGlobalElementIdArray: On\n";
758 }
759 else
760 {
761 os << indent << "GenerateGlobalElementIdArray: Off\n";
762 }
763
764 if (this->GenerateGlobalNodeIdArray)
765 {
766 os << indent << "GenerateGlobalNodeIdArray: On\n";
767 }
768 else
769 {
770 os << indent << "GenerateGlobalNodeIdArray: Off\n";
771 }
772
773 if (this->GenerateVertexWeightArrays)
774 {
775 os << indent << "GenerateVertexWeightArrays: On\n";
776 }
777 else
778 {
779 os << indent << "GenerateVertexWeightArrays: Off\n";
780 }
781
782 if (this->GenerateEdgeWeightArrays)
783 {
784 os << indent << "GenerateEdgeWeightArrays: On\n";
785 }
786 else
787 {
788 os << indent << "GenerateEdgeWeightArrays: Off\n";
789 }
790
791 os << indent << "Base Name: "
792 << (this->BaseName ? this->BaseName : "(none)") << "\n";
793 os << indent << "Dimensionality: " << this->Dimensionality << "\n";
794 os << indent << "NumberOfVertices: " << this->NumberOfVertices << "\n";
795 os << indent << "NumberOfEdges: " << this->NumberOfEdges << "\n";
796 os << indent << "NumberOfVertexWeights: " << this->NumberOfVertexWeights<< "\n";
797 os << indent << "NumberOfEdgeWeights: " << this->NumberOfEdgeWeights<< "\n";
798 os << indent << "NumberOfPointWeightArrays: " << this->NumberOfPointWeightArrays<< "\n";
799 os << indent << "NumberOfCellWeightArrays: " << this->NumberOfCellWeightArrays<< "\n";
800
801 for (i=1; i<=this->NumberOfPointWeightArrays; i++)
802 {
803 cout << "vertex weight array name: " << this->GetVertexWeightArrayName(i) << endl;;
804 }
805
806 for (i=1; i<=this->NumberOfCellWeightArrays; i++)
807 {
808 cout << "edge weight array name: " << this->GetEdgeWeightArrayName(i) << endl;;
809 }
810 }
811
812 //----------------------------------------------------------------------------
CloseCurrentFile()813 void vtkChacoReader::CloseCurrentFile()
814 {
815 if (this->CurrentGeometryFP)
816 {
817 fclose(this->CurrentGeometryFP);
818 fclose(this->CurrentGraphFP);
819 this->CurrentGeometryFP = NULL;
820 this->CurrentGraphFP = NULL;
821 }
822 }
823
824 //----------------------------------------------------------------------------
OpenCurrentFile()825 int vtkChacoReader::OpenCurrentFile()
826 {
827 int result = 0;
828
829 if ( this->CurrentGeometryFP == NULL)
830 {
831 int len = static_cast<int>(strlen(this->BaseName));
832 char *buf = new char [len+64];
833 sprintf(buf, "%s.coords", this->BaseName);
834
835 this->CurrentGeometryFP = fopen(buf, "r");
836
837 if (this->CurrentGeometryFP == NULL)
838 {
839 vtkErrorMacro(<< "Problem opening " << buf);
840 this->SetCurrentBaseName( NULL );
841 }
842 else
843 {
844 sprintf(buf, "%s.graph", this->BaseName);
845
846 this->CurrentGraphFP = fopen(buf, "r");
847
848 if (this->CurrentGraphFP == NULL)
849 {
850 vtkErrorMacro(<< "Problem opening " << buf);
851 this->SetCurrentBaseName( NULL );
852 fclose(this->CurrentGeometryFP);
853 this->CurrentGeometryFP = NULL;
854 }
855 else {
856 this->SetCurrentBaseName( this->GetBaseName() );
857 result = 1;
858 }
859 }
860 delete [] buf;
861 }
862
863 return result;
864 }
865
866 //----------------------------------------------------------------------------
867 // Code to read Chaco files.
868 // This software was developed by Bruce Hendrickson and Robert Leland
869 // at Sandia National Laboratories under US Department of Energy
870 // contract DE-AC04-76DP00789 and is copyrighted by Sandia Corporation.
871
ResetInputBuffers()872 void vtkChacoReader::ResetInputBuffers()
873 {
874 this->Line_length = 200;
875 this->Offset = 0;
876 this->Break_pnt = 200;
877 this->Save_pnt = 0;
878 }
879
880 //----------------------------------------------------------------------------
InputGeom(vtkIdType nvtxs,int igeom,double * x,double * y,double * z)881 int vtkChacoReader::InputGeom(
882 vtkIdType nvtxs, // Number of vertices to read in
883 int igeom, // Dimension (1, 2 or 3), or 0 if you don't know
884 double *x, double *y, double *z)
885 {
886 double xc=0.0, yc=0.0, zc=0.0;
887 int line_num, end_flag, ndims, i=0;
888
889 rewind(this->CurrentGeometryFP);
890
891 line_num = 0;
892 end_flag = 1;
893 while (end_flag == 1) {
894 xc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
895 ++line_num;
896 }
897
898 if (end_flag == -1) {
899 vtkErrorMacro(<<"No values found in geometry file "<< this->BaseName << ".coords");
900 return 0;
901 }
902
903 if (igeom == 0)
904 {
905 ndims = 1;
906 yc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
907 if (end_flag == 0)
908 {
909 ndims = 2;
910 zc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
911 if (end_flag == 0)
912 {
913 ndims = 3;
914 this->ReadVal(this->CurrentGeometryFP, &end_flag);
915 if (!end_flag)
916 {
917 vtkErrorMacro(<< "Invalid geometry file "<< this->BaseName << ".coords");
918 return 0;
919 }
920 }
921 }
922 this->Dimensionality = ndims;
923 }
924 else
925 {
926 ndims = this->Dimensionality;
927 if (ndims > 1)
928 {
929 yc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
930 if (ndims > 2)
931 {
932 zc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
933 }
934 }
935 this->ReadVal(this->CurrentGeometryFP, &end_flag);
936 }
937
938 x[0] = xc;
939 if (ndims > 1)
940 {
941 y[0] = yc;
942 if (ndims > 2)
943 {
944 z[0] = zc;
945 }
946 }
947
948 if (nvtxs == 1)
949 {
950 return 1;
951 }
952
953 for (int nread = 1; nread < nvtxs; nread++)
954 {
955 ++line_num;
956 if (ndims == 1)
957 {
958 i = fscanf(this->CurrentGeometryFP, "%lf", x + nread);
959 }
960 else if (ndims == 2)
961 {
962 i = fscanf(this->CurrentGeometryFP, "%lf%lf", x + nread, y + nread);
963 }
964 else if (ndims == 3)
965 {
966 i = fscanf(this->CurrentGeometryFP, "%lf%lf%lf", x+nread, y+nread, z+nread);
967 }
968
969 if (i == EOF)
970 {
971 vtkErrorMacro(<< "Too few lines in "<< this->BaseName << ".coords");
972 return 0;
973 }
974 else if (i != ndims)
975 {
976 vtkErrorMacro(<< "Wrong dimension in "<< this->BaseName << ".coords");
977 return 0;
978 }
979 }
980
981 return 1;
982 }
983
984 //----------------------------------------------------------------------------
InputGraph1()985 int vtkChacoReader::InputGraph1()
986 {
987 /* Read first line of input (= nvtxs, narcs, option). */
988 /* The (decimal) digits of the option variable mean: 1's digit not zero => input
989 edge weights 10's digit not zero => input vertex weights 100's digit not zero
990 => include vertex numbers */
991
992 FILE *fin = this->CurrentGraphFP;
993 rewind(fin);
994
995 /* Read any leading comment lines */
996 int end_flag = 1;
997 vtkIdType numVertices = 0;
998
999 while (end_flag == 1) {
1000 numVertices = this->ReadInt(fin, &end_flag);
1001 }
1002 if (numVertices <= 0) {
1003 vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" );
1004 return 0;
1005 }
1006
1007 this->NumberOfVertices = numVertices;
1008
1009 this->NumberOfEdges = this->ReadInt(fin, &end_flag);
1010 if (this->NumberOfEdges < 0) {
1011 vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" );
1012 return 0;
1013 }
1014
1015 this->NumberOfVertexWeights = 0;
1016 this->NumberOfEdgeWeights = 0;
1017 this->GraphFileHasVertexNumbers = 0;
1018
1019 /* Check if vertex or edge weights are used */
1020 if (!end_flag) {
1021 vtkIdType option = this->ReadInt(fin, &end_flag);
1022 this->NumberOfEdgeWeights = (int)(option - 10 * (option / 10));
1023 option /= 10;
1024 this->NumberOfVertexWeights = (int)(option - 10 * (option / 10));
1025 option /= 10;
1026 this->GraphFileHasVertexNumbers = (int)(option - 10 * (option / 10));
1027 }
1028
1029 /* Read weight dimensions if they are specified separately */
1030 if (!end_flag && this->NumberOfVertexWeights == 1){
1031 vtkIdType j = this->ReadInt(fin, &end_flag);
1032 if (!end_flag) this->NumberOfVertexWeights = (int)j;
1033 }
1034 if (!end_flag && this->NumberOfEdgeWeights == 1){
1035 vtkIdType j = this->ReadInt(fin, &end_flag);
1036 if (!end_flag) this->NumberOfEdgeWeights = (int)j;
1037 }
1038
1039 return 1;
1040 }
1041
1042 //----------------------------------------------------------------------------
InputGraph2(vtkIdType ** start,vtkIdType ** adjacency,double ** vweights,double ** eweights)1043 int vtkChacoReader::InputGraph2(
1044 vtkIdType **start, // start[i]: location of vertex i in adjacency array
1045 vtkIdType **adjacency, // by vertex by vertex neighbor
1046 double **vweights, // by vertex by weight (or NULL if no weights wanted)
1047 double **eweights ) // edge weights in order in file (or NULL)
1048 {
1049 vtkIdType *adjptr;
1050 double *ewptr;
1051 vtkIdType vtx, sum_edges, vertex, new_vertex;
1052 double weight, eweight;
1053 vtkIdType neighbor, j;
1054 int retVal = 1;
1055
1056 vtkIdType nvtxs = this->NumberOfVertices;
1057 vtkIdType narcs = this->NumberOfEdges;
1058 int vwgt_dim = this->NumberOfVertexWeights;
1059 int ewgt_dim = this->NumberOfEdgeWeights;
1060 int vtxnums = this->GraphFileHasVertexNumbers;
1061
1062 if (nvtxs < 1)
1063 {
1064 vtkErrorMacro(<< "vtkChacoReader::InputGraph2, NumberOfVertices not set");
1065 return 0;
1066 }
1067
1068 if (start == NULL)
1069 {
1070 vtkErrorMacro(<< "vtkChacoReader::InputGraph2, parameter list");
1071 return 0;
1072 }
1073
1074 *start = NULL;
1075 if (adjacency)
1076 {
1077 *adjacency = NULL;
1078 }
1079 if (vweights)
1080 {
1081 *vweights = NULL;
1082 }
1083 if (eweights)
1084 {
1085 *eweights = NULL;
1086 }
1087
1088 int line_num = 0;
1089
1090 FILE *fin = this->CurrentGraphFP;
1091 rewind(fin);
1092
1093 /* Read past the first line containing the metadata */
1094
1095 int end_flag = 1;
1096 while (end_flag == 1)
1097 {
1098 this->ReadInt(fin, &end_flag);
1099 ++line_num;
1100 }
1101 while (!end_flag)
1102 {
1103 this->ReadInt(fin, &end_flag);
1104 }
1105 ++line_num;
1106
1107 /* Allocate space for rows and columns. */
1108 *start = new vtkIdType [nvtxs + 1];
1109 if (adjacency && (narcs > 0))
1110 {
1111 *adjacency = new vtkIdType [2 * narcs + 1]; // why +1 ?
1112 }
1113 if (vweights && (vwgt_dim > 0))
1114 {
1115 *vweights = new double [nvtxs * vwgt_dim];
1116 }
1117
1118 if (eweights && (ewgt_dim > 0) && (narcs > 0))
1119 {
1120 *eweights = new double [(2 * narcs + 1) * ewgt_dim]; // why +1 ?
1121 }
1122
1123 adjptr = (adjacency ? *adjacency : NULL);
1124 ewptr = (eweights ? *eweights : NULL);
1125
1126 sum_edges = 0;
1127 (*start)[0] = 0;
1128 vertex = 0;
1129 vtx = 0;
1130 new_vertex = 1;
1131 while (((vwgt_dim > 0)|| vtxnums || narcs) && end_flag != -1)
1132 {
1133 ++line_num;
1134
1135 /* If multiple input lines per vertex, read vertex number. */
1136 if (vtxnums)
1137 {
1138 j = this->ReadInt(fin, &end_flag);
1139 if (end_flag)
1140 {
1141 if (vertex == nvtxs)
1142 {
1143 break;
1144 }
1145
1146 vtkErrorMacro(<<
1147 "Missing vertex number " << this->BaseName << ".graph, line " << line_num);
1148 retVal = 0;
1149 goto done;
1150 }
1151 if (j != vertex && j != vertex + 1)
1152 {
1153 vtkErrorMacro(<<
1154 "Out of order vertex " << this->BaseName << ".graph, line " << line_num);
1155 retVal = 0;
1156 goto done;
1157 }
1158 if (j != vertex)
1159 {
1160 new_vertex = 1;
1161 vertex = j;
1162 }
1163 else
1164 {
1165 new_vertex = 0;
1166 }
1167 }
1168 else
1169 {
1170 vertex = ++vtx;
1171 }
1172
1173 if (vertex > nvtxs)
1174 break;
1175
1176 /* If vertices are weighted, read vertex weight. */
1177 if ((vwgt_dim > 0) && new_vertex)
1178 {
1179 for (j=0; j<(vwgt_dim); j++)
1180 {
1181 weight = ReadVal(fin, &end_flag);
1182 if (end_flag)
1183 {
1184 vtkErrorMacro(<<
1185 "Vertex weights " << this->BaseName << ".graph, line " << line_num);
1186 retVal = 0;
1187 goto done;
1188 }
1189
1190 if (vweights)
1191 {
1192 (*vweights)[(vertex-1)*(vwgt_dim)+j] = weight;
1193 }
1194 }
1195 }
1196
1197 /* Read number of adjacent vertex. */
1198 neighbor = this->ReadInt(fin, &end_flag);
1199
1200 while (!end_flag)
1201 {
1202 if (ewgt_dim > 0)
1203 {
1204 for (j=0; j<ewgt_dim; j++)
1205 {
1206 eweight = ReadVal(fin, &end_flag);
1207
1208 if (end_flag)
1209 {
1210 vtkErrorMacro(<<
1211 "Edge weights " << this->BaseName << ".graph, line " << line_num);
1212 retVal = 0;
1213 goto done;
1214 }
1215
1216 if (ewptr)
1217 {
1218 *ewptr++ = eweight;
1219 }
1220 }
1221 }
1222
1223 /* Add edge to data structure. */
1224 if (++sum_edges > 2*narcs)
1225 {
1226 vtkErrorMacro(<<
1227 "Too many adjacencies " << this->BaseName << ".graph, line " << line_num);
1228 retVal = 0;
1229 goto done;
1230 }
1231
1232 if (adjptr)
1233 {
1234 *adjptr++ = neighbor;
1235 }
1236
1237 /* Read number of next adjacent vertex. */
1238 neighbor = this->ReadInt(fin, &end_flag);
1239 }
1240
1241 (*start)[vertex] = sum_edges;
1242 }
1243
1244 done:
1245
1246 if ((vertex == 0) || (retVal == 0))
1247 {
1248 /* Graph was empty */
1249 delete [] *start;
1250 *start = NULL;
1251 if (adjacency)
1252 {
1253 delete [] *adjacency;
1254 *adjacency = NULL;
1255 }
1256 if (vweights)
1257 {
1258 delete [] *vweights;
1259 *vweights = NULL;
1260 }
1261 if (eweights)
1262 {
1263 delete [] *eweights;
1264 *eweights = NULL;
1265 }
1266 }
1267
1268 return retVal;
1269 }
1270
1271 //----------------------------------------------------------------------------
ReadVal(FILE * infile,int * end_flag)1272 double vtkChacoReader::ReadVal( FILE *infile, int *end_flag )
1273 {
1274 double val;
1275 char *ptr;
1276 char *ptr2;
1277 int length;
1278 int length_left;
1279 int white_seen;
1280 int done;
1281 int i;
1282
1283 *end_flag = 0;
1284
1285 if (Offset == 0 ||this->Offset >= this->Break_pnt)
1286 {
1287 if (Offset >= this->Break_pnt)
1288 {
1289 length_left = this->Line_length - this->Save_pnt - 1;
1290 ptr2 = this->Line;
1291 ptr = &Line[Save_pnt];
1292 for (i=length_left; i; i--) *ptr2++ = *ptr++;
1293 length = this->Save_pnt + 1;
1294 }
1295 else
1296 {
1297 length = this->Line_length;
1298 length_left = 0;
1299 }
1300
1301 this->Line[this->Line_length - 1] = ' ';
1302 this->Line[this->Line_length - 2] = ' ';
1303 /* Now read next line, or next segment of current one. */
1304 ptr2 = fgets(&Line[length_left], length, infile);
1305
1306 if (ptr2 == (char *) NULL)
1307 {
1308 *end_flag = -1;
1309 return((double) 0.0);
1310 }
1311
1312 if (Line[this->Line_length - 1] == '\0' && this->Line[this->Line_length - 2] != '\0' &&
1313 this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f')
1314 {
1315 /* Line too long. Find last safe place in line. */
1316 this->Break_pnt = this->Line_length - 1;
1317 this->Save_pnt = this->Break_pnt;
1318 white_seen = 0;
1319 done = 0;
1320 while (!done)
1321 {
1322 --Break_pnt;
1323 if (Line[Break_pnt] != '\0')
1324 {
1325 if (isspace((int)(Line[Break_pnt])))
1326 {
1327 if (!white_seen)
1328 {
1329 this->Save_pnt = this->Break_pnt + 1;
1330 white_seen = 1;
1331 }
1332 }
1333 else if (white_seen)
1334 {
1335 done= 1;
1336 }
1337 }
1338 }
1339 }
1340 else
1341 {
1342 this->Break_pnt = this->Line_length;
1343 }
1344
1345 this->Offset = 0;
1346 }
1347
1348 while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++;
1349 if (Line[Offset] == '%' || this->Line[Offset] == '#')
1350 {
1351 *end_flag = 1;
1352 if (Break_pnt < this->Line_length)
1353 {
1354 FlushLine(infile);
1355 }
1356 return((double) 0.0);
1357 }
1358
1359 ptr = &(Line[Offset]);
1360 val = strtod(ptr, &ptr2);
1361
1362 if (ptr2 == ptr)
1363 {
1364 this->Offset = 0;
1365 *end_flag = 1;
1366 return((double) 0.0);
1367 }
1368 else
1369 {
1370 this->Offset = (int) (ptr2 - this->Line) / sizeof(char);
1371 }
1372
1373 return(val);
1374 }
1375
1376 //----------------------------------------------------------------------------
ReadInt(FILE * infile,int * end_flag)1377 vtkIdType vtkChacoReader::ReadInt(
1378 FILE *infile,
1379 int *end_flag
1380 )
1381 {
1382 vtkIdType val;
1383 char *ptr;
1384 char *ptr2;
1385 int length;
1386 int length_left;
1387 int white_seen;
1388 int done;
1389 int i;
1390
1391 *end_flag = 0;
1392
1393 if (Offset == 0 ||this->Offset >= this->Break_pnt)
1394 {
1395 if (Offset >= this->Break_pnt)
1396 {
1397 length_left = this->Line_length - this->Save_pnt - 1;
1398 ptr2 = this->Line;
1399 ptr = &Line[Save_pnt];
1400 for (i=length_left; i; i--) *ptr2++ = *ptr++;
1401 length = this->Save_pnt + 1;
1402 }
1403 else
1404 {
1405 length = this->Line_length;
1406 length_left = 0;
1407 }
1408
1409 this->Line[this->Line_length - 1] = ' ';
1410 this->Line[this->Line_length - 2] = ' ';
1411 /* Now read next line, or next segment of current one. */
1412 ptr2 = fgets(&Line[length_left], length, infile);
1413
1414 if (ptr2 == (char *) NULL)
1415 {
1416 *end_flag = -1;
1417 return(0);
1418 }
1419
1420 if (this->Line[this->Line_length - 1] == '\0' &&this->Line[this->Line_length - 2] != '\0' &&
1421 this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f')
1422 {
1423 /*Line too long. Find last safe place in line. */
1424 this->Break_pnt = this->Line_length - 1;
1425 this->Save_pnt = this->Break_pnt;
1426 white_seen = 0;
1427 done = 0;
1428 while (!done)
1429 {
1430 --Break_pnt;
1431 if (Line[Break_pnt] != '\0')
1432 {
1433 if (isspace((int)(Line[Break_pnt])))
1434 {
1435 if (!white_seen)
1436 {
1437 this->Save_pnt = this->Break_pnt + 1;
1438 white_seen = 1;
1439 }
1440 }
1441 else if (white_seen)
1442 {
1443 done= 1;
1444 }
1445 }
1446 }
1447 }
1448 else
1449 {
1450 this->Break_pnt = this->Line_length;
1451 }
1452
1453 this->Offset = 0;
1454 }
1455
1456 while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++;
1457 if (Line[Offset] == '%' || this->Line[Offset] == '#')
1458 {
1459 *end_flag = 1;
1460 if (Break_pnt < this->Line_length)
1461 {
1462 FlushLine(infile);
1463 }
1464 return(0);
1465 }
1466
1467 ptr = &(Line[Offset]);
1468 val = (int) strtol(ptr, &ptr2, 10);
1469
1470 if (ptr2 == ptr)
1471 {
1472 this->Offset = 0;
1473 *end_flag = 1;
1474 return(0);
1475 }
1476 else
1477 {
1478 this->Offset = (int) (ptr2 - this->Line) / sizeof(char);
1479 }
1480
1481 return(val);
1482 }
1483
1484 //----------------------------------------------------------------------------
FlushLine(FILE * infile)1485 void vtkChacoReader::FlushLine( FILE *infile)
1486 {
1487 char c;
1488
1489 c = getc(infile);
1490 while (c != '\n' && c != '\f')
1491 {
1492 c = getc(infile);
1493 }
1494 }
1495
1496