You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/Common/DataModel/vtkReebGraph.cxx

3458 lines
103 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkReebGraph.cxx
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 "vtkReebGraph.h"
#include "vtkCell.h"
#include "vtkEdgeListIterator.h"
#include "vtkDataArray.h"
#include "vtkIdTypeArray.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkReebGraphSimplificationMetric.h"
#include "vtkUnstructuredGrid.h"
#include "vtkVariantArray.h"
#include <vector>
#include <map>
#include <algorithm>
#include <queue>
//----------------------------------------------------------------------------
// Contain all of the internal data structures, and macros, in the
// implementation.
namespace
{
//----------------------------------------------------------------------------
inline static bool vtkReebGraphVertexSoS(const std::pair<int, double> &v0,
const std::pair<int, double> &v1)
{
return ((v0.second < v1.second)
|| ((v0.second == v1.second)&&(v0.first < v1.first)));
}
}
// INTERNAL MACROS ---------------------------------------------------------
#define vtkReebGraphSwapVars(type, var1, var2) \
{\
type tmp;\
tmp=(var1);\
(var1)=(var2);\
(var2)=tmp;\
}
#define vtkReebGraphInitialStreamSize 1000
#define vtkReebGraphIsSmaller(myReebGraph, nodeId0, nodeId1, node0, node1) \
((node0->Value < node1->Value) || (node0->Value == node1->Value && (nodeId0) < (nodeId1)))
#define vtkReebGraphGetArcPersistence(rg,a) \
((this->GetNode(a->NodeId1)->Value - this->GetNode(a->NodeId0)->Value) \
/(this->MaximumScalarValue - this->MinimumScalarValue))
#define vtkReebGraphIsHigherThan(rg,N0,N1,n0,n1) \
((n0->Value >n1->Value) || (n0->Value==n1->Value && n0->VertexId>n1->VertexId))
// Note: usually this macro is called after the node has been finalized,
// otherwise the behaviour is undefined.
#define vtkReebGraphIsRegular(rg,n) \
((!(n)->IsCritical) && \
((n)->ArcDownId && !this->GetArc((n)->ArcDownId)->ArcDwId1 && \
(n)->ArcUpId && !this->GetArc((n)->ArcUpId)->ArcDwId0))
#define vtkReebGraphAddUpArc(rg,N,A) {\
vtkReebNode* n = this->GetNode(N);\
vtkReebArc* a = this->GetArc(A); \
a->ArcUpId0=0;a->ArcDwId0=n->ArcUpId;\
if (n->ArcUpId) this->GetArc(n->ArcUpId)->ArcUpId0=(A);\
n->ArcUpId=(A);\
}
#define vtkReebGraphAddDownArc(rg,N,A) {\
vtkReebNode* n = this->GetNode(N);\
vtkReebArc* a = this->GetArc(A);\
a->ArcUpId1=0;\
a->ArcDwId1=n->ArcDownId;\
if (n->ArcDownId) this->GetArc(n->ArcDownId)->ArcUpId1=(A);\
n->ArcDownId=(A);\
}
#define vtkReebGraphRemoveUpArc(rg,N,A) {\
vtkReebNode* n = this->GetNode(N);\
vtkReebArc* a = this->GetArc(A);\
if (a->ArcUpId0) this->GetArc(a->ArcUpId0)->ArcDwId0=a->ArcDwId0; else n->ArcUpId=a->ArcDwId0;\
if (a->ArcDwId0) this->GetArc(a->ArcDwId0)->ArcUpId0=a->ArcUpId0;}
#define vtkReebGraphRemoveDownArc(rg,N,A) {\
vtkReebNode* n = this->GetNode(N);\
vtkReebArc* a = this->GetArc(A);\
if (a->ArcUpId1) this->GetArc(a->ArcUpId1)->ArcDwId1=a->ArcDwId1; else n->ArcDownId=a->ArcDwId1;\
if (a->ArcDwId1) this->GetArc(a->ArcDwId1)->ArcUpId1=a->ArcUpId1;\
}
#ifndef vtkReebGraphMax
#define vtkReebGraphMax(a,b) (((a)>=(b))?(a):(b))
#endif
#define vtkReebGraphStackPush(N) \
{\
if (nstack==mstack)\
{\
mstack=vtkReebGraphMax(128,mstack*2);\
int *oldstack = stack;\
stack=(int*)realloc(stack,sizeof(int)*mstack);\
if (!stack)\
{\
free(oldstack);\
assert(0 && "Ran out of memory");\
}\
} \
stack[nstack++]=(N);\
}
#define vtkReebGraphStackSize() (nstack)
#define vtkReebGraphStackTop() (stack[nstack-1])
#define vtkReebGraphStackPop() (--nstack)
//----------------------------------------------------------------------------
// PIMPLed classes...
class vtkReebGraph::Implementation
{
public:
Implementation()
{
this->historyOn = false;
this->MainNodeTable.Buffer = (vtkReebNode*)malloc(sizeof(vtkReebNode)*2);
this->MainArcTable.Buffer = (vtkReebArc*)malloc(sizeof(vtkReebArc)*2);
this->MainLabelTable.Buffer = (vtkReebLabel*)malloc(sizeof(vtkReebLabel)*2);
this->MainNodeTable.Size=2;
this->MainNodeTable.Number=1; //the item "0" is blocked
this->MainArcTable.Size=2;
this->MainArcTable.Number=1;
this->MainLabelTable.Size=2;
this->MainLabelTable.Number=1;
this->MainNodeTable.FreeZone=1;
// Clear node
this->GetNode(1)->ArcUpId = ((int)-2);
// Intialize DownArc
this->GetNode(1)->ArcDownId = 0;
this->MainArcTable.FreeZone=1;
// Clear Arc label 1
this->GetArc(1)->LabelId1 = ((int)-2);
// Initialize Arc label 0
this->GetArc(1)->LabelId0 = 0;
this->MainLabelTable.FreeZone=1;
// Clear label
this->GetLabel(1)->HNext = ((int)-2);
// Initialize Arc id
this->GetLabel(1)->ArcId = 0;
this->MinimumScalarValue = 0;
this->MaximumScalarValue = 0;
this->ArcNumber = 0;
this->NodeNumber = 0;
this->LoopNumber = 0;
this->RemovedLoopNumber = 0;
this->ArcLoopTable = 0;
this->currentNodeId = 0;
this->currentArcId = 0;
// streaming support
this->VertexMapSize = 0;
this->VertexMapAllocatedSize = 0;
this->TriangleVertexMapSize = 0;
this->TriangleVertexMapAllocatedSize = 0;
}
~Implementation()
{
free(this->MainNodeTable.Buffer);
this->MainNodeTable.Buffer = NULL;
free(this->MainArcTable.Buffer);
this->MainArcTable.Buffer = NULL;
free(this->MainLabelTable.Buffer);
this->MainLabelTable.Buffer = NULL;
this->MainNodeTable.Size = this->MainNodeTable.Number = 0;
this->MainArcTable.Size = this->MainArcTable.Number = 0;
this->MainLabelTable.Size = this->MainLabelTable.Number = 0;
this->MainNodeTable.FreeZone = 0;
this->MainArcTable.FreeZone = 0;
this->MainLabelTable.FreeZone = 0;
if(this->ArcLoopTable) free(this->ArcLoopTable);
if(this->VertexMapAllocatedSize) free(this->VertexMap);
if(this->TriangleVertexMapAllocatedSize) free(this->TriangleVertexMap);
}
typedef unsigned long long vtkReebLabelTag;
typedef struct _vtkReebCancellation{
std::vector<std::pair<int, int> > removedArcs;
std::vector<std::pair<int, int> > insertedArcs;
}vtkReebCancellation;
// Node structure
typedef struct
{
vtkIdType VertexId;
double Value;
vtkIdType ArcDownId;
vtkIdType ArcUpId;
bool IsFinalized;
bool IsCritical;
} vtkReebNode;
// Arc structure
typedef struct
{
vtkIdType NodeId0, ArcUpId0, ArcDwId0;
vtkIdType NodeId1, ArcUpId1, ArcDwId1;
vtkIdType LabelId0, LabelId1;
} vtkReebArc;
// Label structure
typedef struct
{
vtkIdType ArcId;
vtkIdType HPrev, HNext; // "horizontal" (for a single arc)
vtkReebLabelTag label;
vtkIdType VPrev, VNext; // "vertical" (for a sequence of arcs)
} vtkReebLabel;
struct vtkReebPath
{
double SimplificationValue;
int ArcNumber;
vtkIdType* ArcTable;
int NodeNumber;
vtkIdType* NodeTable;
inline bool operator<( struct vtkReebPath const &E ) const
{
return !(
(SimplificationValue < E.SimplificationValue) ||
(SimplificationValue == E.SimplificationValue
&& ArcNumber < E.ArcNumber) ||
(SimplificationValue == E.SimplificationValue
&& ArcNumber == E.ArcNumber
&& NodeTable[NodeNumber - 1] < E.NodeTable[E.NodeNumber - 1]));
/* return !((
(MaximumScalarValue - MinimumScalarValue)
< (E.MaximumScalarValue - E.MinimumScalarValue)) ||
((MaximumScalarValue - MinimumScalarValue)
== (E.MaximumScalarValue-E.MinimumScalarValue)
&& ArcNumber < E.ArcNumber) ||
((MaximumScalarValue - MinimumScalarValue)
== (E.MaximumScalarValue - E.MinimumScalarValue)
&& ArcNumber == E.ArcNumber
&& NodeTable[NodeNumber - 1]<E.NodeTable[E.NodeNumber - 1])
);*/
}
};
struct
{
int Size, Number, FreeZone;
vtkReebArc* Buffer;
} MainArcTable;
struct
{
int Size, Number, FreeZone;
vtkReebNode* Buffer;
} MainNodeTable;
struct
{
int Size, Number, FreeZone;
vtkReebLabel* Buffer;
} MainLabelTable;
vtkReebPath FindPath(vtkIdType arcId,
double simplificationThreshold, vtkReebGraphSimplificationMetric *metric);
// INTERNAL METHODS --------------------------------------------------------
vtkIdType AddArc(vtkIdType nodeId0, vtkIdType nodeId1);
// Description:
// Get the node specified from the graph.
vtkReebNode* GetNode(vtkIdType nodeId);
// Description:
// Get the arc specified from the graph.
vtkReebArc* GetArc(vtkIdType arcId);
// Description:
// Get the Label specified from the graph.
vtkReebLabel* GetLabel(vtkIdType labelId);
// Description:
// Collapse (consolidate) two nodes in the graph.
void CollapseVertex(vtkIdType N, vtkReebNode* n);
// Description:
// Triggers customized code for simplification metric evaluation.
double ComputeCustomMetric(
vtkReebGraphSimplificationMetric *simplificationMetric,
vtkReebArc *a);
// Description:
// Add a monotonic path between nodes.
vtkIdType AddPath(int nodeNumber, vtkIdType* nodeOffset,
vtkReebLabelTag label);
// Description:
// Add a vertex from the mesh to the Reeb graph.
vtkIdType AddMeshVertex(vtkIdType vertexId, double scalar);
// Description:
// Add a triangle from the mesh to the Reeb grpah.
int AddMeshTriangle(vtkIdType vertex0Id, double f0,
vtkIdType vertex1Id, double f1, vtkIdType vertex2Id, double f2);
// Description:
// Add a tetrahedron from the mesh to the Reeb grpah.
int AddMeshTetrahedron(vtkIdType vertex0Id, double f0,
vtkIdType vertex1Id, double f1, vtkIdType vertex2Id, double f2,
vtkIdType vertex3Id, double f3);
// Description:
// "Zip" the corresponding paths when the interior of a simplex is added to
// the Reeb graph.
void Collapse(vtkIdType startingNode, vtkIdType endingNode,
vtkReebLabelTag startingLabel, vtkReebLabelTag endingLabel);
// Description:
// Finalize a vertex.
void EndVertex(const vtkIdType N);
// Description:
// Remove an arc during filtering by persistence.
void FastArcSimplify(vtkIdType arcId, int arcNumber, vtkIdType* arcTable);
// Description:
// Remove arcs below the provided persistence.
int SimplifyBranches(double simplificationThreshold,
vtkReebGraphSimplificationMetric *simplificationMetric);
// Description:
// Remove the loops below the provided persistence.
int SimplifyLoops(double simplificationThreshold,
vtkReebGraphSimplificationMetric *simplificationMetric);
// Description:
// Update the vtkMutableDirectedGraph internal structure after filtering, with
// deg-2 nodes maintaining.
int CommitSimplification();
// Description:
// Retrieve downwards labels.
vtkIdType FindDwLabel(vtkIdType nodeId, vtkReebLabelTag label);
// Description
// Find greater arc (persistence-based simplification).
vtkIdType FindGreater(vtkIdType nodeId, vtkIdType startingNodeId,
vtkReebLabelTag label);
// Description:
// Find corresponding joining saddle node (persistence-based simplification).
vtkIdType FindJoinNode(vtkIdType arcId,
vtkReebLabelTag label, bool onePathOnly=false);
// Description:
// Find smaller arc (persistence-based simplification).
vtkIdType FindLess(vtkIdType nodeId, vtkIdType startingNodeId,
vtkReebLabelTag label);
// Description:
// Compute the loops in the Reeb graph.
void FindLoops();
// Description:
// Find corresponding splitting saddle node (persistence-based
// simplification).
vtkIdType FindSplitNode(vtkIdType arcId, vtkReebLabelTag label,
bool onePathOnly=false);
// Description:
// Retrieve upwards labels.
vtkIdType FindUpLabel(vtkIdType nodeId, vtkReebLabelTag label);
// Description:
// Flush labels.
void FlushLabels();
// Description:
// Resize the arc table.
void ResizeMainArcTable(int newSize);
// Description:
// Resize the label table.
void ResizeMainLabelTable(int newSize);
// Description:
// Resize the node table.
void ResizeMainNodeTable(int newSize);
// Description:
// Set a label.
void SetLabel(vtkIdType A, vtkReebLabelTag Label);
// Description:
// Simplify labels.
void SimplifyLabels(const vtkIdType nodeId, vtkReebLabelTag onlyLabel=0,
bool goDown=true, bool goUp=true);
// ACCESSORS
// Description:
// Returns the Id of the lower node of the arc specified by 'arcId'.
vtkIdType GetArcDownNodeId(vtkIdType arcId);
// Description:
// Return the Id of the upper node of the arc specified by 'arcId'.
vtkIdType GetArcUpNodeId(vtkIdType arcId);
// Description:
// Iterates forwards through the arcs of the Reeb graph.
//
// The first time this method is called, the first arc's Id will be returned.
// When the last arc is reached, this method will keep on returning its Id at
// each call. See 'GetPreviousArcId' to go back in the list.
vtkIdType GetNextArcId();
// Description:
// Iterates forwards through the nodes of the Reeb graph.
//
// The first time this method is called, the first node's Id will be returned.
// When the last node is reached, this method will keep on returning its Id at
// each call. See 'GetPreviousNodeId' to go back in the list.
vtkIdType GetNextNodeId();
// Description:
// Copy into 'arcIdList' the list of the down arcs' Ids, given a node
// specified by 'nodeId'.
void GetNodeDownArcIds(vtkIdType nodeId, vtkIdList *arcIdList);
// Description:
// Returns the scalar field value of the node specified by 'nodeId'.
double GetNodeScalarValue(vtkIdType nodeId);
// Description:
// Copy into 'arcIdList' the list of the up arcs' Ids, given a node specified
// by 'nodeId'.
void GetNodeUpArcIds(vtkIdType nodeId, vtkIdList *arcIdList);
// Description:
// Returns the corresponding vertex Id (in the simplicial mesh, vtkPolyData),
// given a node specified by 'nodeId'.
vtkIdType GetNodeVertexId(vtkIdType nodeId);
// Description:
// Returns the number of arcs in the Reeb graph.
int GetNumberOfArcs();
// Description:
// Returns the number of connected components of the Reeb graph.
int GetNumberOfConnectedComponents();
// Description:
// Returns the number of nodes in the Reeb graph.
int GetNumberOfNodes();
// Description:
// Returns the number of loops (cycles) in the Reeb graph.
//
// Notice that for closed PL 2-manifolds, this number equals the genus of the
// manifold.
//
// Reference:
// "Loops in Reeb graphs of 2-manifolds",
// K. Cole-McLaughlin, H. Edelsbrunner, J. Harer, V. Natarajan, and V.
// Pascucci,
// ACM Symposium on Computational Geometry, pp. 344-350, 2003.
int GetNumberOfLoops();
// Description:
// Iterates backwards through the arcs of the Reeb graph.
//
// When the first arc is reached, this method will keep on returning its Id at
// each call. See 'GetNextArcId' to go forwards in the list.
vtkIdType GetPreviousArcId();
// Description:
// Iterates backwards through the nodes of the Reeb graph.
//
// When the first node is reached, this method will keep on returning its Id
// at each call. See 'GetNextNodeId' to go forwards in the list.
vtkIdType GetPreviousNodeId();
// Description:
// Implementations of the stream classes to operate on the streams...
int StreamTetrahedron( vtkIdType vertex0Id, double scalar0,
vtkIdType vertex1Id, double scalar1,
vtkIdType vertex2Id, double scalar2,
vtkIdType vertex3Id, double scalar3);
int StreamTriangle( vtkIdType vertex0Id, double scalar0,
vtkIdType vertex1Id, double scalar1,
vtkIdType vertex2Id, double scalar2);
void DeepCopy(Implementation *src);
// Description:
// Data storage.
std::map<int, int> VertexStream;
std::vector<vtkReebCancellation> cancellationHistory;
// Streaming support
int VertexMapSize, VertexMapAllocatedSize, TriangleVertexMapSize, TriangleVertexMapAllocatedSize;
bool historyOn;
vtkIdType *VertexMap;
int *TriangleVertexMap;
double MinimumScalarValue, MaximumScalarValue;
// Arcs and nodes
int ArcNumber, NodeNumber;
// Loops
int LoopNumber, RemovedLoopNumber;
vtkIdType *ArcLoopTable;
// CC
int ConnectedComponentNumber;
std::map<int, double> ScalarField;
vtkIdType currentNodeId, currentArcId;
vtkDataSet *inputMesh;
vtkDataArray *inputScalarField;
vtkReebGraph *Parent;
};
//----------------------------------------------------------------------------
vtkReebGraph::Implementation::vtkReebNode* vtkReebGraph::Implementation::GetNode(vtkIdType nodeId)
{
return (this->MainNodeTable.Buffer + nodeId);
}
//----------------------------------------------------------------------------
vtkReebGraph::Implementation::vtkReebArc* vtkReebGraph::Implementation::GetArc(vtkIdType arcId)
{
return (this->MainArcTable.Buffer + arcId);
}
//----------------------------------------------------------------------------
vtkReebGraph::Implementation::vtkReebLabel* vtkReebGraph::Implementation::GetLabel(vtkIdType labelId)
{
return (this->MainLabelTable.Buffer + labelId);
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::CollapseVertex(vtkIdType N, vtkReebNode* n)
{
int Lb, Lnext, La;
vtkReebLabel* lb;
int _A0 = n->ArcDownId;
int _A1 = n->ArcUpId;
vtkReebArc* _a0 = this->GetArc(_A0);
vtkReebArc* _a1 = this->GetArc(_A1);
_a0->NodeId1 = _a1->NodeId1;
_a0->ArcUpId1 = _a1->ArcUpId1;
if (_a1->ArcUpId1)
this->GetArc(_a1->ArcUpId1)->ArcDwId1 = _A0;
_a0->ArcDwId1 = _a1->ArcDwId1;
if(_a1->ArcDwId1)
this->GetArc(_a1->ArcDwId1)->ArcUpId1 = _A0;
if (this->GetNode(_a1->NodeId1)->ArcDownId == _A1)
this->GetNode(_a1->NodeId1)->ArcDownId = _A0;
for( Lb = _a1->LabelId0; Lb; Lb=Lnext )
{
lb = this->GetLabel(Lb);
Lnext = lb->HNext;
if (lb->VPrev)
{
La=lb->VPrev;
this->GetLabel(La)->VNext = lb->VNext;
}
if (lb->VNext)
this->GetLabel(lb->VNext)->VPrev=lb->VPrev;
//delete the label...
this->GetLabel(Lb)->HNext = ((int)-2);
this->GetLabel(Lb)->ArcId = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone=(Lb);
--(this->MainLabelTable.Number);
}
//delete the arc from the graph...
this->GetArc(_A1)->LabelId1 = ((int)-2);
this->GetArc(_A1)->LabelId0 = this->MainArcTable.FreeZone;
this->MainArcTable.FreeZone=(_A1);
--(this->MainArcTable.Number);
//delete the node from the graph...
this->GetNode(N)->ArcUpId = ((int)-2);
this->GetNode(N)->ArcDownId = this->MainNodeTable.FreeZone;
this->MainNodeTable.FreeZone=(N);
--(this->MainNodeTable.Number);
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::DeepCopy(Implementation *srcG)
{
MinimumScalarValue = srcG->MinimumScalarValue;
MaximumScalarValue = srcG->MaximumScalarValue;
inputMesh = srcG->inputMesh;
inputScalarField = srcG->inputScalarField;
ArcNumber = srcG->ArcNumber;
NodeNumber = srcG->NodeNumber;
LoopNumber = srcG->LoopNumber;
ScalarField = srcG->ScalarField;
VertexStream = srcG->VertexStream;
if (srcG->MainArcTable.Buffer)
{
MainArcTable.Size = srcG->MainArcTable.Size;
MainArcTable.Number = srcG->MainArcTable.Number;
this->MainArcTable.Buffer = (vtkReebArc*)malloc(
sizeof(vtkReebArc)*srcG->MainArcTable.Size);
memcpy(this->MainArcTable.Buffer,srcG->MainArcTable.Buffer,
sizeof(vtkReebArc)*srcG->MainArcTable.Size);
}
if (srcG->MainNodeTable.Buffer)
{
MainNodeTable.Size = srcG->MainNodeTable.Size;
MainNodeTable.Number = srcG->MainNodeTable.Number;
this->MainNodeTable.Buffer = (vtkReebNode*)malloc(
sizeof(vtkReebNode)*srcG->MainNodeTable.Size);
memcpy(this->MainNodeTable.Buffer,srcG->MainNodeTable.Buffer,
sizeof(vtkReebNode)*srcG->MainNodeTable.Size);
}
if (srcG->MainLabelTable.Buffer)
{
MainLabelTable.Size = srcG->MainLabelTable.Size;
MainLabelTable.Number = srcG->MainLabelTable.Number;
this->MainLabelTable.Buffer = (vtkReebLabel*)malloc(
sizeof(vtkReebLabel)*srcG->MainLabelTable.Size);
memcpy(this->MainLabelTable.Buffer,srcG->MainLabelTable.Buffer,
sizeof(vtkReebLabel)*srcG->MainLabelTable.Size);
}
if (srcG->ArcLoopTable)
{
this->ArcLoopTable=(vtkIdType *)malloc(sizeof(vtkIdType)*srcG->LoopNumber);
memcpy(this->ArcLoopTable,
srcG->ArcLoopTable,sizeof(vtkIdType)*srcG->LoopNumber);
}
if(srcG->VertexMapSize){
this->VertexMapSize = srcG->VertexMapSize;
this->VertexMapAllocatedSize = srcG->VertexMapAllocatedSize;
this->VertexMap = (vtkIdType *) malloc(
sizeof(vtkIdType)*this->VertexMapAllocatedSize);
memcpy(this->VertexMap, srcG->VertexMap,
sizeof(vtkIdType)*srcG->VertexMapAllocatedSize);
}
if(srcG->TriangleVertexMapSize){
this->TriangleVertexMapSize = srcG->TriangleVertexMapSize;
this->TriangleVertexMapAllocatedSize = srcG->TriangleVertexMapAllocatedSize;
this->TriangleVertexMap = (int *) malloc(
sizeof(int)*this->TriangleVertexMapAllocatedSize);
memcpy(this->TriangleVertexMap, srcG->TriangleVertexMap,
sizeof(int)*srcG->TriangleVertexMapAllocatedSize);
}
}
//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkReebGraph);
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::SetLabel(vtkIdType arcId,
vtkReebLabelTag Label)
{
inputMesh = NULL;
ResizeMainLabelTable(1);
//create a new label in the graph
vtkIdType L = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone = this->GetLabel(L)->ArcId;
++(this->MainLabelTable.Number);
memset(this->GetLabel(L),0,sizeof(vtkReebLabel));
vtkReebLabel* l = this->GetLabel(L);
l->HPrev=0;
l->HNext=0;
this->GetArc(arcId)->LabelId0=L;
this->GetArc(arcId)->LabelId1=L;
l->ArcId = arcId;
l->label=Label;
vtkIdType Lp = FindDwLabel(this->GetArc(arcId)->NodeId0,Label);
vtkIdType Ln = FindUpLabel(this->GetArc(arcId)->NodeId1,Label);
l->VPrev=Lp;
if (Lp) this->GetLabel(Lp)->VNext=L;
l->VNext=Ln;
if (Ln) this->GetLabel(Ln)->VPrev=L;
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::FastArcSimplify(vtkIdType arcId,
int vtkNotUsed(ArcNumber),
vtkIdType* vtkNotUsed(arcTable))
{
// Remove the arc which opens the loop
vtkIdType nodeId0 = this->GetArc(arcId)->NodeId0;
vtkIdType nodeId1 = this->GetArc(arcId)->NodeId1;
vtkReebArc *A = this->GetArc(arcId);
vtkReebArc *B = NULL;
int down, middle, up;
if(historyOn)
{
if(A->ArcDwId0)
{
B = this->GetArc(A->ArcDwId0);
down = this->GetNode(B->NodeId0)->VertexId;
middle = this->GetNode(A->NodeId0)->VertexId;
up = this->GetNode(B->NodeId1)->VertexId;
vtkReebCancellation c;
c.removedArcs.push_back(std::pair<int, int>(middle, up));
c.insertedArcs.push_back(std::pair<int, int>(down, up));
this->cancellationHistory.push_back(c);
}
if(A->ArcDwId1)
{
B = this->GetArc(A->ArcDwId1);
down = this->GetNode(B->NodeId0)->VertexId;
middle = this->GetNode(A->NodeId0)->VertexId;
up = this->GetNode(A->NodeId1)->VertexId;
vtkReebCancellation c;
c.removedArcs.push_back(std::pair<int, int>(middle, up));
c.insertedArcs.push_back(std::pair<int, int>(down, up));
this->cancellationHistory.push_back(c);
}
if(A->ArcUpId0)
{
B = this->GetArc(A->ArcUpId0);
down = this->GetNode(A->NodeId0)->VertexId;
middle = this->GetNode(A->NodeId1)->VertexId;
up = this->GetNode(B->NodeId1)->VertexId;
vtkReebCancellation c;
c.removedArcs.push_back(std::pair<int, int>(down, middle));
c.insertedArcs.push_back(std::pair<int, int>(down, up));
this->cancellationHistory.push_back(c);
}
if(A->ArcUpId1)
{
B = this->GetArc(A->ArcUpId1);
down = this->GetNode(B->NodeId0)->VertexId;
middle = this->GetNode(A->NodeId1)->VertexId;
up = this->GetNode(B->NodeId1)->VertexId;
vtkReebCancellation c;
c.removedArcs.push_back(std::pair<int, int>(down, middle));
c.insertedArcs.push_back(std::pair<int, int>(down, up));
this->cancellationHistory.push_back(c);
}
}
vtkReebGraphRemoveUpArc(this, nodeId0, arcId);
vtkReebGraphRemoveDownArc(this, nodeId1, arcId);
//delete the arc from the graph...
this->GetArc(arcId)->LabelId1 = ((int)-2);
this->GetArc(arcId)->LabelId0 = this->MainArcTable.FreeZone;
this->MainArcTable.FreeZone=(arcId);
--(this->MainArcTable.Number);
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindGreater(vtkIdType nodeId,
vtkIdType startingNodeId,
vtkReebLabelTag label)
{
if (!this->GetNode(nodeId)->IsFinalized)
return 0;
//base case
if (vtkReebGraphIsHigherThan(this, nodeId, startingNodeId, this->GetNode(nodeId), this->GetNode(startingNodeId)))
return nodeId;
//iterative case
for (vtkIdType A = this->GetNode(nodeId)->ArcUpId; A; A = this->GetArc(A)->ArcDwId0)
{
vtkReebArc* a = this->GetArc(A);
vtkIdType M = this->GetArc(A)->NodeId1;
vtkReebNode* m = this->GetNode(M);
if (a->LabelId0 || !m->IsFinalized) //other labels or not final node
{
continue;
}
if ((M = FindGreater(M, startingNodeId, label)))
{
if (label)
{
SetLabel(A, label);
}
return M;
}
}
return 0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindLess(vtkIdType nodeId,
vtkIdType startingNodeId,
vtkReebLabelTag label)
{
if (!this->GetNode(nodeId)->IsFinalized)
return 0;
//base case
if(vtkReebGraphIsSmaller(this, nodeId, startingNodeId, this->GetNode(nodeId), this->GetNode(startingNodeId)))
return nodeId;
//iterative case
for (vtkIdType A = this->GetNode(nodeId)->ArcDownId; A; A = this->GetArc(A)->ArcDwId1)
{
vtkReebArc* a = this->GetArc(A);
vtkIdType M = this->GetArc(A)->NodeId0;
vtkReebNode* m = this->GetNode(M);
if (a->LabelId0 || !m->IsFinalized) //other labels or not final node
continue;
if ((M = FindLess(M, startingNodeId, label)))
{
if (label)
{
SetLabel(A, label);
}
return M;
}
}
return 0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindJoinNode(vtkIdType arcId,
vtkReebLabelTag label,
bool onePathOnly)
{
vtkIdType N = this->GetArc(arcId)->NodeId1;
vtkIdType Ret,C;
if (this->GetArc(arcId)->LabelId0 || !this->GetNode(N)->IsFinalized)
//other labels or not final node
return 0;
if (onePathOnly && (this->GetArc(arcId)->ArcDwId0 || this->GetArc(arcId)->ArcUpId0))
return 0;
//base case
if (this->GetArc(arcId)->ArcDwId1 || this->GetArc(arcId)->ArcUpId1)
{
if (label) SetLabel(arcId, label);
return N;
}
for (C = this->GetNode(N)->ArcUpId; C; C = this->GetArc(C)->ArcDwId0)
{
Ret = FindJoinNode(C, label, onePathOnly);
if (Ret)
{
if (label) SetLabel(arcId, label);
return Ret;
}
}
return 0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindSplitNode(vtkIdType arcId,
vtkReebLabelTag label,
bool onePathOnly)
{
vtkIdType N = this->GetArc(arcId)->NodeId0;
vtkIdType Ret,C;
if (this->GetArc(arcId)->LabelId0 || !this->GetNode(N)->IsFinalized)
//other labels or not final node
return 0;
if (onePathOnly && (this->GetArc(arcId)->ArcDwId1 || this->GetArc(arcId)->ArcUpId1))
return 0;
//base case
if (this->GetArc(arcId)->ArcDwId0 || this->GetArc(arcId)->ArcUpId0)
{
if (label) SetLabel(arcId, label);
return N;
}
//iterative case
for (C = this->GetNode(N)->ArcDownId; C; C = this->GetArc(C)->ArcDwId1)
{
Ret = FindSplitNode(C, label, onePathOnly);
if (Ret)
{
if (label) SetLabel(arcId, label);
return Ret;
}
}
return 0;
}
//----------------------------------------------------------------------------
vtkReebGraph::Implementation::vtkReebPath vtkReebGraph::Implementation::FindPath(vtkIdType arcId,
double simplificationThreshold, vtkReebGraphSimplificationMetric *metric)
{
vtkReebPath entry;
std::priority_queue<vtkReebPath> pq;
int size;
vtkIdType N0 = this->GetArc(arcId)->NodeId0;
vtkIdType N1 = this->GetArc(arcId)->NodeId1;
char* Ntouch = 0;
char* Atouch = 0;
// double simplificationValue = 0;
if((!inputMesh)||(!metric))
{
double f0 = this->GetNode(N0)->Value;
double f1 = this->GetNode(N1)->Value;
entry.SimplificationValue = (f1 - f0)
/(this->MaximumScalarValue - this->MinimumScalarValue);
}
else
{
entry.SimplificationValue = ComputeCustomMetric(metric, this->GetArc(arcId));
}
//the arc itself has a good persistence
if (simplificationThreshold
&& entry.SimplificationValue>= simplificationThreshold)
{
NOT_FOUND:
if (Ntouch) free(Ntouch);
if (Atouch) free(Atouch);
vtkReebPath fake;memset(&fake,0,sizeof(vtkReebPath));
fake.SimplificationValue = 1;
return fake;
}
Atouch=(char*)malloc(sizeof(char)*this->MainArcTable.Size);
Ntouch=(char*)malloc(sizeof(char)*this->MainNodeTable.Size);
memset(Atouch,0,sizeof(char)*this->MainArcTable.Size);
memset(Ntouch,0,sizeof(char)*this->MainNodeTable.Size);
Ntouch[N0]=1;
//I don't want to use the arc given by the user
Atouch[arcId]=1;
entry.NodeNumber=1;
entry.NodeTable = new vtkIdType[1];
entry.NodeTable[0]=N0;
entry.ArcNumber=0;
entry.ArcTable =0;
pq.push(entry);
while ((size=static_cast<int>(pq.size())))
{
entry=pq.top();
pq.pop();
int N=entry.NodeTable[entry.NodeNumber-1];
for (int dir=0;dir<=1;dir++)
{
for (int A = (!dir) ? this->GetNode(N)->ArcDownId : this->GetNode(N)->ArcUpId; A;
A=(!dir) ? this->GetArc(A)->ArcDwId1 : this->GetArc(A)->ArcDwId0)
{
int M = (!dir) ? (this->GetArc(A)->NodeId0) : (this->GetArc(A)->NodeId1);
if (Atouch[A]) continue;
Atouch[A]=1;
//already used (==there is a better path to reach M)
if (Ntouch[M]) continue;
Ntouch[M]=1;
//found!!!
if (M==N1)
{
//clear all the items in the priority queue
while (!pq.empty())
{
vtkReebPath aux=pq.top();pq.pop();
delete aux.ArcTable;
delete aux.NodeTable;
}
free(Ntouch);
free(Atouch);
vtkIdType* tmp=new vtkIdType[entry.NodeNumber+1];
memcpy(tmp,entry.NodeTable,sizeof(vtkIdType)*entry.NodeNumber);
tmp[entry.NodeNumber]=N1;
delete [] entry.NodeTable;
entry.NodeTable = tmp;
entry.NodeNumber++;
return entry;
}
if((!inputMesh)||(!metric))
{
entry.SimplificationValue += vtkReebGraphGetArcPersistence(this, this->GetArc(A));
}
else
{
entry.SimplificationValue += ComputeCustomMetric(metric, this->GetArc(A));
}
// The loop persistence is greater than functionScale
if(simplificationThreshold
&& entry.SimplificationValue >= simplificationThreshold)
continue;
vtkReebPath newentry;
newentry.SimplificationValue = entry.SimplificationValue;
newentry.ArcNumber = entry.ArcNumber+1;
newentry.ArcTable = new vtkIdType [newentry.ArcNumber];
newentry.NodeNumber = entry.NodeNumber+1;
newentry.NodeTable = new vtkIdType [newentry.NodeNumber];
if (entry.ArcNumber)
memcpy(newentry.ArcTable,entry.ArcTable,
sizeof(vtkIdType)*entry.ArcNumber);
if (entry.NodeNumber)
memcpy(newentry.NodeTable,entry.NodeTable,
sizeof(vtkIdType)*entry.NodeNumber);
newentry.ArcTable[entry.ArcNumber]=A;
newentry.NodeTable[entry.NodeNumber]=M;
pq.push(newentry);
}
}
//finished with this entry
delete entry.ArcTable;
delete [] entry.NodeTable;
}
goto NOT_FOUND;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::SimplifyLoops(double simplificationThreshold,
vtkReebGraphSimplificationMetric *simplificationMetric)
{
if (!simplificationThreshold)
return 0;
// refresh information about ArcLoopTable
this->FindLoops();
int NumSimplified=0;
for (int n = 0; n < this->LoopNumber; n++)
{
int A = this->ArcLoopTable[n];
if (this->GetArc(A)->LabelId1 == ((int)-2))
continue;
double simplificationValue = 0;
if((!inputMesh)||(!simplificationMetric))
{
vtkIdType N0 = this->GetArc(A)->NodeId0;
vtkIdType N1 = this->GetArc(A)->NodeId1;
double f0 = this->GetNode(N0)->Value;
double f1 = this->GetNode(N1)->Value;
simplificationValue = (f1 - f0)
/(this->MaximumScalarValue - this->MinimumScalarValue);
}
else
{
simplificationValue = ComputeCustomMetric(simplificationMetric, this->GetArc(A));
}
if(simplificationValue >= simplificationThreshold)
continue;
vtkReebPath entry = this->FindPath(this->ArcLoopTable[n],
simplificationThreshold, simplificationMetric);
//too high for persistence
if(entry.SimplificationValue >= simplificationThreshold)
continue;
//distribute its bucket to the loop and delete the arc
this->FastArcSimplify(ArcLoopTable[n],entry.ArcNumber,entry.ArcTable);
delete entry.ArcTable;
delete entry.NodeTable;
++NumSimplified;
CommitSimplification();
}
//check for regular points
for (int N=1;N<this->MainNodeTable.Size;N++)
{
if(this->GetNode(N)->ArcUpId == ((int)-2))
continue;
if (this->GetNode(N)->ArcDownId==0 && this->GetNode(N)->ArcUpId==0)
{
//delete the node from the graph...
this->GetNode(N)->ArcUpId = ((int)-2);
this->GetNode(N)->ArcDownId = this->MainNodeTable.FreeZone;
this->MainNodeTable.FreeZone=(N);
--(this->MainNodeTable.Number);
}
else if (vtkReebGraphIsRegular(this,this->GetNode(N)))
{
if(historyOn)
{
vtkReebNode *n = this->GetNode(N);
int A0 = n->ArcDownId;
int A1 = n->ArcUpId;
vtkReebArc *a0 = this->GetArc(A0);
vtkReebArc *a1 = this->GetArc(A1);
vtkReebNode *downN = this->GetNode(a0->NodeId0);
vtkReebNode *upN = this->GetNode(a1->NodeId1);
int down, middle, up;
down = downN->VertexId;
middle = n->VertexId;
up = upN->VertexId;
vtkReebCancellation c;
c.removedArcs.push_back(std::pair<int, int>(down, middle));
c.removedArcs.push_back(std::pair<int, int>(middle, up));
c.insertedArcs.push_back(std::pair<int, int>(down, up));
this->cancellationHistory.push_back(c);
}
EndVertex(N);
}
}
this->RemovedLoopNumber = NumSimplified;
return NumSimplified;
}
//----------------------------------------------------------------------------
double vtkReebGraph::Implementation::ComputeCustomMetric(
vtkReebGraphSimplificationMetric *simplificationMetric, vtkReebArc *a)
{
int edgeId = -1, start = -1, end = -1;
vtkDataArray *vertexInfo = vtkArrayDownCast<vtkDataArray>(
this->Parent->GetVertexData()->GetAbstractArray("Vertex Ids"));
if(!vertexInfo) return vtkReebGraphGetArcPersistence(this, a);
vtkVariantArray *edgeInfo = vtkArrayDownCast<vtkVariantArray>(
this->Parent->GetEdgeData()->GetAbstractArray("Vertex Ids"));
if(!edgeInfo) return vtkReebGraphGetArcPersistence(this, a);
vtkEdgeListIterator *eIt = vtkEdgeListIterator::New();
this->Parent->GetEdges(eIt);
do
{
vtkEdgeType e = eIt->Next();
if(((*(vertexInfo->GetTuple(e.Source))) == GetNodeVertexId(a->NodeId0))
&&((*(vertexInfo->GetTuple(e.Target))) == GetNodeVertexId(a->NodeId1)))
{
edgeId = e.Id;
start = static_cast<int>(*(vertexInfo->GetTuple(e.Source)));
end = static_cast<int>(*(vertexInfo->GetTuple(e.Target)));
break;
}
}while(eIt->HasNext());
eIt->Delete();
vtkAbstractArray *vertexList = edgeInfo->GetPointer(edgeId)->ToArray();
return simplificationMetric->ComputeMetric(inputMesh, inputScalarField,
start, vertexList, end);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::SimplifyBranches(double simplificationThreshold,
vtkReebGraphSimplificationMetric *simplificationMetric)
{
static const vtkReebLabelTag RouteOld=100;
static const vtkReebLabelTag RouteNew=200;
int nstack,mstack=0;
int* stack=0;
if (!simplificationThreshold)
return 0;
int nsimp=0;
int cont=0;
const int step=10000;
bool redo;
vtkDataSet *input = inputMesh;
REDO:
nstack=0;
redo=false;
for (int N = 1; N < this->MainNodeTable.Size; ++N)
{
if(this->GetNode(N)->ArcUpId == ((int)-2))
continue;
vtkReebNode* n = this->GetNode(N);
//simplify atomic nodes
if (!n->ArcDownId && !n->ArcUpId)
{
//delete the node from the graph...
this->GetNode(N)->ArcUpId = ((int)-2);
this->GetNode(N)->ArcDownId = this->MainNodeTable.FreeZone;
this->MainNodeTable.FreeZone=(N);
--(this->MainNodeTable.Number);
}
else if (!n->ArcDownId)
{
//insert into stack branches to simplify
for (int _A_ = n->ArcUpId; _A_; _A_ = this->GetArc(_A_)->ArcDwId0)
{
vtkReebArc* _a_ = this->GetArc(_A_);
if((!inputMesh)||(!simplificationMetric))
{
if (vtkReebGraphGetArcPersistence(this,_a_)< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
else
{
if(this->ComputeCustomMetric(simplificationMetric, _a_)
< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
}
}
else if (!n->ArcUpId)
{
//insert into stack branches to simplify
for (int _A_=n->ArcDownId;_A_;_A_=this->GetArc(_A_)->ArcDwId1)
{
vtkReebArc* _a_ = this->GetArc(_A_);
if (vtkReebGraphGetArcPersistence(this,_a_)< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
}
}
while (vtkReebGraphStackSize())
{
int A=vtkReebGraphStackTop();vtkReebGraphStackPop();
if (!--cont)
{
cont=step;
}
if (this->GetArc(A)->LabelId1 == ((int)-2))
continue;
cont++;
vtkReebArc* arc = this->GetArc(A);
int N = arc->NodeId0;
int M = arc->NodeId1;
if (this->GetNode(N)->ArcDownId && this->GetNode(M)->ArcUpId)
continue;
double persistence = vtkReebGraphGetArcPersistence(this, arc);
//is the actual persistence (in percentage) greater than the applied filter?
if (persistence>=simplificationThreshold)
continue;
int _A, Mdown = 0, Nup = 0, Ndown = 0, Mup = 0;
//get the 'down' degree for M
for(_A = this->GetNode(M)->ArcDownId;_A;_A = this->GetArc(_A)->ArcDwId1)
++Mdown;
//Get the 'up' degree for N
for(_A = this->GetNode(N)->ArcUpId;_A;_A = this->GetArc(_A)->ArcDwId0)
++Nup;
//get the 'down' degree for N
for(_A = this->GetNode(N)->ArcDownId;_A;_A = this->GetArc(_A)->ArcDwId1)
++Ndown;
//get the 'up' degree for M
for(_A = this->GetNode(M)->ArcUpId;_A;_A = this->GetArc(_A)->ArcDwId0)
++Mup;
//isolated arc
if (!Ndown && Nup==1 && Mdown==1 && !Mup)
{
vtkReebGraphRemoveUpArc (this,N,A);
vtkReebGraphRemoveDownArc(this,M,A);
//delete the arc from the graph...
this->GetArc(A)->LabelId1 = ((int)-2);
this->GetArc(A)->LabelId0 = this->MainArcTable.FreeZone;
this->MainArcTable.FreeZone=(A);
--(this->MainArcTable.Number);
if (!(this->GetNode(N)->ArcUpId == ((int)-2)) &&
vtkReebGraphIsRegular(this, this->GetNode(N)))
{
EndVertex(N);
}
if (!(this->GetNode(M)->ArcUpId == ((int)-2)) &&
vtkReebGraphIsRegular(this, this->GetNode(M)))
{
EndVertex(M);
}
nsimp++;redo=true;
continue;
}
int Down=0;
int Up=0;
bool simplified=false;
// M is a maximum
if (!simplified && !Mup)
{
if ((Down = FindSplitNode(A, RouteOld)))
{
if ((Up = FindGreater(Down, M, RouteNew)))
{
SetLabel(AddArc(M,Up),RouteOld);
Collapse(Down,Up,RouteOld,RouteNew);
simplified=true;
}
else
{
this->SimplifyLabels(Down);
}
}
}
//N is a minimum
if (!simplified && !Ndown)
{
if ((Up = FindJoinNode(A, RouteOld)))
{
if ((Down = FindLess(Up, N, RouteNew)))
{
SetLabel(AddArc(Down,N),RouteOld);
Collapse(Down,Up,RouteOld,RouteNew);
simplified=true;
}
else
{
this->SimplifyLabels(Up);
}
}
}
if (simplified)
{
if (!(this->GetNode(Down)->ArcUpId == ((int)-2)))
{
this->SimplifyLabels(Down);
if (!this->GetNode(Down)->ArcDownId) //minimum
{
for (vtkIdType _A_ = this->GetNode(Down)->ArcUpId; _A_; _A_ = this->GetArc(_A_)->ArcDwId0)
{
vtkReebArc* _a_ = this->GetArc(_A_);
if((!inputMesh)||(!simplificationMetric))
{
if (vtkReebGraphGetArcPersistence(this,_a_)
< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
else
{
if(this->ComputeCustomMetric(simplificationMetric, _a_) < simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
}
}
}
if (!(this->GetNode(Up)->ArcUpId == ((int)-2)))
{
this->SimplifyLabels(Up);
if (!this->GetNode(Up)->ArcUpId)
{
for (int _A_ = this->GetNode(Up)->ArcDownId; _A_; _A_ = this->GetArc(_A_)->ArcDwId1)
{
vtkReebArc* _a_ = this->GetArc(_A_);
if((!inputMesh)||(!simplificationMetric))
{
if (vtkReebGraphGetArcPersistence(this,_a_)
< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
else
{
if(this->ComputeCustomMetric(simplificationMetric, _a_)
< simplificationThreshold)
{
vtkReebGraphStackPush(_A_);
}
}
}
}
}
nsimp++;
redo=true;
}
CommitSimplification();
} //while
if (redo)
goto REDO;
free(stack);
inputMesh = input;
return nsimp;
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::ResizeMainNodeTable(int newSize)
{
int oldsize,i;
if ((this->MainNodeTable.Size-this->MainNodeTable.Number)< newSize)
{
oldsize=this->MainNodeTable.Size;
if (!this->MainNodeTable.Size) this->MainNodeTable.Size = newSize;
while ((this->MainNodeTable.Size-this->MainNodeTable.Number)< newSize)
this->MainNodeTable.Size<<=1;
this->MainNodeTable.Buffer = (vtkReebNode*)realloc(
this->MainNodeTable.Buffer,sizeof(vtkReebNode)*this->MainNodeTable.Size);
for (i=oldsize;i<this->MainNodeTable.Size-1;i++)
{
this->GetNode(i)->ArcDownId=i+1;
this->GetNode(i)->ArcUpId = ((int)-2);
}
this->GetNode(i)->ArcDownId = this->MainNodeTable.FreeZone;
this->GetNode(i)->ArcUpId = ((int)-2);
this->MainNodeTable.FreeZone=oldsize;
}
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::CommitSimplification()
{
// now re-construct the graph with projected deg-2 nodes.
std::vector<std::pair<std::pair<int, int>, std::vector<int> > > before, after;
vtkEdgeListIterator *eIt = vtkEdgeListIterator::New();
this->Parent->GetEdges(eIt);
vtkVariantArray *edgeInfo = vtkArrayDownCast<vtkVariantArray>(
this->Parent->GetEdgeData()->GetAbstractArray("Vertex Ids"));
vtkDataArray *vertexInfo =
this->Parent->GetVertexData()->GetArray("Vertex Ids");
// avoids double projection
int vertexNumber = vertexInfo->GetNumberOfTuples();
std::vector<bool> segmentedVertices;
do
{
std::pair<std::pair<int, int>, std::vector<int> > superArc;
vtkEdgeType e = eIt->Next();
vtkAbstractArray *vertexList = edgeInfo->GetPointer(e.Id)->ToArray();
superArc.first.first = (int) *(vertexInfo->GetTuple(e.Source));
superArc.first.second = (int) *(vertexInfo->GetTuple(e.Target));
superArc.second.resize(vertexList->GetNumberOfTuples());
vertexNumber += vertexList->GetNumberOfTuples();
for(unsigned int i = 0; i < superArc.second.size(); i++)
superArc.second[i] = vertexList->GetVariantValue(i).ToInt();
before.push_back(superArc);
}while(eIt->HasNext());
segmentedVertices.resize(vertexNumber);
for(unsigned int i = 0; i < segmentedVertices.size(); i++)
segmentedVertices[i] = false;
vtkIdType prevArcId = -1, arcId = 0;
while(arcId != prevArcId)
{
prevArcId = arcId;
arcId = GetPreviousArcId();
}
prevArcId = -1;
while(prevArcId != arcId)
{
if(this->GetArc(arcId))
{
int down, up;
down = this->GetNode((this->GetArc(arcId))->NodeId0)->VertexId;
up = this->GetNode((this->GetArc(arcId))->NodeId1)->VertexId;
std::pair<std::pair<int, int>, std::vector<int> > superArc;
superArc.first.first = down;
superArc.first.second = up;
after.push_back(superArc);
}
prevArcId = arcId;
arcId = GetNextArcId();
}
std::pair<int, int> destinationArc;
std::map<int, bool> processedOutputArcs;
// now map the unsimplified arcs onto the simplified ones
for(unsigned int i = 0; i < before.size(); i++)
{
std::vector<int> simplifiedCriticalNodes;
destinationArc = before[i].first;
for(unsigned int j = 0; j < this->cancellationHistory.size(); j++)
{
for(unsigned int k = 0;
k < this->cancellationHistory[j].removedArcs.size(); k++)
{
if((destinationArc.first ==
this->cancellationHistory[j].removedArcs[k].first)
&&(destinationArc.second
== this->cancellationHistory[j].removedArcs[k].second))
{
// the arc has been involved in a cancellation
destinationArc = this->cancellationHistory[j].insertedArcs[0];
if(this->cancellationHistory[j].removedArcs.size() > 1)
{
if(((this->cancellationHistory[j].removedArcs[0].first
== destinationArc.first)
&&(this->cancellationHistory[j].removedArcs[1].second
== destinationArc.second))
||
((this->cancellationHistory[j].removedArcs[1].first
== destinationArc.first)
&&(this->cancellationHistory[j].removedArcs[0].second
== destinationArc.second)))
{
for(unsigned int l = 0;
l < this->cancellationHistory[j].removedArcs.size(); l++)
{
if((this->cancellationHistory[j].removedArcs[l].first
!= destinationArc.first)
&&(this->cancellationHistory[j].removedArcs[l].first
!= destinationArc.second))
{
// this critical node will become a degree two node, let's
// remember it
simplifiedCriticalNodes.push_back(
this->cancellationHistory[j].removedArcs[l].first);
}
if((this->cancellationHistory[j].removedArcs[l].second
!= destinationArc.first)
&&(this->cancellationHistory[j].removedArcs[l].second
!= destinationArc.second))
{
// same thing as above
simplifiedCriticalNodes.push_back(
this->cancellationHistory[j].removedArcs[l].second);
}
}
}
}
}
}
}
// at this point the deg2-nodes are in before[i].second
// now find the projection in the simplified graph
for(unsigned int j = 0; j < after.size(); j++)
{
if(destinationArc == after[j].first)
{
std::map<int, bool>::iterator aIt;
aIt = processedOutputArcs.find(j);
if(aIt == processedOutputArcs.end())
{
if(before[i].first == destinationArc)
{
// non-simplified arc
processedOutputArcs[j] = true;
after[j].second = before[i].second;
}
if(before[i].first != destinationArc)
{
// adding content of before[i].second to after[j].second
for(unsigned int k = 0; k < before[i].second.size(); k++)
{
if(!segmentedVertices[before[i].second[k]])
{
after[j].second.push_back(before[i].second[k]);
segmentedVertices[before[i].second[k]] = true;
}
}
}
for(unsigned int k = 0; k < simplifiedCriticalNodes.size(); k++)
{
if(!segmentedVertices[simplifiedCriticalNodes[k]])
{
after[j].second.push_back(simplifiedCriticalNodes[k]);
segmentedVertices[simplifiedCriticalNodes[k]] = true;
}
}
break;
}
}
}
}
// ensure the sorting on the arcs
for(unsigned int i = 0; i < after.size(); i++)
{
std::vector<std::pair<int, double> > scalarValues;
for(unsigned int j = 0; j < after[i].second.size(); j++)
{
std::pair<int, double> scalarVertex;
scalarVertex.first = after[i].second[j];
std::map<int, double>::iterator sIt;
sIt = ScalarField.find(scalarVertex.first);
if(sIt != ScalarField.end())
{
scalarVertex.second = sIt->second;
scalarValues.push_back(scalarVertex);
}
}
std::sort(scalarValues.begin(), scalarValues.end(), vtkReebGraphVertexSoS);
for(unsigned int j = 0; j < after[i].second.size(); j++)
after[i].second[j] = scalarValues[j].first;
}
// now construct the vtkMutableDirectedGraph
// first, clean up the current graph
while(this->Parent->GetNumberOfEdges()) this->Parent->RemoveEdge(0);
while(this->Parent->GetNumberOfVertices()) this->Parent->RemoveVertex(0);
this->Parent->GetVertexData()->RemoveArray("Vertex Ids");
this->Parent->GetEdgeData()->RemoveArray("Vertex Ids");
vtkIdType prevNodeId = -1, nodeId = 0;
while(prevNodeId != nodeId)
{
prevNodeId = nodeId;
nodeId = GetPreviousNodeId();
}
prevNodeId = -1;
vtkVariantArray *vertexProperties = vtkVariantArray::New();
vertexProperties->SetNumberOfValues(1);
vtkIdTypeArray *vertexIds = vtkIdTypeArray::New();
vertexIds->SetName("Vertex Ids");
this->Parent->GetVertexData()->AddArray(vertexIds);
std::map<int, int> vMap;
int vIt = 0;
while(prevNodeId != nodeId)
{
vtkIdType nodeVertexId = GetNodeVertexId(nodeId);
vMap[nodeVertexId] = vIt;
vertexProperties->SetValue(0, nodeVertexId);
this->Parent->AddVertex(vertexProperties);
prevNodeId = nodeId;
nodeId = GetNextNodeId();
vIt++;
}
vertexIds->Delete();
vertexProperties->Delete();
vtkVariantArray *deg2NodeIds = vtkVariantArray::New();
deg2NodeIds->SetName("Vertex Ids");
this->Parent->GetEdgeData()->AddArray(deg2NodeIds);
for(unsigned int i = 0; i < after.size(); i++)
{
std::map<int, int>::iterator downIt, upIt;
downIt = vMap.find(after[i].first.first);
upIt = vMap.find(after[i].first.second);
if((downIt != vMap.end())&&(upIt != vMap.end()))
{
vtkVariantArray *edgeProperties = vtkVariantArray::New();
vtkIdTypeArray *vertexList = vtkIdTypeArray::New();
vertexList->SetNumberOfValues(after[i].second.size());
for(unsigned int j = 0; j < after[i].second.size(); j++)
vertexList->SetValue(j, after[i].second[j]);
edgeProperties->SetNumberOfValues(1);
edgeProperties->SetValue(0, vertexList);
this->Parent->AddEdge(downIt->second, upIt->second, edgeProperties);
vertexList->Delete();
edgeProperties->Delete();
}
}
deg2NodeIds->Delete();
this->cancellationHistory.clear();
return 0;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Simplify(double simplificationThreshold,
vtkReebGraphSimplificationMetric *simplificationMetric)
{
int deletionNumber = 0;
this->Storage->cancellationHistory.clear();
this->Storage->historyOn = true;
this->Storage->ArcNumber = 0;
this->Storage->NodeNumber = 0;
deletionNumber =
this->Storage->SimplifyBranches(
simplificationThreshold, simplificationMetric)
+ this->Storage->SimplifyLoops(
simplificationThreshold, simplificationMetric)
+ this->Storage->SimplifyBranches(
simplificationThreshold, simplificationMetric);
this->Storage->historyOn = false;
return deletionNumber;
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::FlushLabels()
{
for (int A=1;A<this->MainArcTable.Size;A++)
{
if (!(this->GetArc(A)->LabelId1 == ((int)-2)))
this->GetArc(A)->LabelId0 = this->GetArc(A)->LabelId1=0;
}
if (this->MainLabelTable.Buffer)
{
free(this->MainLabelTable.Buffer);
}
this->MainLabelTable.Buffer=(vtkReebLabel*)malloc(sizeof(vtkReebLabel)*2);
this->MainLabelTable.Size=2;
this->MainLabelTable.Number=1;
this->MainLabelTable.FreeZone=1;
this->GetLabel(1)->HNext = ((int)-2);
this->GetLabel(1)->ArcId = 0;
}
//----------------------------------------------------------------------------
void vtkReebGraph::DeepCopy(vtkDataObject *src)
{
vtkReebGraph *srcG = vtkReebGraph::SafeDownCast(src);
if (srcG)
{
this->Storage->DeepCopy(srcG->Storage);
}
vtkMutableDirectedGraph::DeepCopy(srcG);
}
//----------------------------------------------------------------------------
void vtkReebGraph::Set(vtkMutableDirectedGraph *g)
{
vtkMutableDirectedGraph::DeepCopy(g);
}
//----------------------------------------------------------------------------
void vtkReebGraph::CloseStream()
{
vtkIdType prevArcId = -1, arcId = 0;
while(arcId != prevArcId)
{
prevArcId = arcId;
arcId = this->Storage->GetPreviousArcId();
}
prevArcId = -1;
// loop over the arcs and build the local adjacency map
// vertex -> (down vertices, up vertices)
std::map<int, std::pair<std::vector<int>, std::vector<int> > > localAdjacency;
while(prevArcId != arcId)
{
vtkIdType downVertexId, upVertexId;
downVertexId = this->Storage->GetNode((this->Storage->GetArc(arcId))->NodeId0)->VertexId;
upVertexId = this->Storage->GetNode((this->Storage->GetArc(arcId))->NodeId1)->VertexId;
std::map<int,
std::pair<std::vector<int>, std::vector<int> > >::iterator aIt;
// lookUp for the down vertex
aIt = localAdjacency.find(downVertexId);
if(aIt == localAdjacency.end())
{
std::pair<std::vector<int>, std::vector<int> > adjacencyItem;
adjacencyItem.second.push_back(upVertexId);
localAdjacency[downVertexId] = adjacencyItem;
}
else
{
aIt->second.second.push_back(upVertexId);
}
// same thing for the up vertex
aIt = localAdjacency.find(upVertexId);
if(aIt == localAdjacency.end())
{
std::pair<std::vector<int>, std::vector<int> > adjacencyItem;
adjacencyItem.first.push_back(downVertexId);
localAdjacency[upVertexId] = adjacencyItem;
}
else
{
aIt->second.first.push_back(downVertexId);
}
prevArcId = arcId;
arcId = this->Storage->GetNextArcId();
}
// now build the super-arcs with deg-2 nodes
// <vertex,vertex>,<vertex list> (arc, deg2 node list)
std::vector<std::pair<std::pair<int, int>, std::vector<int> > >
globalAdjacency;
std::map<int, std::pair<std::vector<int>, std::vector<int> > >::iterator aIt;
aIt = localAdjacency.begin();
do
{
if(!((aIt->second.first.size() == 1)&&(aIt->second.second.size() == 1)))
{
// not a deg-2 node
if(aIt->second.second.size())
{
// start the sweep up
for(unsigned int i = 0; i < aIt->second.second.size(); i++)
{
std::vector<int> deg2List;
std::map<int,
std::pair<std::vector<int>, std::vector<int> > >::iterator nextIt;
nextIt = localAdjacency.find(aIt->second.second[i]);
while((nextIt->second.first.size() == 1)
&&(nextIt->second.second.size() == 1))
{
deg2List.push_back(nextIt->first);
nextIt = localAdjacency.find(nextIt->second.second[0]);
}
globalAdjacency.push_back(
std::pair<std::pair<int, int>,
std::vector<int> >(std::pair<int, int>(
aIt->first, nextIt->first), deg2List));
}
}
}
aIt++;
}
while(aIt != localAdjacency.end());
// now cleanup the internal representation
int nmyend=0;
for (vtkIdType N=1;N<this->Storage->MainNodeTable.Size;N++)
{
// clear the node
if (this->Storage->GetNode(N)->ArcUpId == ((int)-2))
continue;
vtkReebGraph::Implementation::vtkReebNode* n = this->Storage->GetNode(N);
if (!n->IsFinalized)
{
nmyend++;
this->Storage->EndVertex(N);
}
}
this->Storage->FlushLabels();
// now construct the actual graph
vtkIdType prevNodeId = -1, nodeId = 0;
while(prevNodeId != nodeId)
{
prevNodeId = nodeId;
nodeId = this->Storage->GetPreviousNodeId();
}
prevNodeId = -1;
vtkVariantArray *vertexProperties = vtkVariantArray::New();
vertexProperties->SetNumberOfValues(1);
vtkIdTypeArray *vertexIds = vtkIdTypeArray::New();
vertexIds->SetName("Vertex Ids");
GetVertexData()->AddArray(vertexIds);
std::map<int, int> vMap;
int vIt = 0;
while(prevNodeId != nodeId)
{
vtkIdType nodeVertexId = this->Storage->GetNodeVertexId(nodeId);
vMap[nodeVertexId] = vIt;
vertexProperties->SetValue(0, nodeVertexId);
AddVertex(vertexProperties);
prevNodeId = nodeId;
nodeId = this->Storage->GetNextNodeId();
vIt++;
}
vertexIds->Delete();
vertexProperties->Delete();
vtkVariantArray *deg2NodeIds = vtkVariantArray::New();
deg2NodeIds->SetName("Vertex Ids");
GetEdgeData()->AddArray(deg2NodeIds);
for(unsigned int i = 0; i < globalAdjacency.size(); i++)
{
std::map<int, int>::iterator downIt, upIt;
downIt = vMap.find(globalAdjacency[i].first.first);
upIt = vMap.find(globalAdjacency[i].first.second);
if((downIt != vMap.end())&&(upIt != vMap.end()))
{
vtkVariantArray *edgeProperties = vtkVariantArray::New();
vtkIdTypeArray *vertexList = vtkIdTypeArray::New();
vertexList->SetNumberOfValues(globalAdjacency[i].second.size());
for(unsigned int j = 0; j < globalAdjacency[i].second.size(); j++)
vertexList->SetValue(j, globalAdjacency[i].second[j]);
edgeProperties->SetNumberOfValues(1);
edgeProperties->SetValue(0, vertexList);
AddEdge(downIt->second, upIt->second, edgeProperties);
vertexList->Delete();
edgeProperties->Delete();
}
}
deg2NodeIds->Delete();
}
//----------------------------------------------------------------------------
vtkReebGraph::vtkReebGraph()
{
this->Storage = new vtkReebGraph::Implementation;
this->Storage->Parent = this;
}
//----------------------------------------------------------------------------
vtkReebGraph::~vtkReebGraph()
{
delete this->Storage;
}
//----------------------------------------------------------------------------
void vtkReebGraph::PrintSelf(ostream& os, vtkIndent indent)
{
vtkObject::PrintSelf(os, indent);
os << indent << "Reeb graph general statistics:" << endl;
os << indent << indent << "Number Of Node(s): "
<< this->Storage->GetNumberOfNodes() << endl;
os << indent << indent << "Number Of Arc(s): "
<< this->Storage->GetNumberOfArcs() << endl;
os << indent << indent << "Number Of Connected Component(s): "
<< this->Storage->GetNumberOfConnectedComponents() << endl;
os << indent << indent << "Number Of Loop(s): "
<< this->Storage->GetNumberOfLoops() << endl;
}
void vtkReebGraph::PrintNodeData(ostream& os, vtkIndent indent)
{
vtkIdType arcId = 0, nodeId = 0;
os << indent << "Node Data:" << endl;
vtkIdType prevNodeId = -1;
// roll back to the beginning of the list
while(prevNodeId != nodeId){
prevNodeId = nodeId;
nodeId = this->Storage->GetPreviousNodeId();
}
prevNodeId = -1;
while(prevNodeId != nodeId)
{
prevNodeId = nodeId;
vtkIdList *downArcIdList = vtkIdList::New();
vtkIdList *upArcIdList = vtkIdList::New();
this->Storage->GetNodeDownArcIds(nodeId, downArcIdList);
this->Storage->GetNodeUpArcIds(nodeId, upArcIdList);
cout << indent << indent << "Node " << nodeId << ":" << endl;
cout << indent << indent << indent;
cout << "Vert: " << this->Storage->GetNodeVertexId(nodeId);
cout << ", Val: " << this->Storage->GetNodeScalarValue(nodeId);
cout << ", DwA:";
for(vtkIdType i = 0; i < downArcIdList->GetNumberOfIds(); i++)
cout << " " << this->Storage->GetArcDownNodeId(downArcIdList->GetId(i));
cout << ", UpA:";
for(vtkIdType i = 0; i < upArcIdList->GetNumberOfIds(); i++)
cout << " " << this->Storage->GetArcUpNodeId(upArcIdList->GetId(i));
cout << endl;
downArcIdList->Delete();
upArcIdList->Delete();
nodeId = this->Storage->GetNextNodeId();
}
os << indent << "Arc Data:" << endl;
vtkIdType prevArcId = -1;
arcId = 0;
// roll back to the beginning of the list
while(prevArcId != arcId){
prevArcId = arcId;
arcId = this->Storage->GetPreviousArcId();
}
prevArcId = -1;
while(prevArcId != arcId)
{
prevArcId = arcId;
cout << indent << indent << "Arc " << arcId << ":" << endl;
cout << indent << indent << indent;
cout << "Down: " << this->Storage->GetArcDownNodeId(arcId);
cout << ", Up: " << this->Storage->GetArcUpNodeId(arcId);
cout << ", Persistence: "
<< this->Storage->GetNodeScalarValue(this->Storage->GetArcUpNodeId(arcId))
- this->Storage->GetNodeScalarValue(
this->Storage->GetArcDownNodeId(arcId));
cout << endl;
arcId = this->Storage->GetNextArcId();
}
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::GetNodeDownArcIds(vtkIdType nodeId,
vtkIdList *arcIdList)
{
vtkIdType i = 0;
if(!arcIdList) return;
arcIdList->Reset();
for(vtkIdType arcId = this->GetNode(nodeId)->ArcDownId;
arcId; arcId = this->GetArc(arcId)->ArcDwId1)
{
arcIdList->InsertId(i, arcId);
i++;
}
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::GetNodeUpArcIds(vtkIdType nodeId,
vtkIdList *arcIdList)
{
vtkIdType i = 0;
if(!arcIdList) return;
for(vtkIdType arcId = this->GetNode(nodeId)->ArcUpId;
arcId; arcId = this->GetArc(arcId)->ArcDwId0)
{
arcIdList->InsertId(i, arcId);
i++;
}
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::FindLoops()
{
if (this->ArcLoopTable)
{
free(this->ArcLoopTable);
this->ArcLoopTable=0;
this->LoopNumber=0;
}
this->ConnectedComponentNumber=0;
int nstack=0,mstack=0;
int* stack=0;
char* Ntouch=(char*)malloc(sizeof(char)*this->MainNodeTable.Size);
char* Atouch=(char*)malloc(sizeof(char)*this->MainArcTable.Size);
memset(Ntouch,0,sizeof(char)*this->MainNodeTable.Size);
for(int Node=1;Node<this->MainNodeTable.Size;Node++)
{
// check that the node is clear
if (this->GetNode(Node)->ArcUpId == ((int)-2))
continue;
if (!Ntouch[Node])
{
++(this->ConnectedComponentNumber);
memset(Atouch,0,sizeof(bool)*this->MainArcTable.Size);
Ntouch[Node]=1;
nstack=0;
vtkReebGraphStackPush(Node);
while (vtkReebGraphStackSize())
{
int N=vtkReebGraphStackTop();
vtkReebGraphStackPop();
for (int dir=0;dir<=1;dir++)
{
for (int A = (!dir) ? (this->GetNode(N)->ArcDownId) : (this->GetNode(N)->ArcUpId);
A; A = (!dir) ? (this->GetArc(A)->ArcDwId1) : (this->GetArc(A)->ArcDwId0))
{
int M = (!dir) ? (this->GetArc(A)->NodeId0) : (this->GetArc(A)->NodeId1);
if (Atouch[A])
continue;
if (!Ntouch[M])
{
vtkReebGraphStackPush(M);
}
else
{
this->LoopNumber++;
this->ArcLoopTable = (vtkIdType *) realloc(this->ArcLoopTable,
sizeof(vtkIdType)*this->LoopNumber);
this->ArcLoopTable[this->LoopNumber-1]=A;
}
Atouch[A]=1;
Ntouch[M]=1;
}
}
}
}
}
free(stack);
free(Ntouch);
free(Atouch);
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::AddMeshVertex(vtkIdType vertexId,
double scalar)
{
static bool firstVertex = true;
ScalarField[vertexId] = scalar;
vtkIdType N0;
ResizeMainNodeTable(1);
//create a new node in the graph...
N0 = this->MainNodeTable.FreeZone;
this->MainNodeTable.FreeZone = this->GetNode(N0)->ArcDownId;
++(this->MainNodeTable.Number);
memset(this->GetNode(N0),0,sizeof(vtkReebNode));
vtkReebNode* node = this->GetNode(N0);
node->VertexId=vertexId;
node->Value = scalar;
node->ArcDownId=0;
node->ArcUpId=0;
node->IsFinalized = false;
if(firstVertex)
{
this->MinimumScalarValue = node->Value;
this->MaximumScalarValue = node->Value;
}
else
{
if(node->Value > this->MaximumScalarValue)
this->MaximumScalarValue = node->Value;
if(node->Value < this->MinimumScalarValue)
this->MinimumScalarValue = node->Value;
}
firstVertex = false;
return N0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindDwLabel(vtkIdType nodeId,
vtkReebLabelTag label)
{
for (vtkIdType arcId = this->GetNode(nodeId)->ArcDownId;
arcId; arcId = this->GetArc(arcId)->ArcDwId1)
{
for (vtkIdType labelId = this->GetArc(arcId)->LabelId0;
labelId; labelId = this->GetLabel(labelId)->HNext)
{
if (this->GetLabel(labelId)->label == label)
return labelId;
}
}
return 0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::FindUpLabel(vtkIdType nodeId,
vtkReebLabelTag label)
{
for (vtkIdType arcId = this->GetNode(nodeId)->ArcUpId;
arcId; arcId = this->GetArc(arcId)->ArcDwId0)
{
for (vtkIdType labelId = this->GetArc(arcId)->LabelId0;
labelId; labelId = this->GetLabel(labelId)->HNext)
{
if (this->GetLabel(labelId)->label==label)
return labelId;
}
}
return 0;
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::ResizeMainArcTable(int newSize)
{
int oldsize,i;
if ((this->MainArcTable.Size-this->MainArcTable.Number)< newSize)
{
oldsize=this->MainArcTable.Size;
if (!this->MainArcTable.Size) this->MainArcTable.Size= newSize;
while ((this->MainArcTable.Size-this->MainArcTable.Number)< newSize)
this->MainArcTable.Size<<=1;
this->MainArcTable.Buffer =
(vtkReebArc*)realloc(this->MainArcTable.Buffer,
sizeof(vtkReebArc)*this->MainArcTable.Size);
for (i=oldsize;i<this->MainArcTable.Size-1;i++)
{
this->GetArc(i)->LabelId0 = i+1;
// clear arc
this->GetArc(i)->LabelId1 = ((int)-2);
}
this->GetArc(i)->LabelId0 = this->MainArcTable.FreeZone;
// clear arc
this->GetArc(i)->LabelId1 = ((int)-2);
this->MainArcTable.FreeZone=oldsize;
}
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::ResizeMainLabelTable(int newSize)
{
int oldsize,i;
if ((this->MainLabelTable.Size-this->MainLabelTable.Number)< newSize)
{
oldsize=this->MainLabelTable.Size;
if (!this->MainLabelTable.Size) this->MainLabelTable.Size = newSize;
while ((this->MainLabelTable.Size-this->MainLabelTable.Number)< newSize)
this->MainLabelTable.Size<<=1;
this->MainLabelTable.Buffer = (vtkReebLabel*)realloc(this->MainLabelTable.Buffer, sizeof(vtkReebLabel)*this->MainLabelTable.Size);
for (i=oldsize;i<this->MainLabelTable.Size-1;i++)
{
this->GetLabel(i)->ArcId = i+1;
this->GetLabel(i)->HNext = ((int)-2);
}
this->GetLabel(i)->ArcId = this->MainLabelTable.FreeZone;
this->GetLabel(i)->HNext = ((int)-2);
this->MainLabelTable.FreeZone=oldsize;
}
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::AddPath(int nodeNumber,
vtkIdType* nodeOffset,
vtkReebLabelTag label)
{
vtkIdType i, Lprev, Ret=0;
this->ResizeMainArcTable(nodeNumber - 1);
if (label)
ResizeMainLabelTable(nodeNumber - 1);
Lprev=0;
for (i = 0; i < (nodeNumber - 1);i++)
{
vtkIdType N0 = nodeOffset[i ];
vtkIdType N1= nodeOffset[i + 1];
//create a new arc in the graph
int A = this->MainArcTable.FreeZone;
this->MainArcTable.FreeZone = this->GetArc(A)->LabelId0;
++(this->MainArcTable.Number);
memset(this->GetArc(A),0,sizeof(vtkReebArc));
vtkReebArc* arc = this->GetArc(A);
int L=0;
if (!Ret) Ret=A;
if (label)
{
vtkReebLabel* temporaryLabel;
//create a new label in the graph
L = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone = this->GetLabel(L)->ArcId;
++(this->MainLabelTable.Number);
memset(this->GetLabel(L),0,sizeof(vtkReebLabel));
temporaryLabel = this->GetLabel(L);
temporaryLabel->ArcId = A;
temporaryLabel->label=label;
temporaryLabel->VPrev=Lprev;
}
arc->NodeId0=N0;
arc->NodeId1=N1;
arc->LabelId0=arc->LabelId1=L;
vtkReebGraphAddUpArc(this,N0,A);
vtkReebGraphAddDownArc(this,N1,A);
if (label)
{
if (Lprev) this->GetLabel(Lprev)->VNext = L;
Lprev=L;
}
}
return Ret;
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::Collapse(vtkIdType startingNode,
vtkIdType endingNode,
vtkReebLabelTag startingLabel,
vtkReebLabelTag endingLabel)
{
int L0,L0n,L1,L1n;
int cont[3]={0,0,0},Case;
if (startingNode == endingNode)
return;
vtkReebNode* nstart = this->GetNode(startingNode);
vtkReebNode* nend = this->GetNode(endingNode);
if (!vtkReebGraphIsSmaller(this,startingNode,endingNode,nstart,nend))
{
vtkReebGraphSwapVars(int,startingNode,endingNode);
vtkReebGraphSwapVars(vtkReebNode* ,nstart,nend);
}
L0 = FindUpLabel(startingNode, startingLabel);
L1 = FindUpLabel(startingNode, endingLabel);
while (1)
{
int A0 = this->GetLabel(L0)->ArcId;
vtkReebArc* a0 = this->GetArc(A0);
int A1 = this->GetLabel(L1)->ArcId;
vtkReebArc* a1 = this->GetArc(A1);
vtkReebNode *down0 = this->GetNode(a0->NodeId0);
vtkReebNode *up0 = this->GetNode(a0->NodeId1);
vtkReebNode *up1 = this->GetNode(a1->NodeId1);
/* it is the same arc, no semplification is done */
if (A0==A1)
{
Case = 0;
L0n = this->GetLabel(L0)->VNext;
L1n = this->GetLabel(L1)->VNext;
}
/* there are two arcs connecting the same start-end node */
else if (A0 != A1 && a0->NodeId1 == a1->NodeId1)
{
Case = 1;
vtkReebGraphRemoveUpArc(this, a0->NodeId0, A1);
vtkReebGraphRemoveDownArc(this, a0->NodeId1, A1);
for (int Lcur = this->GetArc(A1)->LabelId0;
Lcur; Lcur = this->GetLabel(Lcur)->HNext)
{
this->GetLabel(Lcur)->ArcId = A0;
}
this->GetLabel(this->GetArc(A1)->LabelId0)->HPrev = this->GetArc(A0)->LabelId1;
this->GetLabel(this->GetArc(A0)->LabelId1)->HNext = this->GetArc(A1)->LabelId0;
this->GetArc(A0)->LabelId1 = this->GetArc(A1)->LabelId1;
this->GetArc(A1)->LabelId0=0;
this->GetArc(A1)->LabelId1=0;
//delete the arc from the graph...
this->GetArc(A1)->LabelId1 = ((int)-2);
this->GetArc(A1)->LabelId0 = this->MainArcTable.FreeZone;
this->MainArcTable.FreeZone=(A1);
--(this->MainArcTable.Number);
L0n = this->GetLabel(L0)->VNext;
L1n = this->GetLabel(L1)->VNext;
}
else
{
if(historyOn)
{
vtkReebCancellation c;
int downVertex, middleVertex, upVertex;
downVertex = down0->VertexId;
middleVertex = up0->VertexId;
upVertex = up1->VertexId;
c.removedArcs.push_back(std::pair<int, int>(downVertex, upVertex));
c.insertedArcs.push_back(std::pair<int, int>(downVertex, middleVertex));
c.insertedArcs.push_back(std::pair<int, int>(middleVertex, upVertex));
this->cancellationHistory.push_back(c);
}
// a more complicate situation, collapse reaching the less ending point of
// the arcs.
Case=2;
{
vtkReebNode* a0n1 = this->GetNode(a0->NodeId1);
vtkReebNode* a1n1 = this->GetNode(a1->NodeId1);
if (!vtkReebGraphIsSmaller(this,a0->NodeId1,a1->NodeId1,a0n1,a1n1))
{
vtkReebGraphSwapVars(int,A0,A1);
vtkReebGraphSwapVars(int,L0,L1);
vtkReebGraphSwapVars(vtkReebArc* ,a0,a1);
}
}
vtkReebGraphRemoveUpArc(this,a0->NodeId0,A1);
a1->NodeId0=a0->NodeId1;
vtkReebGraphAddUpArc(this,a0->NodeId1,A1);
//"replicate" labels from A1 to A0
for (int Lcur = this->GetArc(A1)->LabelId0;
Lcur;Lcur = this->GetLabel(Lcur)->HNext)
{
int Lnew;
ResizeMainLabelTable(1);
//create a new label in the graph
Lnew = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone = this->GetLabel(Lnew)->ArcId;
++(this->MainLabelTable.Number);
memset(this->GetLabel(Lnew),0,sizeof(vtkReebLabel));
vtkReebLabel* lnew = this->GetLabel(Lnew);
vtkReebLabel* lcur = this->GetLabel(Lcur);
lnew->ArcId = A0;
lnew->VPrev = lcur->VPrev;
if (lcur->VPrev)
this->GetLabel(lcur->VPrev)->VNext=Lnew;
lcur->VPrev = Lnew;
lnew->VNext = Lcur;
lnew->label = lcur->label;
lnew->HNext = 0;
lnew->HPrev = this->GetArc(A0)->LabelId1;
this->GetLabel(this->GetArc(A0)->LabelId1)->HNext = Lnew;
this->GetArc(A0)->LabelId1=Lnew;
}
L0n = this->GetLabel(L0)->VNext;
L1n=L1;
}
++cont[Case];
int N0=a0->NodeId0;
vtkReebNode* n0 = this->GetNode(N0);
if (n0->IsFinalized && vtkReebGraphIsRegular(this,n0))
{
if(historyOn)
{
vtkReebArc *up = this->GetArc(n0->ArcUpId),
*down = this->GetArc(n0->ArcDownId);
vtkReebCancellation c;
int v0, v1, v2, v3;
v0 = this->GetNode(up->NodeId0)->VertexId;
v1 = this->GetNode(up->NodeId1)->VertexId;
v2 = this->GetNode(down->NodeId0)->VertexId;
v3 = this->GetNode(down->NodeId1)->VertexId;
c.removedArcs.push_back(std::pair<int, int>(v0, v1));
c.removedArcs.push_back(std::pair<int, int>(v2, v3));
c.insertedArcs.push_back(std::pair<int, int>(v2, v1));
this->cancellationHistory.push_back(c);
}
this->CollapseVertex(N0, n0);
}
/* end condition */
if (a0->NodeId1 == endingNode)
{
vtkReebNode* nendNode = this->GetNode(endingNode);
if (nendNode->IsFinalized && vtkReebGraphIsRegular(this, nendNode))
{
if(historyOn)
{
vtkReebArc *up = this->GetArc(this->GetNode(endingNode)->ArcUpId),
*down = this->GetArc(this->GetNode(endingNode)->ArcDownId);
vtkReebCancellation c;
int v0, v1, v2, v3;
v0 = this->GetNode(up->NodeId0)->VertexId;
v1 = this->GetNode(up->NodeId1)->VertexId;
v2 = this->GetNode(down->NodeId0)->VertexId;
v3 = this->GetNode(down->NodeId1)->VertexId;
c.removedArcs.push_back(std::pair<int, int>(v0, v1));
c.removedArcs.push_back(std::pair<int, int>(v2, v3));
c.insertedArcs.push_back(std::pair<int, int>(v2, v1));
this->cancellationHistory.push_back(c);
}
this->CollapseVertex(endingNode, nendNode);
}
return;
}
L0 = L0n;
L1 = L1n;
}
}
void vtkReebGraph::Implementation::SimplifyLabels(const vtkIdType nodeId,
vtkReebLabelTag onlyLabel,
bool goDown, bool goUp)
{
static int nactivation=0;
++nactivation;
int A,L,Lnext;
vtkReebLabel *l;
vtkReebNode *n = this->GetNode(nodeId);
//I remove all Labels (paths) which start from me
if (goDown)
{
int Anext;
for (A=n->ArcDownId;A;A=Anext)
{
Anext = this->GetArc(A)->ArcDwId1;
for (L = this->GetArc(A)->LabelId0;L;L=Lnext)
{
Lnext = this->GetLabel(L)->HNext;
if (!(l = this->GetLabel(L))->VNext) //...starts from me!
{
if (!onlyLabel || onlyLabel == this->GetLabel(L)->label)
{
int Lprev;
for (int Lcur=L;Lcur;Lcur=Lprev)
{
vtkReebLabel* lcur = this->GetLabel(Lcur);
Lprev=lcur->VPrev;
int CurA=lcur->ArcId;
if (lcur->HPrev)
this->GetLabel(lcur->HPrev)->HNext = lcur->HNext;
else this->GetArc(CurA)->LabelId0 = lcur->HNext;
if (lcur->HNext)
this->GetLabel(lcur->HNext)->HPrev = lcur->HPrev;
else this->GetArc(CurA)->LabelId1 = lcur->HPrev;
//delete the label
this->GetLabel(Lcur)->HNext = ((int)-2);
this->GetLabel(Lcur)->ArcId = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone=(Lcur);
--(this->MainLabelTable.Number);
}
}
}
}
}
}
// Remove all Labels (paths) which start from here
if (goUp && !(this->GetNode(nodeId)->ArcUpId == ((int)-2)))
{
int Anext;
for (A=n->ArcUpId;A;A=Anext)
{
Anext = this->GetArc(A)->ArcDwId0;
for (L=this->GetArc(A)->LabelId0;L;L=Lnext)
{
Lnext = this->GetLabel(L)->HNext;
if (!(l = this->GetLabel(L))->VPrev) //...starts from me!
{
if (!onlyLabel || onlyLabel == this->GetLabel(L)->label)
{
int myLnext;
for (int Lcur = L; Lcur; Lcur = myLnext)
{
vtkReebLabel* lcur = this->GetLabel(Lcur);
myLnext = lcur->VNext;
int CurA = lcur->ArcId;
vtkReebArc* cura = this->GetArc(CurA);
if (lcur->HPrev)
{
this->GetLabel(lcur->HPrev)->HNext = lcur->HNext;
}
else
{
cura->LabelId0=lcur->HNext;
}
if (lcur->HNext)
{
this->GetLabel(lcur->HNext)->HPrev = lcur->HPrev;
}
else
{
cura->LabelId1=lcur->HPrev;
}
//delete the label...
this->GetLabel(Lcur)->HNext = ((int)-2);
this->GetLabel(Lcur)->ArcId = this->MainLabelTable.FreeZone;
this->MainLabelTable.FreeZone=(Lcur);
--(this->MainLabelTable.Number);
}
}
}
}
}
}
}
//----------------------------------------------------------------------------
void vtkReebGraph::Implementation::EndVertex(const vtkIdType N)
{
vtkReebNode *n = this->GetNode(N);
n->IsFinalized = true;
if (!(this->GetNode(N)->ArcUpId == ((int)-2)))
{
this->SimplifyLabels(N);
if (!(this->GetNode(N)->ArcUpId == ((int)-2)))
{
//special case for regular point. A node is regular if it has one
//arc down and one arc up. In this case it can disappear
if (vtkReebGraphIsRegular(this,n))
{
this->CollapseVertex(N, n);
}
}
}
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::AddMeshTetrahedron(vtkIdType vertex0Id,
double f0,
vtkIdType vertex1Id,
double f1,
vtkIdType vertex2Id,
double f2,
vtkIdType vertex3Id,
double f3)
{
vtkIdType vertex0, vertex1, vertex2, vertex3;
vertex0 = this->VertexStream[vertex0Id];
vertex1 = this->VertexStream[vertex1Id];
vertex2 = this->VertexStream[vertex2Id];
vertex3 = this->VertexStream[vertex3Id];
int N0 = this->VertexMap[vertex0];
int N1 = this->VertexMap[vertex1];
int N2 = this->VertexMap[vertex2];
int N3 = this->VertexMap[vertex3];
// Consistency less check
if (f3 < f2 || (f3==f2 && vertex3 < vertex2))
{
vtkReebGraphSwapVars(int,vertex2,vertex3);
vtkReebGraphSwapVars(int,N2,N3);
vtkReebGraphSwapVars(double,f2,f3);
}
if (f2 < f1 || (f2==f1 && vertex2 < vertex1))
{
vtkReebGraphSwapVars(int,vertex1,vertex2);
vtkReebGraphSwapVars(int,N1,N2);
vtkReebGraphSwapVars(double,f1,f2);
}
if (f1 < f0 || (f1==f0 && vertex1 < vertex0))
{
vtkReebGraphSwapVars(int,vertex0,vertex1);
vtkReebGraphSwapVars(int,N0,N1);
vtkReebGraphSwapVars(double,f0,f1);
}
if (f3 < f2 || (f3==f2 && vertex3 < vertex2))
{
vtkReebGraphSwapVars(int,vertex2,vertex3);
vtkReebGraphSwapVars(int,N2,N3);
vtkReebGraphSwapVars(double,f2,f3);
}
if (f2 < f1 || (f2==f1 && vertex2 < vertex1))
{
vtkReebGraphSwapVars(int,vertex1,vertex2);
vtkReebGraphSwapVars(int,N1,N2);
vtkReebGraphSwapVars(double,f1,f2);
}
if (f3 < f2 || (f3==f2 && vertex3 < vertex2))
{
vtkReebGraphSwapVars(int,vertex2,vertex3);
vtkReebGraphSwapVars(int,N2,N3);
vtkReebGraphSwapVars(double,f2,f3);
}
vtkIdType t0[]={vertex0, vertex1, vertex2},
t1[]={vertex0, vertex1, vertex3},
t2[]={vertex0, vertex2, vertex3},
t3[]={vertex1, vertex2, vertex3};
vtkIdType *cellIds[4];
cellIds[0] = t0;
cellIds[1] = t1;
cellIds[2] = t2;
cellIds[3] = t3;
for(int i=0; i < 3; i++)
{
int n0 = this->VertexMap[cellIds[i][0]],
n1 = this->VertexMap[cellIds[i][1]],
n2 = this->VertexMap[cellIds[i][2]];
vtkReebLabelTag Label01 =
((vtkReebLabelTag) cellIds[i][0])
| (((vtkReebLabelTag) cellIds[i][1])<<32);
vtkReebLabelTag Label12 =
((vtkReebLabelTag) cellIds[i][1])
| (((vtkReebLabelTag) cellIds[i][2])<<32);
vtkReebLabelTag Label02 =
((vtkReebLabelTag) cellIds[i][0])
| (((vtkReebLabelTag) cellIds[i][2])<<32);
if (!this->FindUpLabel(n0,Label01))
{
vtkIdType N01[] = {n0, n1};
this->AddPath(2, N01, Label01);
}
if (!this->FindUpLabel(n1,Label12))
{
vtkIdType N12[] = {n1,n2};
this->AddPath(2, N12, Label12);
}
if (!this->FindUpLabel(n0, Label02))
{
vtkIdType N02[] = {n0,n2};
this->AddPath(2, N02, Label02);
}
this->Collapse(n0,n1,Label01,Label02);
this->Collapse(n1,n2,Label12,Label02);
}
if (!(--(this->TriangleVertexMap[vertex0])))
this->EndVertex(N0);
if (!(--(this->TriangleVertexMap[vertex1])))
this->EndVertex(N1);
if (!(--(this->TriangleVertexMap[vertex2])))
this->EndVertex(N2);
if (!(--(this->TriangleVertexMap[vertex3])))
this->EndVertex(N3);
return 1;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::AddMeshTriangle(vtkIdType vertex0Id, double f0,
vtkIdType vertex1Id, double f1,
vtkIdType vertex2Id, double f2)
{
int vertex0 = this->VertexStream[vertex0Id],
vertex1 = this->VertexStream[vertex1Id],
vertex2 = this->VertexStream[vertex2Id];
int N0 = this->VertexMap[vertex0];
int N1 = this->VertexMap[vertex1];
int N2 = this->VertexMap[vertex2];
// Consistency less check
if (f2 < f1 || (f2==f1 && vertex2 < vertex1))
{
vtkReebGraphSwapVars(int,vertex1,vertex2);
vtkReebGraphSwapVars(int,N1,N2);
vtkReebGraphSwapVars(double,f1,f2);
}
if (f1 < f0 || (f1==f0 && vertex1 < vertex0))
{
vtkReebGraphSwapVars(int,vertex0,vertex1);
vtkReebGraphSwapVars(int,N0,N1);
vtkReebGraphSwapVars(double,f0,f1);
}
if (f2 < f1 || (f2==f1 && vertex2 < vertex1))
{
vtkReebGraphSwapVars(int,vertex1,vertex2);
vtkReebGraphSwapVars(int,N1,N2);
vtkReebGraphSwapVars(double,f1,f2);
}
vtkReebLabelTag Label01 =
((vtkReebLabelTag)vertex0) | (((vtkReebLabelTag)vertex1)<<32);
vtkReebLabelTag Label12 =
((vtkReebLabelTag)vertex1) | (((vtkReebLabelTag)vertex2)<<32);
vtkReebLabelTag Label02 =
((vtkReebLabelTag)vertex0) | (((vtkReebLabelTag)vertex2)<<32);
if (!this->FindUpLabel(N0,Label01))
{
vtkIdType N01[] = {N0, N1};
this->AddPath(2, N01, Label01);
}
if (!this->FindUpLabel(N1,Label12))
{
vtkIdType N12[] = {N1,N2};
this->AddPath(2, N12, Label12);
}
if (!this->FindUpLabel(N0, Label02))
{
vtkIdType N02[] = {N0,N2};
this->AddPath(2, N02, Label02);
}
this->Collapse(N0,N1,Label01,Label02);
this->Collapse(N1,N2,Label12,Label02);
if (!(--(this->TriangleVertexMap[vertex0])))
this->EndVertex(N0);
if (!(--(this->TriangleVertexMap[vertex1])))
this->EndVertex(N1);
if (!(--(this->TriangleVertexMap[vertex2])))
this->EndVertex(N2);
return 1;
}
//----------------------------------------------------------------------------
int vtkReebGraph::StreamTetrahedron( vtkIdType vertex0Id, double scalar0,
vtkIdType vertex1Id, double scalar1,
vtkIdType vertex2Id, double scalar2,
vtkIdType vertex3Id, double scalar3)
{
return this->Storage->StreamTetrahedron(vertex0Id, scalar0,
vertex1Id, scalar1,
vertex2Id, scalar2,
vertex3Id, scalar3);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::StreamTetrahedron( vtkIdType vertex0Id,
double scalar0,
vtkIdType vertex1Id,
double scalar1,
vtkIdType vertex2Id,
double scalar2,
vtkIdType vertex3Id,
double scalar3)
{
if(!this->VertexMapAllocatedSize)
{
// first allocate an arbitrary size
this->VertexMapAllocatedSize = vtkReebGraphInitialStreamSize;
this->VertexMap = (vtkIdType *) malloc(
sizeof(vtkIdType)*this->VertexMapAllocatedSize);
memset(this->VertexMap, 0, sizeof(vtkIdType)*this->VertexMapAllocatedSize);
this->VertexStream.clear();
}
else if(this->VertexMapSize >= this->VertexMapAllocatedSize - 4)
{
int oldSize = this->VertexMapAllocatedSize;
this->VertexMapAllocatedSize <<= 1;
this->VertexMap = (vtkIdType *) realloc(this->VertexMap,
sizeof(vtkIdType)*this->VertexMapAllocatedSize);
for(int i = oldSize; i < this->VertexMapAllocatedSize - 1; i++)
this->VertexMap[i] = 0;
}
// same thing with the triangle map
if(!this->TriangleVertexMapAllocatedSize)
{
// first allocate an arbitrary size
this->TriangleVertexMapAllocatedSize = vtkReebGraphInitialStreamSize;
this->TriangleVertexMap = (int *) malloc(
sizeof(int)*this->TriangleVertexMapAllocatedSize);
memset(this->TriangleVertexMap, 0,
sizeof(int)*this->TriangleVertexMapAllocatedSize);
}
else if(this->TriangleVertexMapSize >=
this->TriangleVertexMapAllocatedSize - 4)
{
int oldSize = this->TriangleVertexMapAllocatedSize;
this->TriangleVertexMapAllocatedSize <<= 1;
this->TriangleVertexMap = (int *) realloc(this->TriangleVertexMap,
sizeof(int)*this->TriangleVertexMapAllocatedSize);
for(int i = oldSize; i < this->TriangleVertexMapAllocatedSize - 1; i++)
this->TriangleVertexMap[i] = 0;
}
// Add the vertices to the stream
std::map<int, int>::iterator sIter;
// vertex0
sIter = this->VertexStream.find(vertex0Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex0Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex0Id, scalar0);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
// vertex1
sIter = this->VertexStream.find(vertex1Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex1Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex1Id, scalar1);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
// vertex2
sIter = this->VertexStream.find(vertex2Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex2Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex2Id, scalar2);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
// vertex3
sIter = this->VertexStream.find(vertex3Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex3Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex3Id, scalar3);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
this->AddMeshTetrahedron(vertex0Id, scalar0, vertex1Id, scalar1,
vertex2Id, scalar2, vertex3Id, scalar3);
return 0;
}
//----------------------------------------------------------------------------
int vtkReebGraph::StreamTriangle( vtkIdType vertex0Id, double scalar0,
vtkIdType vertex1Id, double scalar1,
vtkIdType vertex2Id, double scalar2)
{
return this->Storage->StreamTriangle(vertex0Id, scalar0,
vertex1Id, scalar1,
vertex2Id, scalar2);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::StreamTriangle(vtkIdType vertex0Id,
double scalar0,
vtkIdType vertex1Id,
double scalar1,
vtkIdType vertex2Id,
double scalar2)
{
if(!this->VertexMapAllocatedSize)
{
// first allocate an arbitrary size
this->VertexMapAllocatedSize = vtkReebGraphInitialStreamSize;
this->VertexMap = (vtkIdType *) malloc(
sizeof(vtkIdType)*this->VertexMapAllocatedSize);
memset(this->VertexMap, 0, sizeof(vtkIdType)*this->VertexMapAllocatedSize);
}
else if(this->VertexMapSize >= this->VertexMapAllocatedSize - 3)
{
int oldSize = this->VertexMapAllocatedSize;
this->VertexMapAllocatedSize <<= 1;
this->VertexMap = (vtkIdType *) realloc(this->VertexMap,
sizeof(vtkIdType)*this->VertexMapAllocatedSize);
for(int i = oldSize; i < this->VertexMapAllocatedSize - 1; i++)
this->VertexMap[i] = 0;
}
// same thing with the triangle map
if(!this->TriangleVertexMapAllocatedSize)
{
// first allocate an arbitrary size
this->TriangleVertexMapAllocatedSize = vtkReebGraphInitialStreamSize;
this->TriangleVertexMap = (int *) malloc(
sizeof(int)*this->TriangleVertexMapAllocatedSize);
memset(this->TriangleVertexMap, 0,
sizeof(int)*this->TriangleVertexMapAllocatedSize);
}
else if(this->TriangleVertexMapSize >=
this->TriangleVertexMapAllocatedSize - 3)
{
int oldSize = this->TriangleVertexMapAllocatedSize;
this->TriangleVertexMapAllocatedSize <<= 1;
this->TriangleVertexMap = (int *) realloc(this->TriangleVertexMap,
sizeof(int)*this->TriangleVertexMapAllocatedSize);
for(int i = oldSize; i < this->TriangleVertexMapAllocatedSize - 1; i++)
this->TriangleVertexMap[i] = 0;
}
// Add the vertices to the stream
std::map<int, int>::iterator sIter;
// vertex0
sIter = this->VertexStream.find(vertex0Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex0Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex0Id, scalar0);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
// vertex1
sIter = this->VertexStream.find(vertex1Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex1Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex1Id, scalar1);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
// vertex2
sIter = this->VertexStream.find(vertex2Id);
if(sIter == this->VertexStream.end())
{
// this vertex hasn't been streamed yet, let's add it
this->VertexStream[vertex2Id] = this->VertexMapSize;
this->VertexMap[this->VertexMapSize]
= this->AddMeshVertex(vertex2Id, scalar2);
this->VertexMapSize++;
this->TriangleVertexMapSize++;
}
this->AddMeshTriangle(vertex0Id, scalar0, vertex1Id, scalar1,
vertex2Id, scalar2);
return 0;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkPolyData *mesh, vtkDataArray *scalarField)
{
for(vtkIdType i = 0; i < mesh->GetNumberOfCells(); i++)
{
vtkCell *triangle = mesh->GetCell(i);
vtkIdList *trianglePointList = triangle->GetPointIds();
if(trianglePointList->GetNumberOfIds() != 3)
return vtkReebGraph::ERR_NOT_A_SIMPLICIAL_MESH;
StreamTriangle(trianglePointList->GetId(0),
scalarField->GetComponent(trianglePointList->GetId(0),0),
trianglePointList->GetId(1),
scalarField->GetComponent(trianglePointList->GetId(1),0),
trianglePointList->GetId(2),
scalarField->GetComponent(trianglePointList->GetId(2),0));
}
this->Storage->inputMesh = mesh;
this->Storage->inputScalarField = scalarField;
this->CloseStream();
return 0;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkUnstructuredGrid *mesh, vtkDataArray *scalarField)
{
for(vtkIdType i = 0; i < mesh->GetNumberOfCells(); i++)
{
vtkCell *tet = mesh->GetCell(i);
vtkIdList *tetPointList = tet->GetPointIds();
if(tetPointList->GetNumberOfIds() != 4)
return vtkReebGraph::ERR_NOT_A_SIMPLICIAL_MESH;
StreamTetrahedron(tetPointList->GetId(0),
scalarField->GetComponent(tetPointList->GetId(0),0),
tetPointList->GetId(1),
scalarField->GetComponent(tetPointList->GetId(1),0),
tetPointList->GetId(2),
scalarField->GetComponent(tetPointList->GetId(2),0),
tetPointList->GetId(3),
scalarField->GetComponent(tetPointList->GetId(3),0));
}
this->Storage->inputMesh = mesh;
this->Storage->inputScalarField = scalarField;
this->CloseStream();
return 0;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::GetNumberOfArcs()
{
if(!this->ArcNumber)
for(vtkIdType arcId = 1; arcId < this->MainArcTable.Size; arcId++)
{
// check if arc is cleared
if(!(this->GetArc(arcId)->LabelId1 == ((int)-2)))
this->ArcNumber++;
}
return this->ArcNumber;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::GetNumberOfConnectedComponents()
{
if(!this->ArcLoopTable) this->FindLoops();
return this->ConnectedComponentNumber;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::GetNumberOfNodes()
{
if(!this->NodeNumber)
for(vtkIdType nodeId = 1; nodeId < this->MainNodeTable.Size; nodeId++)
{
// check if node is cleared
if(!(this->GetNode(nodeId)->ArcUpId == ((int)-2)))
this->NodeNumber++;
}
return this->NodeNumber;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetNextNodeId()
{
for(vtkIdType nodeId = this->currentNodeId + 1;
nodeId < this->MainNodeTable.Size; nodeId++)
{
// check if node is cleared
if(!(this->GetNode(nodeId)->ArcUpId == ((int)-2)))
{
this->currentNodeId = nodeId;
return this->currentNodeId;
}
}
return this->currentNodeId;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetPreviousNodeId()
{
if(!this->currentNodeId)
{
return this->GetNextNodeId();
}
for(vtkIdType nodeId = this->currentNodeId - 1; nodeId > 0; nodeId--)
{
// check if node is cleared
if(!(this->GetNode(nodeId)->ArcUpId == ((int)-2)))
{
this->currentNodeId = nodeId;
return this->currentNodeId;
}
}
return this->currentNodeId;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetNextArcId()
{
for(vtkIdType arcId = this->currentArcId + 1; arcId < this->MainArcTable.Size; arcId++)
{
// check if arc is cleared
if(!(this->GetArc(arcId)->LabelId1 == ((int)-2)))
{
this->currentArcId = arcId;
return this->currentArcId;
}
}
return this->currentArcId;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetPreviousArcId()
{
if(!this->currentArcId)
{
return this->GetNextArcId();
}
for(vtkIdType arcId = this->currentArcId - 1; arcId > 0; arcId--)
{
// check if arc is cleared
if(!(this->GetArc(arcId)->LabelId1 == ((int)-2)))
{
this->currentArcId = arcId;
return this->currentArcId;
}
}
return this->currentArcId;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetArcDownNodeId(vtkIdType arcId)
{
return (this->GetArc(arcId))->NodeId0;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetArcUpNodeId(vtkIdType arcId)
{
return (this->GetArc(arcId))->NodeId1;
}
//----------------------------------------------------------------------------
double vtkReebGraph::Implementation::GetNodeScalarValue(vtkIdType nodeId)
{
return (this->GetNode(nodeId))->Value;
}
//----------------------------------------------------------------------------
vtkIdType vtkReebGraph::Implementation::GetNodeVertexId(vtkIdType nodeId)
{
return (this->GetNode(nodeId))->VertexId;
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkPolyData *mesh, vtkIdType scalarFieldId)
{
vtkPointData *pointData = mesh->GetPointData();
vtkDataArray *scalarField = pointData->GetArray(scalarFieldId);
if(!scalarField) return vtkReebGraph::ERR_NO_SUCH_FIELD;
return this->Build(mesh, scalarField);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkUnstructuredGrid *mesh, vtkIdType scalarFieldId)
{
vtkPointData *pointData = mesh->GetPointData();
vtkDataArray *scalarField = pointData->GetArray(scalarFieldId);
if(!scalarField) return vtkReebGraph::ERR_NO_SUCH_FIELD;
return this->Build(mesh, scalarField);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkPolyData *mesh, const char* scalarFieldName)
{
int scalarFieldId = 0;
vtkPointData *pointData = mesh->GetPointData();
vtkDataArray *scalarField =
pointData->GetArray(scalarFieldName, scalarFieldId);
if(!scalarField) return vtkReebGraph::ERR_NO_SUCH_FIELD;
return this->Build(mesh, scalarField);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Build(vtkUnstructuredGrid *mesh, const char* scalarFieldName)
{
int scalarFieldId = 0;
vtkPointData *pointData = mesh->GetPointData();
vtkDataArray *scalarField =
pointData->GetArray(scalarFieldName, scalarFieldId);
if(!scalarField) return vtkReebGraph::ERR_NO_SUCH_FIELD;
return this->Build(mesh, scalarField);
}
//----------------------------------------------------------------------------
int vtkReebGraph::Implementation::GetNumberOfLoops()
{
if(!this->ArcLoopTable) this->FindLoops();
return this->LoopNumber - this->RemovedLoopNumber;
}
//----------------------------------------------------------------------------
inline vtkIdType vtkReebGraph::Implementation::AddArc(vtkIdType nodeId0,
vtkIdType nodeId1)
{
if (!vtkReebGraphIsSmaller(this, nodeId0, nodeId1,
this->GetNode(nodeId0),
this->GetNode(nodeId1)))
vtkReebGraphSwapVars(vtkIdType, nodeId0, nodeId1);
vtkIdType nodevtkReebArcble[] = { nodeId0, nodeId1};
return AddPath(2, nodevtkReebArcble, 0);
}