// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-FileCopyrightText: Copyright 2008 Sandia Corporation // SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Sandia-USGov #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 #include #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; std::cerr << "Testing vtkCircularLayoutStrategy..." << std::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 = std::abs(dist); if (dist > eps || pt[2] != 0.0) { std::cerr << "ERROR: Point " << i << " is not on the unit circle." << std::endl; errors++; } } std::cerr << "...done." << std::endl; std::cerr << "Testing vtkFast2DLayoutStrategy..." << std::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) { std::cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << std::endl; errors++; } if (pt[2] != 0.0) { std::cerr << "ERROR: Point " << u << " not on the xy plane" << std::endl; errors++; } if (pt2[2] != 0.0) { std::cerr << "ERROR: Point " << v << " not on the xy plane" << std::endl; errors++; } } std::cerr << "...done." << std::endl; std::cerr << "Testing vtkForceDirectedLayoutStrategy..." << std::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) { std::cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << std::endl; errors++; } } std::cerr << "...done." << std::endl; std::cerr << "Testing vtkPassThroughLayoutStrategy..." << std::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) { std::cerr << "ERROR: Point " << i << " is not 0,0,0." << std::endl; errors++; } } std::cerr << "...done." << std::endl; std::cerr << "Testing vtkRandomLayoutStrategy..." << std::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]) { std::cerr << "ERROR: Point " << i << " is not within the bounds." << std::endl; errors++; } } std::cerr << "...done." << std::endl; std::cerr << "Testing vtkSimple2DLayoutStrategy..." << std::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) { std::cerr << "ERROR: Edge " << u << "," << v << " distance is " << dist << " but resting distance is " << length << std::endl; errors++; } if (pt[2] != 0.0) { std::cerr << "ERROR: Point " << u << " not on the xy plane" << std::endl; errors++; } if (pt2[2] != 0.0) { std::cerr << "ERROR: Point " << v << " not on the xy plane" << std::endl; errors++; } } std::cerr << "...done." << std::endl; return errors; }