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