Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1480 lines
35 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkChacoReader.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/*----------------------------------------------------------------------------
Copyright (c) Sandia Corporation
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/
#include <stdio.h>
#include <ctype.h>
#include "vtkChacoReader.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkPointData.h"
#include "vtkDoubleArray.h"
#include "vtkInformation.h"
#include "vtkInformationDoubleVectorKey.h"
#include "vtkInformationVector.h"
#include "vtkIntArray.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnstructuredGrid.h"
vtkCxxRevisionMacro(vtkChacoReader, "$Revision: 1.9 $");
vtkStandardNewMacro(vtkChacoReader);
//----------------------------------------------------------------------------
// Description:
// Instantiate object with NULL filename.
vtkChacoReader::vtkChacoReader()
{
this->BaseName = NULL;
this->GenerateGlobalElementIdArray = 1;
this->GenerateGlobalNodeIdArray = 1;
this->GenerateVertexWeightArrays = 0;
this->GenerateEdgeWeightArrays = 0;
this->EarrayName = NULL;
this->VarrayName = NULL;
this->Dimensionality = -1;
this->NumberOfVertices = 0;
this->NumberOfEdges = 0;
this->NumberOfVertexWeights = 0;
this->NumberOfEdgeWeights = 0;
this->GraphFileHasVertexNumbers = 0;
this->NumberOfPointWeightArrays = 0;
this->NumberOfCellWeightArrays = 0;
this->CurrentGeometryFP = NULL;
this->CurrentGraphFP = NULL;
this->CurrentBaseName = NULL;
this->DataCache = vtkUnstructuredGrid::New();
this->RemakeDataCacheFlag = 1;
this->Line_length = 200;
this->Line = new char [200];
this->Offset = 0;
this->Break_pnt = 200;
this->Save_pnt = 0;
this->SetNumberOfInputPorts(0);
}
//----------------------------------------------------------------------------
vtkChacoReader::~vtkChacoReader()
{
this->SetBaseName(NULL);
this->SetCurrentBaseName(NULL);
this->ClearWeightArrayNames();
this->DataCache->Delete();
this->DataCache = NULL;
delete [] this->Line;
}
//----------------------------------------------------------------------------
void vtkChacoReader::ClearWeightArrayNames()
{
int i=0;
if (this->VarrayName)
{
for (i=0; i<this->NumberOfVertexWeights; i++)
{
delete [] this->VarrayName[i];
}
delete [] this->VarrayName;
this->VarrayName = NULL;
}
if (this->EarrayName)
{
for (i=0; i<this->NumberOfEdgeWeights; i++)
{
delete [] this->EarrayName[i];
}
delete [] this->EarrayName;
this->EarrayName = NULL;
}
}
void vtkChacoReader::MakeWeightArrayNames(int nv, int ne)
{
int i=0;
if (nv > 0)
{
this->VarrayName = new char *[nv];
for (i=0; i<nv; i++)
{
this->VarrayName[i] = new char [64];
sprintf(this->VarrayName[i], "VertexWeight%d", i+1);
}
}
if (ne > 0)
{
this->EarrayName = new char *[ne];
for (i=0; i<ne; i++)
{
this->EarrayName[i] = new char [64];
sprintf(this->EarrayName[i], "EdgeWeight%d", i+1);
}
}
}
char *vtkChacoReader::GetVertexWeightArrayName(int weight)
{
if (this->GetGenerateVertexWeightArrays() &&
(weight > 0) &&
(weight <= this->NumberOfVertexWeights))
{
return this->VarrayName[weight-1];
}
return NULL;
}
char *vtkChacoReader::GetEdgeWeightArrayName(int weight)
{
if (this->GetGenerateEdgeWeightArrays() &&
(weight > 0) &&
(weight <= this->NumberOfEdgeWeights))
{
return this->EarrayName[weight-1];
}
return NULL;
}
//----------------------------------------------------------------------------
int vtkChacoReader::RequestInformation(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *vtkNotUsed(outputVector))
{
double x, y, z;
if (!this->BaseName)
{
vtkErrorMacro(<< "No BaseName specified");
return 0;
}
int newFile =
((this->CurrentBaseName == NULL) ||
strcmp(this->CurrentBaseName, this->BaseName));
if ( !newFile )
{
return 1;
}
if ( this->OpenCurrentFile() != 1 )
{
return 0;
}
// Get the dimension of the coordinates from the vertex file
int rc = this->InputGeom(1, 0, &x, &y, &z);
this->ResetInputBuffers();
if (rc)
{
// Get the number of vertices and edges, and number of
// vertex weights and edge weights from the graph file.
rc = this->InputGraph1();
this->ResetInputBuffers();
if (rc)
{
this->MakeWeightArrayNames(
this->NumberOfVertexWeights, this->NumberOfEdgeWeights);
}
}
// Close the file
this->CloseCurrentFile();
this->RemakeDataCacheFlag = 1;
return rc;
}
//----------------------------------------------------------------------------
int vtkChacoReader::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *outputVector)
{
if (!this->BaseName)
{
vtkErrorMacro(<< "No BaseName specified");
return 0;
}
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
int retVal = this->BuildOutputGrid(output);
return retVal;
}
//----------------------------------------------------------------------------
int vtkChacoReader::BuildOutputGrid(vtkUnstructuredGrid *output)
{
int i=0;
if ( this->OpenCurrentFile() != 1 )
{
vtkWarningMacro(<< "Can't open file");
return 0;
}
int ncells = this->DataCache->GetNumberOfCells();
int haveVertexWeightArrays = 0;
int haveEdgeWeightArrays = 0;
if (ncells && (this->NumberOfVertexWeights > 0))
{
vtkDoubleArray *da = vtkDoubleArray::SafeDownCast(
this->DataCache->GetPointData()->GetArray(this->VarrayName[0]));
haveVertexWeightArrays = (da != NULL);
}
if (ncells && (this->NumberOfEdgeWeights > 0))
{
vtkDoubleArray *da = vtkDoubleArray::SafeDownCast(
this->DataCache->GetCellData()->GetArray(this->EarrayName[0]));
haveEdgeWeightArrays = (da != NULL);
}
if (!this->RemakeDataCacheFlag &&
((!haveVertexWeightArrays && this->GenerateVertexWeightArrays) ||
(!haveEdgeWeightArrays && this->GenerateEdgeWeightArrays)))
{
this->RemakeDataCacheFlag = 1;
}
if (this->RemakeDataCacheFlag)
{
output->Initialize();
int rc = this->ReadFile(output);
if (rc == 0)
{
this->CloseCurrentFile();
return 0;
}
if (this->GenerateGlobalElementIdArray)
{
this->AddElementIds(output);
}
if (this->GenerateGlobalNodeIdArray)
{
this->AddNodeIds(output);
}
// Save the output. Next time we execute, it may be simply
// because they turned off vertex or edge weights, or decided they
// do or do not want element or point IDs. For these we can just
// modify the DataCache, rather than reading in the whole file
// and creating a vtkUnstructuredGrid from it.
this->DataCache->Initialize();
this->DataCache->ShallowCopy(output);
this->RemakeDataCacheFlag = 0;
}
else
{
// Just copy the output we calculated last time, after checking
// to see if any parameters have changed
if (haveVertexWeightArrays && !this->GenerateVertexWeightArrays)
{
for (i=0; i<this->NumberOfVertexWeights; i++)
{
this->DataCache->GetPointData()->RemoveArray(this->VarrayName[i]);
}
this->NumberOfPointWeightArrays = 0;
}
if (haveEdgeWeightArrays && !this->GenerateEdgeWeightArrays)
{
for (i=0; i<this->NumberOfEdgeWeights; i++)
{
this->DataCache->GetCellData()->RemoveArray(this->EarrayName[i]);
}
this->NumberOfCellWeightArrays = 0;
}
vtkIntArray *ia = vtkIntArray::SafeDownCast(
this->DataCache->GetCellData()->GetArray(this->GetGlobalElementIdArrayName()));
if (!ia && this->GenerateGlobalElementIdArray)
{
this->AddElementIds(this->DataCache);
}
else if (ia && !this->GenerateGlobalElementIdArray)
{
this->DataCache->GetCellData()->RemoveArray(this->GetGlobalElementIdArrayName());
}
ia = vtkIntArray::SafeDownCast(
this->DataCache->GetPointData()->GetArray(this->GetGlobalNodeIdArrayName()));
if (!ia && this->GenerateGlobalNodeIdArray)
{
this->AddNodeIds(this->DataCache);
}
else if (ia && !this->GenerateGlobalNodeIdArray)
{
this->DataCache->GetPointData()->RemoveArray(this->GetGlobalNodeIdArrayName());
}
output->ShallowCopy(this->DataCache);
}
// This just makes sure the arrays are the same size as the number
// of nodes or cell
output->CheckAttributes();
// We may have some mem that can be condensed
output->Squeeze();
this->CloseCurrentFile();
return 1;
}
//----------------------------------------------------------------------------
int vtkChacoReader::ReadFile(vtkUnstructuredGrid* output)
{
int i=0;
vtkIdType id=0;
// Reset the entire unstructured grid
output->Reset();
this->NumberOfPointWeightArrays = 0;
this->NumberOfCellWeightArrays = 0;
// Read in the points. Maintain the order in the original file.
// The order indicates the global node ID.
vtkPoints *ptarray = vtkPoints::New();
ptarray->SetNumberOfPoints(this->NumberOfVertices);
ptarray->SetDataTypeToDouble();
int memoryOK = 1;
double *x = new double [this->NumberOfVertices];
double *y = NULL;
double *z = NULL;
if (!x)
{
memoryOK = 0;
}
else if (this->Dimensionality > 1)
{
y = new double [this->NumberOfVertices];
if (!y)
{
memoryOK = 0;
}
else if (this->Dimensionality > 2)
{
z = new double [this->NumberOfVertices];
if (!z)
{
memoryOK = 0;
}
}
}
if (!memoryOK)
{
vtkErrorMacro(<< "ReadFile memory allocation failure");
if (x) delete [] x;
if (y) delete [] y;
return 0;
}
int rc = this->InputGeom(this->NumberOfVertices, this->Dimensionality, x, y, z);
this->ResetInputBuffers();
if (rc == 0)
{
if (x) delete [] x;
if (y) delete [] y;
if (z) delete [] z;
return 0;
}
if (this->Dimensionality == 3)
{
for (id=0; id<this->NumberOfVertices; id++)
{
ptarray->InsertNextPoint(x[id], y[id], z[id]);
}
}
else if (this->Dimensionality == 2)
{
for (id=0; id<this->NumberOfVertices; id++)
{
ptarray->InsertNextPoint(x[id], y[id], 0.0);
}
}
else if (this->Dimensionality == 1)
{
for (id=0; id<this->NumberOfVertices; id++)
{
ptarray->InsertNextPoint(x[id], 0.0, 0.0);
}
}
output->SetPoints(ptarray);
if (x) delete [] x;
if (y) delete [] y;
if (z) delete [] z;
ptarray->Delete();
// Read in cell topology and possibly cell and point weights.
// (The unstructured grid "cells" are the Chaco "edges".)
//
// Note: The order in which point and cell arrays appear in the
// output must be fixed. This is because this reader is called
// by vtkPChacoReader, and all processes must create output
// ugrids with the cell arrays and point arrays in the same
// order. The order we choose for point arrays is:
// vertex weight arrays, if any, in order they appear in file
// global point IDs, if any
//
// The order for cell arrays is:
// edge weight arrays, if any, in order they appear in file
// global element IDs, if any
int retVal = 1;
vtkIdType *idx = NULL;
vtkIdType *nbors = NULL;
double *vweights = NULL;
double *eweights = NULL;
double **vw = NULL;
double **ew = NULL;
if (this->GetGenerateVertexWeightArrays() && (this->NumberOfVertexWeights > 0))
{
vw = &vweights;
}
if (this->GetGenerateEdgeWeightArrays() && (this->NumberOfEdgeWeights > 0))
{
ew = &eweights;
}
rc = this->InputGraph2(&idx, &nbors, vw, ew);
this->ResetInputBuffers();
if (rc == 0)
{
return 0;
}
vtkDoubleArray **varrays = NULL;
vtkDoubleArray **earrays = NULL;
double *vwgt = NULL;
double *ewgt = NULL;
if (vw)
{
varrays = new vtkDoubleArray * [this->NumberOfVertexWeights];
for (i=0; i<this->NumberOfVertexWeights; i++)
{
varrays[i] = vtkDoubleArray::New();
varrays[i]->SetNumberOfValues(this->NumberOfVertices);
varrays[i]->SetName(this->VarrayName[i]);
}
vwgt = vweights;
}
if (ew)
{
earrays = new vtkDoubleArray * [this->NumberOfEdgeWeights];
for (i=0; i<this->NumberOfEdgeWeights; i++)
{
earrays[i] = vtkDoubleArray::New();
earrays[i]->SetNumberOfValues(this->NumberOfEdges);
earrays[i]->SetName(this->EarrayName[i]);
}
ewgt = eweights;
}
vtkIdTypeArray *ca = vtkIdTypeArray::New();
if (idx == NULL)
{
// Special case: there are no edges in this graph. Every
// vertex will be a cell.
ca->SetNumberOfValues(2*this->NumberOfVertices);
vtkIdType *captr = ca->GetPointer(0);
for (id=0; id<this->NumberOfVertices; id++)
{
*captr++ = 1; // number of vertices in cell
*captr++ = id; // internal ID of vertex
if (vw)
{
for (int w=0; w<this->NumberOfVertexWeights; w++)
{
varrays[w]->SetValue(id, *vwgt++);
}
}
}
vtkCellArray *cells = vtkCellArray::New();
cells->SetCells(this->NumberOfVertices, ca);
output->SetCells(VTK_VERTEX, cells);
cells->Delete();
}
else
{
// The usual case: most or all vertices are connected to
// other vertices.
ca->SetNumberOfValues(3 * this->NumberOfEdges);
vtkIdType *captr = ca->GetPointer(0);
vtkIdType edgeNum = -1;
for (id=0; id < this->NumberOfVertices; id++)
{
// Each edge in the Chaco file is listed twice, for each
// vertex. We only save the edge once.
for (int n=idx[id]; n < idx[id+1]; n++)
{
vtkIdType nbor = nbors[n] - 1; // internal id
// Save each edge connected to this vertex, if it hasn't
// been saved already.
if (nbor > id)
{
edgeNum++;
if (edgeNum == this->NumberOfEdges)
{
vtkErrorMacro(<< "Too many edges in Chaco file");
retVal = 0;
break;
}
*captr++ = 2; // size of cell
*captr++ = id; // first vertex
*captr++ = nbor; // second vertex
if (ew)
{
// Save the edge weights associated with this edge
for (i=0; i<this->NumberOfEdgeWeights; i++)
{
earrays[i]->SetValue(edgeNum, *ewgt++);
}
}
}
else if (ew)
{
ewgt += this->NumberOfEdgeWeights; // Skip duplicate edge weights
}
}
if (!retVal) break;
// Save the weights associated with this vertex
if (vw)
{
for (i=0; i<this->NumberOfVertexWeights; i++)
{
varrays[i]->SetValue(id, *vwgt++);
}
}
}
if (edgeNum != this->NumberOfEdges - 1)
{
vtkErrorMacro(<< "Too few edges in Chaco file");
retVal = 0;
}
delete [] idx;
delete [] nbors;
if (retVal)
{
vtkCellArray *cells = vtkCellArray::New();
cells->SetCells(this->NumberOfEdges, ca);
output->SetCells(VTK_LINE, cells);
cells->Delete();
}
else
{
output->Initialize();
}
}
ca->Delete();
if (retVal == 1)
{
this->NumberOfPointWeightArrays = this->NumberOfVertexWeights;
this->NumberOfCellWeightArrays = this->NumberOfEdgeWeights;
}
if (vw)
{
delete [] vweights;
for (i=0; i<this->NumberOfVertexWeights; i++)
{
if (retVal)
{
output->GetPointData()->AddArray(varrays[i]);
}
varrays[i]->Delete();
}
delete [] varrays;
}
if (ew)
{
delete [] eweights;
for (i=0; i<this->NumberOfEdgeWeights; i++)
{
if (retVal)
{
output->GetCellData()->AddArray(earrays[i]);
}
earrays[i]->Delete();
}
delete [] earrays;
}
if (retVal)
{
output->Squeeze();
}
return retVal;
}
//----------------------------------------------------------------------------
void vtkChacoReader::AddElementIds(vtkUnstructuredGrid* output)
{
// We arbitrarily assign the element ids, since Chaco files do
// not have the notion of Element IDs.
vtkIdType len = output->GetNumberOfCells();
vtkIntArray *ia = vtkIntArray::New();
ia->SetName(this->GetGlobalElementIdArrayName());
ia->SetNumberOfValues(len);
for (vtkIdType i=0; i<len; i++)
{
ia->SetValue(i, i+1);
}
output->GetCellData()->AddArray(ia);
ia->Delete();
}
void vtkChacoReader::AddNodeIds(vtkUnstructuredGrid* output)
{
// The vertex IDs in a Chaco file begin at 1 for the first
// vertex in the .coords file, and increase by 1 thereafter.
vtkIdType len = output->GetNumberOfPoints();
vtkIntArray *ia = vtkIntArray::New();
ia->SetName(this->GetGlobalNodeIdArrayName());
ia->SetNumberOfValues(len);
for (vtkIdType i=0; i<len; i++)
{
ia->SetValue(i, i+1);
}
output->GetPointData()->AddArray(ia);
ia->Delete();
}
//----------------------------------------------------------------------------
void vtkChacoReader::PrintSelf(ostream& os, vtkIndent indent)
{
int i=0;
this->Superclass::PrintSelf(os,indent);
if (this->GenerateGlobalElementIdArray)
{
os << indent << "GenerateGlobalElementIdArray: On\n";
}
else
{
os << indent << "GenerateGlobalElementIdArray: Off\n";
}
if (this->GenerateGlobalNodeIdArray)
{
os << indent << "GenerateGlobalNodeIdArray: On\n";
}
else
{
os << indent << "GenerateGlobalNodeIdArray: Off\n";
}
if (this->GenerateVertexWeightArrays)
{
os << indent << "GenerateVertexWeightArrays: On\n";
}
else
{
os << indent << "GenerateVertexWeightArrays: Off\n";
}
if (this->GenerateEdgeWeightArrays)
{
os << indent << "GenerateEdgeWeightArrays: On\n";
}
else
{
os << indent << "GenerateEdgeWeightArrays: Off\n";
}
os << indent << "Base Name: "
<< (this->BaseName ? this->BaseName : "(none)") << "\n";
os << indent << "Dimensionality: " << this->Dimensionality << "\n";
os << indent << "NumberOfVertices: " << this->NumberOfVertices << "\n";
os << indent << "NumberOfEdges: " << this->NumberOfEdges << "\n";
os << indent << "NumberOfVertexWeights: " << this->NumberOfVertexWeights<< "\n";
os << indent << "NumberOfEdgeWeights: " << this->NumberOfEdgeWeights<< "\n";
os << indent << "NumberOfPointWeightArrays: " << this->NumberOfPointWeightArrays<< "\n";
os << indent << "NumberOfCellWeightArrays: " << this->NumberOfCellWeightArrays<< "\n";
for (i=1; i<=this->NumberOfPointWeightArrays; i++)
{
cout << "vertex weight array name: " << this->GetVertexWeightArrayName(i) << endl;;
}
for (i=1; i<=this->NumberOfCellWeightArrays; i++)
{
cout << "edge weight array name: " << this->GetEdgeWeightArrayName(i) << endl;;
}
}
void vtkChacoReader::CloseCurrentFile()
{
if (this->CurrentGeometryFP){
fclose(this->CurrentGeometryFP);
fclose(this->CurrentGraphFP);
this->CurrentGeometryFP = NULL;
this->CurrentGraphFP = NULL;
}
}
int vtkChacoReader::OpenCurrentFile()
{
int result = 0;
if ( this->CurrentGeometryFP == NULL)
{
int len = strlen(this->BaseName);
char *buf = new char [len+64];
sprintf(buf, "%s.coords", this->BaseName);
this->CurrentGeometryFP = fopen(buf, "r");
if (this->CurrentGeometryFP == NULL)
{
vtkErrorMacro(<< "Problem opening " << buf);
this->SetCurrentBaseName( NULL );
}
else
{
sprintf(buf, "%s.graph", this->BaseName);
this->CurrentGraphFP = fopen(buf, "r");
if (this->CurrentGraphFP == NULL)
{
vtkErrorMacro(<< "Problem opening " << buf);
this->SetCurrentBaseName( NULL );
fclose(this->CurrentGeometryFP);
this->CurrentGeometryFP = NULL;
}
else {
this->SetCurrentBaseName( this->GetBaseName() );
result = 1;
}
}
delete [] buf;
}
return result;
}
//----------------------------------------------------------------------------
// Code to read Chaco files.
// This software was developed by Bruce Hendrickson and Robert Leland
// at Sandia National Laboratories under US Department of Energy
// contract DE-AC04-76DP00789 and is copyrighted by Sandia Corporation.
void vtkChacoReader::ResetInputBuffers()
{
this->Line_length = 200;
this->Offset = 0;
this->Break_pnt = 200;
this->Save_pnt = 0;
}
int vtkChacoReader::InputGeom(
vtkIdType nvtxs, // Number of vertices to read in
int igeom, // Dimension (1, 2 or 3), or 0 if you don't know
double *x, double *y, double *z)
{
double xc=0.0, yc=0.0, zc=0.0;
int line_num, end_flag, ndims, i=0;
rewind(this->CurrentGeometryFP);
line_num = 0;
end_flag = 1;
while (end_flag == 1) {
xc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
++line_num;
}
if (end_flag == -1) {
vtkErrorMacro(<<"No values found in geometry file "<< this->BaseName << ".coords");
return 0;
}
if (igeom == 0)
{
ndims = 1;
yc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
if (end_flag == 0)
{
ndims = 2;
zc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
if (end_flag == 0)
{
ndims = 3;
this->ReadVal(this->CurrentGeometryFP, &end_flag);
if (!end_flag)
{
vtkErrorMacro(<< "Invalid geometry file "<< this->BaseName << ".coords");
return 0;
}
}
}
this->Dimensionality = ndims;
}
else
{
ndims = this->Dimensionality;
if (ndims > 1)
{
yc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
if (ndims > 2)
{
zc = this->ReadVal(this->CurrentGeometryFP, &end_flag);
}
}
this->ReadVal(this->CurrentGeometryFP, &end_flag);
}
x[0] = xc;
if (ndims > 1)
{
y[0] = yc;
if (ndims > 2)
{
z[0] = zc;
}
}
if (nvtxs == 1)
{
return 1;
}
for (int nread = 1; nread < nvtxs; nread++)
{
++line_num;
if (ndims == 1)
{
i = fscanf(this->CurrentGeometryFP, "%lf", x + nread);
}
else if (ndims == 2)
{
i = fscanf(this->CurrentGeometryFP, "%lf%lf", x + nread, y + nread);
}
else if (ndims == 3)
{
i = fscanf(this->CurrentGeometryFP, "%lf%lf%lf", x+nread, y+nread, z+nread);
}
if (i == EOF)
{
vtkErrorMacro(<< "Too few lines in "<< this->BaseName << ".coords");
return 0;
}
else if (i != ndims)
{
vtkErrorMacro(<< "Wrong dimension in "<< this->BaseName << ".coords");
return 0;
}
}
return 1;
}
int vtkChacoReader::InputGraph1()
{
/* Read first line of input (= nvtxs, narcs, option). */
/* The (decimal) digits of the option variable mean: 1's digit not zero => input
edge weights 10's digit not zero => input vertex weights 100's digit not zero
=> include vertex numbers */
FILE *fin = this->CurrentGraphFP;
rewind(fin);
/* Read any leading comment lines */
int end_flag = 1;
vtkIdType numVertices = 0;
while (end_flag == 1) {
numVertices = this->ReadInt(fin, &end_flag);
}
if (numVertices <= 0) {
vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" );
return 0;
}
this->NumberOfVertices = numVertices;
this->NumberOfEdges = this->ReadInt(fin, &end_flag);
if (this->NumberOfEdges < 0) {
vtkErrorMacro(<< "Invalid file " << this->BaseName << ".graph" );
return 0;
}
this->NumberOfVertexWeights = 0;
this->NumberOfEdgeWeights = 0;
this->GraphFileHasVertexNumbers = 0;
/* Check if vertex or edge weights are used */
if (!end_flag) {
vtkIdType option = this->ReadInt(fin, &end_flag);
this->NumberOfEdgeWeights = (int)(option - 10 * (option / 10));
option /= 10;
this->NumberOfVertexWeights = (int)(option - 10 * (option / 10));
option /= 10;
this->GraphFileHasVertexNumbers = (int)(option - 10 * (option / 10));
}
/* Read weight dimensions if they are specified separately */
if (!end_flag && this->NumberOfVertexWeights == 1){
vtkIdType j = this->ReadInt(fin, &end_flag);
if (!end_flag) this->NumberOfVertexWeights = (int)j;
}
if (!end_flag && this->NumberOfEdgeWeights == 1){
vtkIdType j = this->ReadInt(fin, &end_flag);
if (!end_flag) this->NumberOfEdgeWeights = (int)j;
}
return 1;
}
int vtkChacoReader::InputGraph2(
vtkIdType **start, // start[i]: location of vertex i in adjacency array
vtkIdType **adjacency, // by vertex by vertex neighbor
double **vweights, // by vertex by weight (or NULL if no weights wanted)
double **eweights ) // edge weights in order in file (or NULL)
{
vtkIdType *adjptr;
double *ewptr;
vtkIdType vtx, sum_edges, vertex, new_vertex;
double weight, eweight;
vtkIdType neighbor, j;
int retVal = 1;
vtkIdType nvtxs = this->NumberOfVertices;
vtkIdType narcs = this->NumberOfEdges;
int vwgt_dim = this->NumberOfVertexWeights;
int ewgt_dim = this->NumberOfEdgeWeights;
int vtxnums = this->GraphFileHasVertexNumbers;
if (nvtxs < 1)
{
vtkErrorMacro(<< "vtkChacoReader::InputGraph2, NumberOfVertices not set");
return 0;
}
if (start == NULL)
{
vtkErrorMacro(<< "vtkChacoReader::InputGraph2, parameter list");
return 0;
}
*start = NULL;
if (adjacency)
{
*adjacency = NULL;
}
if (vweights)
{
*vweights = NULL;
}
if (eweights)
{
*eweights = NULL;
}
int line_num = 0;
FILE *fin = this->CurrentGraphFP;
rewind(fin);
/* Read past the first line containing the metadata */
int end_flag = 1;
while (end_flag == 1)
{
j = this->ReadInt(fin, &end_flag);
++line_num;
}
while (!end_flag)
{
j = this->ReadInt(fin, &end_flag);
}
++line_num;
/* Allocate space for rows and columns. */
*start = new vtkIdType [nvtxs + 1];
if (adjacency && (narcs > 0))
{
*adjacency = new vtkIdType [2 * narcs + 1]; // why +1 ?
}
else
{
*adjacency = NULL;
}
if (vweights && (vwgt_dim > 0))
{
*vweights = new double [nvtxs * vwgt_dim];
}
if (eweights && (ewgt_dim > 0) && (narcs > 0))
{
*eweights = new double [(2 * narcs + 1) * ewgt_dim]; // why +1 ?
}
adjptr = (adjacency ? *adjacency : NULL);
ewptr = (eweights ? *eweights : NULL);
sum_edges = 0;
(*start)[0] = 0;
vertex = 0;
vtx = 0;
new_vertex = 1;
while (((vwgt_dim > 0)|| vtxnums || narcs) && end_flag != -1)
{
++line_num;
/* If multiple input lines per vertex, read vertex number. */
if (vtxnums)
{
j = this->ReadInt(fin, &end_flag);
if (end_flag)
{
if (vertex == nvtxs)
{
break;
}
vtkErrorMacro(<<
"Missing vertex number " << this->BaseName << ".graph, line " << line_num);
retVal = 0;
goto done;
}
if (j != vertex && j != vertex + 1)
{
vtkErrorMacro(<<
"Out of order vertex " << this->BaseName << ".graph, line " << line_num);
retVal = 0;
goto done;
}
if (j != vertex)
{
new_vertex = 1;
vertex = j;
}
else
{
new_vertex = 0;
}
}
else
{
vertex = ++vtx;
}
if (vertex > nvtxs)
break;
/* If vertices are weighted, read vertex weight. */
if ((vwgt_dim > 0) && new_vertex)
{
for (j=0; j<(vwgt_dim); j++)
{
weight = ReadVal(fin, &end_flag);
if (end_flag)
{
vtkErrorMacro(<<
"Vertex weights " << this->BaseName << ".graph, line " << line_num);
retVal = 0;
goto done;
}
if (vweights)
{
(*vweights)[(vertex-1)*(vwgt_dim)+j] = weight;
}
}
}
/* Read number of adjacent vertex. */
neighbor = this->ReadInt(fin, &end_flag);
while (!end_flag)
{
if (ewgt_dim > 0)
{
for (j=0; j<ewgt_dim; j++)
{
eweight = ReadVal(fin, &end_flag);
if (end_flag)
{
vtkErrorMacro(<<
"Edge weights " << this->BaseName << ".graph, line " << line_num);
retVal = 0;
goto done;
}
if (ewptr)
{
*ewptr++ = eweight;
}
}
}
/* Add edge to data structure. */
if (++sum_edges > 2*narcs)
{
vtkErrorMacro(<<
"Too many adjacencies " << this->BaseName << ".graph, line " << line_num);
retVal = 0;
goto done;
}
if (adjptr)
{
*adjptr++ = neighbor;
}
/* Read number of next adjacent vertex. */
neighbor = this->ReadInt(fin, &end_flag);
}
(*start)[vertex] = sum_edges;
}
done:
if ((vertex == 0) || (retVal == 0))
{
/* Graph was empty */
delete [] *start;
*start = NULL;
if (adjacency && (*adjacency != NULL))
{
delete [] *adjacency;
*adjacency = NULL;
}
if (vweights && (*vweights != NULL))
{
delete [] *vweights;
*vweights = NULL;
}
if (eweights && (*eweights != NULL))
{
delete [] *eweights;
*eweights = NULL;
}
}
return retVal;
}
double vtkChacoReader::ReadVal( FILE *infile, int *end_flag )
{
double val;
char *ptr;
char *ptr2;
int length;
int length_left;
int white_seen;
int done;
int i;
*end_flag = 0;
if (Offset == 0 ||this->Offset >= this->Break_pnt)
{
if (Offset >= this->Break_pnt)
{
length_left = this->Line_length - this->Save_pnt - 1;
ptr2 = this->Line;
ptr = &Line[Save_pnt];
for (i=length_left; i; i--) *ptr2++ = *ptr++;
length = this->Save_pnt + 1;
}
else
{
length = this->Line_length;
length_left = 0;
}
this->Line[this->Line_length - 1] = ' ';
this->Line[this->Line_length - 2] = ' ';
/* Now read next line, or next segment of current one. */
ptr2 = fgets(&Line[length_left], length, infile);
if (ptr2 == (char *) NULL)
{
*end_flag = -1;
return((double) 0.0);
}
if (Line[this->Line_length - 1] == '\0' && this->Line[this->Line_length - 2] != '\0' &&
this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f')
{
/* Line too long. Find last safe place in line. */
this->Break_pnt = this->Line_length - 1;
this->Save_pnt = this->Break_pnt;
white_seen = 0;
done = 0;
while (!done)
{
--Break_pnt;
if (Line[Break_pnt] != '\0')
{
if (isspace((int)(Line[Break_pnt])))
{
if (!white_seen)
{
this->Save_pnt = this->Break_pnt + 1;
white_seen = 1;
}
}
else if (white_seen)
{
done= 1;
}
}
}
}
else
{
this->Break_pnt = this->Line_length;
}
this->Offset = 0;
}
while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++;
if (Line[Offset] == '%' || this->Line[Offset] == '#')
{
*end_flag = 1;
if (Break_pnt < this->Line_length)
{
FlushLine(infile);
}
return((double) 0.0);
}
ptr = &(Line[Offset]);
val = strtod(ptr, &ptr2);
if (ptr2 == ptr)
{
this->Offset = 0;
*end_flag = 1;
return((double) 0.0);
}
else
{
this->Offset = (int) (ptr2 - this->Line) / sizeof(char);
}
return(val);
}
vtkIdType vtkChacoReader::ReadInt(
FILE *infile,
int *end_flag
)
{
vtkIdType val;
char *ptr;
char *ptr2;
int length;
int length_left;
int white_seen;
int done;
int i;
*end_flag = 0;
if (Offset == 0 ||this->Offset >= this->Break_pnt)
{
if (Offset >= this->Break_pnt)
{
length_left = this->Line_length - this->Save_pnt - 1;
ptr2 = this->Line;
ptr = &Line[Save_pnt];
for (i=length_left; i; i--) *ptr2++ = *ptr++;
length = this->Save_pnt + 1;
}
else
{
length = this->Line_length;
length_left = 0;
}
this->Line[this->Line_length - 1] = ' ';
this->Line[this->Line_length - 2] = ' ';
/* Now read next line, or next segment of current one. */
ptr2 = fgets(&Line[length_left], length, infile);
if (ptr2 == (char *) NULL)
{
*end_flag = -1;
return(0);
}
if (this->Line[this->Line_length - 1] == '\0' &&this->Line[this->Line_length - 2] != '\0' &&
this->Line[this->Line_length - 2] != '\n' && this->Line[this->Line_length - 2] != '\f')
{
/*Line too long. Find last safe place in line. */
this->Break_pnt = this->Line_length - 1;
this->Save_pnt = this->Break_pnt;
white_seen = 0;
done = 0;
while (!done)
{
--Break_pnt;
if (Line[Break_pnt] != '\0')
{
if (isspace((int)(Line[Break_pnt])))
{
if (!white_seen)
{
this->Save_pnt = this->Break_pnt + 1;
white_seen = 1;
}
}
else if (white_seen)
{
done= 1;
}
}
}
}
else
{
this->Break_pnt = this->Line_length;
}
this->Offset = 0;
}
while (isspace((int)(Line[Offset])) &&this->Offset < this->Line_length)this->Offset++;
if (Line[Offset] == '%' || this->Line[Offset] == '#')
{
*end_flag = 1;
if (Break_pnt < this->Line_length)
{
FlushLine(infile);
}
return(0);
}
ptr = &(Line[Offset]);
val = (int) strtol(ptr, &ptr2, 10);
if (ptr2 == ptr)
{
this->Offset = 0;
*end_flag = 1;
return(0);
}
else
{
this->Offset = (int) (ptr2 - this->Line) / sizeof(char);
}
return(val);
}
void vtkChacoReader::FlushLine( FILE *infile)
{
char c;
c = getc(infile);
while (c != '\n' && c != '\f')
{
c = getc(infile);
}
}