/*========================================================================= Program: Visualization Toolkit Module: TestGraphLayoutStrategy.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 2008 Sandia Corporation. Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains certain rights in this software. -------------------------------------------------------------------------*/ #include "vtkCircularLayoutStrategy.h" #include "vtkEdgeListIterator.h" #include "vtkFast2DLayoutStrategy.h" #include "vtkForceDirectedLayoutStrategy.h" #include "vtkGraphLayout.h" #include "vtkMath.h" #include "vtkPassThroughLayoutStrategy.h" #include "vtkRandomGraphSource.h" #include "vtkRandomLayoutStrategy.h" #include "vtkSimple2DLayoutStrategy.h" #include "vtkSmartPointer.h" #include "vtkTestUtilities.h" #include "vtkTreeLayoutStrategy.h" #define VTK_CREATE(type, name) vtkSmartPointer name = vtkSmartPointer::New() int TestGraphLayoutStrategy(int vtkNotUsed(argc), char* vtkNotUsed(argv)[]) { int errors = 0; // Create input graph vtkIdType numVert = 100; vtkIdType numEdges = 150; VTK_CREATE(vtkRandomGraphSource, source); source->SetNumberOfVertices(numVert); source->SetNumberOfEdges(numEdges); VTK_CREATE(vtkGraphLayout, layout); layout->SetInputConnection(source->GetOutputPort()); vtkGraph* output = nullptr; double pt[3] = { 0.0, 0.0, 0.0 }; double pt2[3] = { 0.0, 0.0, 0.0 }; double eps = 1.0e-6; double length = 0.0; double tol = 50.0; cerr << "Testing vtkCircularLayoutStrategy..." << endl; VTK_CREATE(vtkCircularLayoutStrategy, circular); layout->SetLayoutStrategy(circular); layout->Update(); output = layout->GetOutput(); for (vtkIdType i = 0; i < numVert; i++) { output->GetPoint(i, pt); double dist = pt[0] * pt[0] + pt[1] * pt[1] - 1.0; dist = dist > 0 ? dist : -dist; if (dist > eps || pt[2] != 0.0) { cerr << "ERROR: Point " << i << " is not on the unit circle." << endl; errors++; } } cerr << "...done." << endl; cerr << "Testing vtkFast2DLayoutStrategy..." << endl; VTK_CREATE(vtkFast2DLayoutStrategy, fast); fast->SetRestDistance(1.0f); length = fast->GetRestDistance(); layout->SetLayoutStrategy(fast); layout->Update(); output = layout->GetOutput(); VTK_CREATE(vtkEdgeListIterator, edges); output->GetEdges(edges); while (edges->HasNext()) { vtkEdgeType e = edges->Next(); vtkIdType u = e.Source; vtkIdType v = e.Target; output->GetPoint(u, pt); output->GetPoint(v, pt2); double dist = sqrt(vtkMath::Distance2BetweenPoints(pt, pt2)); if (dist < length / tol || dist > length * tol) { cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << endl; errors++; } if (pt[2] != 0.0) { cerr << "ERROR: Point " << u << " not on the xy plane" << endl; errors++; } if (pt2[2] != 0.0) { cerr << "ERROR: Point " << v << " not on the xy plane" << endl; errors++; } } cerr << "...done." << endl; cerr << "Testing vtkForceDirectedLayoutStrategy..." << endl; VTK_CREATE(vtkForceDirectedLayoutStrategy, force); length = pow(1.0 / numVert, 1.0 / 3.0); layout->SetLayoutStrategy(force); layout->Update(); output = layout->GetOutput(); output->GetEdges(edges); while (edges->HasNext()) { vtkEdgeType e = edges->Next(); vtkIdType u = e.Source; vtkIdType v = e.Target; output->GetPoint(u, pt); output->GetPoint(v, pt2); double dist = sqrt(vtkMath::Distance2BetweenPoints(pt, pt2)); if (dist < length / tol || dist > length * tol) { cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << endl; errors++; } } cerr << "...done." << endl; cerr << "Testing vtkPassThroughLayoutStrategy..." << endl; VTK_CREATE(vtkPassThroughLayoutStrategy, pass); layout->SetLayoutStrategy(pass); layout->Update(); output = layout->GetOutput(); for (vtkIdType i = 0; i < numVert; i++) { output->GetPoint(i, pt); if (pt[0] != 0.0 || pt[1] != 0.0 || pt[2] != 0.0) { cerr << "ERROR: Point " << i << " is not 0,0,0." << endl; errors++; } } cerr << "...done." << endl; cerr << "Testing vtkRandomLayoutStrategy..." << endl; VTK_CREATE(vtkRandomLayoutStrategy, random); double bounds[6] = { 0, 0, 0, 0, 0, 0 }; random->GetGraphBounds(bounds); layout->SetLayoutStrategy(random); layout->Update(); output = layout->GetOutput(); for (vtkIdType i = 0; i < numVert; i++) { output->GetPoint(i, pt); if (pt[0] < bounds[0] || pt[0] > bounds[1] || pt[1] < bounds[2] || pt[1] > bounds[3] || pt[2] < bounds[4] || pt[2] > bounds[5]) { cerr << "ERROR: Point " << i << " is not within the bounds." << endl; errors++; } } cerr << "...done." << endl; cerr << "Testing vtkSimple2DLayoutStrategy..." << endl; VTK_CREATE(vtkSimple2DLayoutStrategy, simple); simple->SetRestDistance(1.0f); length = simple->GetRestDistance(); layout->SetLayoutStrategy(simple); layout->Update(); output = layout->GetOutput(); output->GetEdges(edges); while (edges->HasNext()) { vtkEdgeType e = edges->Next(); vtkIdType u = e.Source; vtkIdType v = e.Target; output->GetPoint(u, pt); output->GetPoint(v, pt2); double dist = sqrt(vtkMath::Distance2BetweenPoints(pt, pt2)); if (dist < length / tol || dist > length * tol) { cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << endl; errors++; } if (pt[2] != 0.0) { cerr << "ERROR: Point " << u << " not on the xy plane" << endl; errors++; } if (pt2[2] != 0.0) { cerr << "ERROR: Point " << v << " not on the xy plane" << endl; errors++; } } cerr << "...done." << endl; return errors; }