/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestSimple3DCirclesStrategy.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.

=========================================================================*/

#include "vtkActor.h"
#include "vtkEdgeLayout.h"
#include "vtkGraphLayout.h"
#include "vtkGraphToPolyData.h"
#include "vtkMutableDirectedGraph.h"
#include "vtkPassThroughEdgeStrategy.h"
#include "vtkPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkRandomGraphSource.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderer.h"
#include "vtkSimple3DCirclesStrategy.h"
#include "vtkSmartPointer.h"
#include "vtkVertexGlyphFilter.h"

int TestSimple3DCirclesStrategy(int argc, char* argv[])
{
  // graph
  vtkSmartPointer<vtkMutableDirectedGraph> graph = vtkSmartPointer<vtkMutableDirectedGraph>::New();
  // mapper
  vtkSmartPointer<vtkPolyDataMapper> edgeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkPolyDataMapper> vertMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkPassThroughEdgeStrategy> edgeStrategy =
    vtkSmartPointer<vtkPassThroughEdgeStrategy>::New();
  vtkSmartPointer<vtkSimple3DCirclesStrategy> strategy =
    vtkSmartPointer<vtkSimple3DCirclesStrategy>::New();
  vtkSmartPointer<vtkGraphLayout> layout = vtkSmartPointer<vtkGraphLayout>::New();
  vtkSmartPointer<vtkEdgeLayout> edgeLayout = vtkSmartPointer<vtkEdgeLayout>::New();
  vtkSmartPointer<vtkGraphToPolyData> graphToPoly = vtkSmartPointer<vtkGraphToPolyData>::New();
  vtkSmartPointer<vtkVertexGlyphFilter> vertGlyph = vtkSmartPointer<vtkVertexGlyphFilter>::New();
  vtkSmartPointer<vtkActor> edgeActor = vtkSmartPointer<vtkActor>::New();
  vtkSmartPointer<vtkActor> vertActor = vtkSmartPointer<vtkActor>::New();
  vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renwin = vtkSmartPointer<vtkRenderWindow>::New();
  vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renwin);
  renwin->SetMultiSamples(0);

  // Vertices:
  // layer 0: 0,1,2
  // layer 1: 3,4,5,6
  // layer 2: 7,8,9
  // standalone: 10,11
  for (int i = 0; i < 12; ++i)
    graph->AddVertex();

  // Edges:
  // layer 0 -> 1
  graph->AddEdge(0, 4);
  graph->AddEdge(0, 6);
  graph->AddEdge(1, 5);
  graph->AddEdge(1, 6);
  graph->AddEdge(2, 3);
  graph->AddEdge(2, 4);
  graph->AddEdge(2, 5);
  // layer 1 -> 2
  graph->AddEdge(3, 8);
  graph->AddEdge(3, 7);
  graph->AddEdge(4, 9);
  graph->AddEdge(4, 8);
  graph->AddEdge(5, 7);
  // layer 0 -> 2
  graph->AddEdge(0, 9);

  strategy->SetMethod(vtkSimple3DCirclesStrategy::FixedDistanceMethod);
  strategy->AutoHeightOn();
  strategy->SetDirection(0.0, -1.0, 0.0);
  strategy->SetMinimumDegree(45.0);
  layout->SetInputData(graph);
  layout->SetLayoutStrategy(strategy);

  // Uncomment the following for a more interesting result!
#if 0
  vtkSmartPointer<vtkRandomGraphSource> src = vtkSmartPointer<vtkRandomGraphSource>::New();
  src->SetNumberOfVertices(1000);
  src->SetNumberOfEdges(0);
  src->SetDirected(true);
  src->SetStartWithTree(true);
  layout->SetInputConnection( src->GetOutputPort() );
#endif

  edgeLayout->SetInputConnection(layout->GetOutputPort());
  edgeLayout->SetLayoutStrategy(edgeStrategy);
  edgeLayout->Update();

  graphToPoly->EdgeGlyphOutputOn();
  graphToPoly->SetInputConnection(edgeLayout->GetOutputPort());
  vertGlyph->SetInputConnection(edgeLayout->GetOutputPort());

  edgeMapper->ScalarVisibilityOff();
  edgeMapper->SetInputConnection(graphToPoly->GetOutputPort());
  edgeActor->GetProperty()->SetColor(0.75, 0.75, 0.75);
  edgeActor->GetProperty()->SetOpacity(1.0);
  edgeActor->GetProperty()->SetLineWidth(2);
  edgeActor->PickableOff();
  edgeActor->SetMapper(edgeMapper);
  ren->AddActor(edgeActor);

  vertMapper->ScalarVisibilityOff();
  vertMapper->SetInputConnection(vertGlyph->GetOutputPort());
  vertActor->GetProperty()->SetColor(0.5, 0.5, 0.5);
  vertActor->GetProperty()->SetOpacity(1.0);
  vertActor->GetProperty()->SetPointSize(7);
  vertActor->PickableOff();
  vertActor->SetMapper(vertMapper);
  ren->AddActor(vertActor);

  renwin->SetSize(800, 600);

  renwin->AddRenderer(ren);
  renwin->Render();

  int retVal = vtkRegressionTestImage(renwin);
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
  {
    iren->Start();
  }

  return !retVal;
}
