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.
594 lines
13 KiB
594 lines
13 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkEdgeTable.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.
|
||
|
|
||
|
=========================================================================*/
|
||
|
#include "vtkEdgeTable.h"
|
||
|
#include "vtkPoints.h"
|
||
|
#include "vtkIdList.h"
|
||
|
#include "vtkVoidArray.h"
|
||
|
#include "vtkObjectFactory.h"
|
||
|
|
||
|
vtkCxxRevisionMacro(vtkEdgeTable, "$Revision: 1.39 $");
|
||
|
vtkStandardNewMacro(vtkEdgeTable);
|
||
|
|
||
|
// Instantiate object based on maximum point id.
|
||
|
vtkEdgeTable::vtkEdgeTable()
|
||
|
{
|
||
|
this->Table = NULL;
|
||
|
this->Attributes = NULL;
|
||
|
this->PointerAttributes = NULL;
|
||
|
this->Points = NULL;
|
||
|
|
||
|
this->TableMaxId = -1;
|
||
|
this->TableSize = 0;
|
||
|
|
||
|
this->Position[0] = 0;
|
||
|
this->Position[1] = -1;
|
||
|
this->NumberOfEdges = 0;
|
||
|
}
|
||
|
|
||
|
// Free memory and return to instantiated state.
|
||
|
void vtkEdgeTable::Initialize()
|
||
|
{
|
||
|
vtkIdType i;
|
||
|
|
||
|
if ( this->Table )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->Table[i] )
|
||
|
{
|
||
|
this->Table[i]->Delete();
|
||
|
}
|
||
|
}
|
||
|
delete [] this->Table;
|
||
|
this->Table = NULL;
|
||
|
this->TableMaxId = -1;
|
||
|
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->Attributes[i] )
|
||
|
{
|
||
|
this->Attributes[i]->Delete();
|
||
|
}
|
||
|
}
|
||
|
delete [] this->Attributes;
|
||
|
this->Attributes = NULL;
|
||
|
}
|
||
|
else if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->PointerAttributes[i] )
|
||
|
{
|
||
|
this->PointerAttributes[i]->Delete();
|
||
|
}
|
||
|
}
|
||
|
delete [] this->PointerAttributes;
|
||
|
this->PointerAttributes = NULL;
|
||
|
}
|
||
|
}//if table defined
|
||
|
|
||
|
if ( this->Points )
|
||
|
{
|
||
|
this->Points->Delete();
|
||
|
this->Points = NULL;
|
||
|
}
|
||
|
|
||
|
this->TableSize = 0;
|
||
|
this->NumberOfEdges = 0;
|
||
|
}
|
||
|
|
||
|
// Free memory and return to instantiated state.
|
||
|
void vtkEdgeTable::Reset()
|
||
|
{
|
||
|
vtkIdType i;
|
||
|
|
||
|
if ( this->Table )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->Table[i] )
|
||
|
{
|
||
|
this->Table[i]->Reset();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( this->StoreAttributes == 1 && this->Attributes )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->Attributes[i] )
|
||
|
{
|
||
|
this->Attributes[i]->Reset();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if ( this->StoreAttributes == 2 && this->PointerAttributes )
|
||
|
{
|
||
|
for (i=0; i < this->TableSize; i++)
|
||
|
{
|
||
|
if ( this->PointerAttributes[i] )
|
||
|
{
|
||
|
this->PointerAttributes[i]->Reset();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}//if table defined
|
||
|
|
||
|
this->TableMaxId = -1;
|
||
|
|
||
|
if ( this->Points )
|
||
|
{
|
||
|
this->Points->Reset();
|
||
|
}
|
||
|
|
||
|
this->NumberOfEdges = 0;
|
||
|
}
|
||
|
|
||
|
vtkEdgeTable::~vtkEdgeTable()
|
||
|
{
|
||
|
this->Initialize();
|
||
|
}
|
||
|
|
||
|
int vtkEdgeTable::InitEdgeInsertion(vtkIdType numPoints, int storeAttributes)
|
||
|
{
|
||
|
vtkIdType i;
|
||
|
|
||
|
numPoints = (numPoints < 1 ? 1 : numPoints);
|
||
|
|
||
|
// Discard old memory if not enough has been previously allocated
|
||
|
this->StoreAttributes = storeAttributes;
|
||
|
this->TableMaxId = -1;
|
||
|
|
||
|
if ( numPoints > this->TableSize )
|
||
|
{
|
||
|
this->Initialize();
|
||
|
this->Table = new vtkIdList *[numPoints];
|
||
|
for (i=0; i < numPoints; i++)
|
||
|
{
|
||
|
this->Table[i] = NULL;
|
||
|
}
|
||
|
|
||
|
if (this->StoreAttributes == 1)
|
||
|
{
|
||
|
this->Attributes = new vtkIdList *[numPoints];
|
||
|
for (i=0; i < numPoints; i++)
|
||
|
{
|
||
|
this->Attributes[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
else if (this->StoreAttributes == 2)
|
||
|
{
|
||
|
this->PointerAttributes = new vtkVoidArray *[numPoints];
|
||
|
for (i=0; i < numPoints; i++)
|
||
|
{
|
||
|
this->PointerAttributes[i] = NULL;
|
||
|
}
|
||
|
}
|
||
|
this->TableSize = numPoints;
|
||
|
}
|
||
|
|
||
|
// Otherwise, reuse the old memory
|
||
|
else
|
||
|
{
|
||
|
this->Reset();
|
||
|
}
|
||
|
|
||
|
this->Position[0] = 0;
|
||
|
this->Position[1] = -1;
|
||
|
|
||
|
this->NumberOfEdges = 0;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Return non-negative if edge (p1,p2) is an edge; otherwise -1.
|
||
|
vtkIdType vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2)
|
||
|
{
|
||
|
vtkIdType index, search;
|
||
|
|
||
|
if ( p1 < p2 )
|
||
|
{
|
||
|
index = p1;
|
||
|
search = p2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = p2;
|
||
|
search = p1;
|
||
|
}
|
||
|
|
||
|
if ( this->Table[index] == NULL )
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vtkIdType loc;
|
||
|
if ( (loc=this->Table[index]->IsId(search)) == (-1) )
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
return this->Attributes[index]->GetId(loc);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return non-negative if edge (p1,p2) is an edge; otherwise -1.
|
||
|
void vtkEdgeTable::IsEdge(vtkIdType p1, vtkIdType p2, void* &ptr)
|
||
|
{
|
||
|
vtkIdType index, search;
|
||
|
|
||
|
if ( p1 < p2 )
|
||
|
{
|
||
|
index = p1;
|
||
|
search = p2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = p2;
|
||
|
search = p1;
|
||
|
}
|
||
|
|
||
|
if ( this->Table[index] == NULL )
|
||
|
{
|
||
|
ptr = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vtkIdType loc;
|
||
|
if ( (loc=this->Table[index]->IsId(search)) == (-1) )
|
||
|
{
|
||
|
ptr = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
ptr = this->PointerAttributes[index]->GetVoidPointer(loc);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ptr = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Insert the edge (p1,p2) into the table. It is the user's responsibility to
|
||
|
// check if the edge has already been inserted.
|
||
|
vtkIdType vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2)
|
||
|
{
|
||
|
vtkIdType index, search;
|
||
|
|
||
|
if ( p1 < p2 )
|
||
|
{
|
||
|
index = p1;
|
||
|
search = p2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = p2;
|
||
|
search = p1;
|
||
|
}
|
||
|
|
||
|
if ( index >= this->TableSize )
|
||
|
{
|
||
|
this->Resize(index+1);
|
||
|
}
|
||
|
|
||
|
if ( index > this->TableMaxId )
|
||
|
{
|
||
|
this->TableMaxId = index;
|
||
|
}
|
||
|
|
||
|
if ( this->Table[index] == NULL )
|
||
|
{
|
||
|
this->Table[index] = vtkIdList::New();
|
||
|
this->Table[index]->Allocate(6,12);
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
if ( this->Attributes[index] )
|
||
|
{
|
||
|
this->Attributes[index]->Delete();
|
||
|
}
|
||
|
this->Attributes[index] = vtkIdList::New();
|
||
|
this->Attributes[index]->Allocate(6,12);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->Table[index]->InsertNextId(search);
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
this->Attributes[index]->InsertNextId(this->NumberOfEdges);
|
||
|
}
|
||
|
this->NumberOfEdges++;
|
||
|
|
||
|
return (this->NumberOfEdges - 1);
|
||
|
}
|
||
|
|
||
|
void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2,
|
||
|
vtkIdType attributeId)
|
||
|
{
|
||
|
vtkIdType index, search;
|
||
|
|
||
|
if ( p1 < p2 )
|
||
|
{
|
||
|
index = p1;
|
||
|
search = p2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = p2;
|
||
|
search = p1;
|
||
|
}
|
||
|
|
||
|
if ( index >= this->TableSize )
|
||
|
{
|
||
|
this->Resize(index+1);
|
||
|
}
|
||
|
|
||
|
if ( index > this->TableMaxId )
|
||
|
{
|
||
|
this->TableMaxId = index;
|
||
|
}
|
||
|
|
||
|
if ( this->Table[index] == NULL )
|
||
|
{
|
||
|
this->Table[index] = vtkIdList::New();
|
||
|
this->Table[index]->Allocate(6,12);
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
this->Attributes[index] = vtkIdList::New();
|
||
|
this->Attributes[index]->Allocate(6,12);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->NumberOfEdges++;
|
||
|
this->Table[index]->InsertNextId(search);
|
||
|
if ( this->StoreAttributes )
|
||
|
{
|
||
|
this->Attributes[index]->InsertNextId(attributeId);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vtkEdgeTable::InsertEdge(vtkIdType p1, vtkIdType p2, void* ptr)
|
||
|
{
|
||
|
vtkIdType index, search;
|
||
|
|
||
|
if ( p1 < p2 )
|
||
|
{
|
||
|
index = p1;
|
||
|
search = p2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
index = p2;
|
||
|
search = p1;
|
||
|
}
|
||
|
|
||
|
if ( index >= this->TableSize )
|
||
|
{
|
||
|
this->Resize(index+1);
|
||
|
}
|
||
|
|
||
|
if ( index > this->TableMaxId )
|
||
|
{
|
||
|
this->TableMaxId = index;
|
||
|
}
|
||
|
|
||
|
if ( this->Table[index] == NULL )
|
||
|
{
|
||
|
this->Table[index] = vtkIdList::New();
|
||
|
this->Table[index]->Allocate(6,12);
|
||
|
if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
this->PointerAttributes[index] = vtkVoidArray::New();
|
||
|
this->PointerAttributes[index]->Allocate(6,12);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->NumberOfEdges++;
|
||
|
this->Table[index]->InsertNextId(search);
|
||
|
if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
this->PointerAttributes[index]->InsertNextVoidPointer(ptr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Intialize traversal of edges in table.
|
||
|
void vtkEdgeTable::InitTraversal()
|
||
|
{
|
||
|
this->Position[0] = 0;
|
||
|
this->Position[1] = -1;
|
||
|
}
|
||
|
|
||
|
// Traverse list of edges in table. Return the edge as (p1,p2), where p1 and
|
||
|
// p2 are point id's. Method return value is <0 if the list is exhausted;
|
||
|
// otherwise a valid id >=0. The value of p1 is guaranteed to be <= p2. The
|
||
|
// return value is an id that can be used for accessing attributes.
|
||
|
vtkIdType vtkEdgeTable::GetNextEdge(vtkIdType &p1, vtkIdType &p2)
|
||
|
{
|
||
|
for ( ; this->Position[0] <= this->TableMaxId;
|
||
|
this->Position[0]++, this->Position[1]=(-1) )
|
||
|
{
|
||
|
if ( this->Table[this->Position[0]] != NULL &&
|
||
|
++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds() )
|
||
|
{
|
||
|
p1 = this->Position[0];
|
||
|
p2 = this->Table[this->Position[0]]->GetId(this->Position[1]);
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
return this->Attributes[this->Position[0]]->GetId(this->Position[1]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
// Traverse list of edges in table. Return the edge as (p1,p2), where p1 and
|
||
|
// p2 are point id's. The value of p1 is guaranteed to be <= p2. The
|
||
|
// return value is either 1 for success or 0 if the list is exhausted.
|
||
|
int vtkEdgeTable::GetNextEdge(vtkIdType &p1, vtkIdType &p2, void* &ptr)
|
||
|
{
|
||
|
for ( ; this->Position[0] <= this->TableMaxId;
|
||
|
this->Position[0]++, this->Position[1]=(-1) )
|
||
|
{
|
||
|
if ( this->Table[this->Position[0]] != NULL &&
|
||
|
++this->Position[1] < this->Table[this->Position[0]]->GetNumberOfIds() )
|
||
|
{
|
||
|
p1 = this->Position[0];
|
||
|
p2 = this->Table[this->Position[0]]->GetId(this->Position[1]);
|
||
|
if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
this->IsEdge(p1, p2, ptr);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ptr = NULL;
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
vtkIdList **vtkEdgeTable::Resize(vtkIdType sz)
|
||
|
{
|
||
|
vtkIdList **newTableArray;
|
||
|
vtkIdList **newAttributeArray;
|
||
|
vtkVoidArray **newPointerAttributeArray;
|
||
|
vtkIdType newSize, i;
|
||
|
vtkIdType extend=this->TableSize/2 + 1;
|
||
|
|
||
|
if (sz >= this->TableSize)
|
||
|
{
|
||
|
newSize = this->TableSize +
|
||
|
extend*(((sz-this->TableSize)/extend)+1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
newSize = sz;
|
||
|
}
|
||
|
|
||
|
sz = (sz < this->TableSize ? sz : this->TableSize);
|
||
|
newTableArray = new vtkIdList *[newSize];
|
||
|
memcpy(newTableArray, this->Table, sz * sizeof(vtkIdList *));
|
||
|
for (i=sz; i < newSize; i++)
|
||
|
{
|
||
|
newTableArray[i] = NULL;
|
||
|
}
|
||
|
this->TableSize = newSize;
|
||
|
delete [] this->Table;
|
||
|
this->Table = newTableArray;
|
||
|
|
||
|
if ( this->StoreAttributes == 1 )
|
||
|
{
|
||
|
newAttributeArray = new vtkIdList *[newSize];
|
||
|
memcpy(newAttributeArray, this->Attributes, sz * sizeof(vtkIdList *));
|
||
|
for (i=sz; i < newSize; i++)
|
||
|
{
|
||
|
newAttributeArray[i] = NULL;
|
||
|
}
|
||
|
if ( this->Attributes )
|
||
|
{
|
||
|
delete [] this->Attributes;
|
||
|
}
|
||
|
this->Attributes = newAttributeArray;
|
||
|
}
|
||
|
else if ( this->StoreAttributes == 2 )
|
||
|
{
|
||
|
newPointerAttributeArray = new vtkVoidArray *[newSize];
|
||
|
memcpy(newPointerAttributeArray, this->Attributes, sz * sizeof(vtkVoidArray *));
|
||
|
for (i=sz; i < newSize; i++)
|
||
|
{
|
||
|
newPointerAttributeArray[i] = NULL;
|
||
|
}
|
||
|
if ( this->PointerAttributes )
|
||
|
{
|
||
|
delete [] this->PointerAttributes;
|
||
|
}
|
||
|
this->PointerAttributes = newPointerAttributeArray;
|
||
|
}
|
||
|
|
||
|
return this->Table;
|
||
|
}
|
||
|
|
||
|
int vtkEdgeTable::InitPointInsertion(vtkPoints *newPts, vtkIdType estSize)
|
||
|
{
|
||
|
// Initialize
|
||
|
if ( this->Table )
|
||
|
{
|
||
|
this->Initialize();
|
||
|
}
|
||
|
if ( newPts == NULL )
|
||
|
{
|
||
|
vtkErrorMacro(<<"Must define points for point insertion");
|
||
|
return 0;
|
||
|
}
|
||
|
if (this->Points != NULL)
|
||
|
{
|
||
|
this->Points->Delete();
|
||
|
}
|
||
|
// Set up the edge insertion
|
||
|
this->InitEdgeInsertion(estSize,1);
|
||
|
|
||
|
this->Points = newPts;
|
||
|
this->Points->Register(this);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int vtkEdgeTable::InsertUniquePoint(vtkIdType p1, vtkIdType p2, double x[3],
|
||
|
vtkIdType &ptId)
|
||
|
{
|
||
|
int loc = this->IsEdge(p1,p2);
|
||
|
|
||
|
if ( loc != -1 )
|
||
|
{
|
||
|
ptId = loc;
|
||
|
return 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ptId = this->InsertEdge(p1,p2);
|
||
|
this->Points->InsertPoint(ptId,x);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vtkEdgeTable::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
{
|
||
|
this->Superclass::PrintSelf(os,indent);
|
||
|
|
||
|
os << indent << "NumberOfEdges: " << this->GetNumberOfEdges() << "\n";
|
||
|
}
|