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

  Program:   Visualization Toolkit
  Module:    cmbContourTest.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 "vtkCMBArc.h"
#include "vtkCMBArcEndNode.h"
#include "vtkCMBArcProvider.h"
#include "vtkCMBArcManager.h"
#include "vtkCMBArcUpdateOperator.h"

#include "vtkActor.h"
#include  "vtkCellArray.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSmartPointer.h"
#include "vtkRegressionTestImage.h"

namespace
{

vtkPolyData* moved_arc()
  {
  //Should look like the letter: p
  //this will be the stalk
  vtkPolyData* arcP = vtkPolyData::New();
  vtkPoints *points = vtkPoints::New();
  points->InsertNextPoint(5,0,0);
  points->InsertNextPoint(2.5,2.5,5);
  arcP->SetPoints(points);
  points->FastDelete();

  vtkCellArray *lines = vtkCellArray::New();
  lines->InsertNextCell(2);
  lines->InsertCellPoint(0);
  lines->InsertCellPoint(1);
  arcP->SetLines(lines);
  lines->FastDelete();

  return arcP;
  }
}

int ArcVisUpdateTest1( int argc, char *argv[] )
{
  vtkSmartPointer<vtkTesting> testHelper = vtkSmartPointer<vtkTesting>::New();

  double bl[3]={0,0,0};
  double br[3]={5,0,0};
  double tl[3]={0,5,0};
  double tr[3]={5,5,0};

  vtkCMBArc *bottomArc = vtkCMBArc::New();
  bottomArc->SetEndNode(0,bl);
  bottomArc->SetEndNode(1,br);

  vtkCMBArc *topArc = vtkCMBArc::New();
  topArc->SetEndNode(0,tr);
  topArc->InsertNextPoint(4,5,0);
  topArc->InsertNextPoint(3,5,0);
  topArc->InsertNextPoint(2,5,0);
  topArc->InsertNextPoint(1,5,0);
  topArc->SetEndNode(1,tl);

  double tlhalf[3]={0,2.5,0};
  vtkCMBArc *leftArc1 = vtkCMBArc::New();
  leftArc1->SetEndNode(0,bl);
  leftArc1->SetEndNode(1,tlhalf);

  vtkCMBArc *leftArc2 = vtkCMBArc::New();
  leftArc2->SetEndNode(0,tlhalf);
  leftArc2->InsertNextPoint(0,3,0);
  leftArc2->InsertNextPoint(0,4,0);
  leftArc2->SetEndNode(1,tl);

  double trhalf[3]={5,2.5,0};
  vtkCMBArc *rightArc1 = vtkCMBArc::New();
  rightArc1->SetEndNode(0,br);
  rightArc1->SetEndNode(1,trhalf);

  vtkCMBArc *rightArc2 = vtkCMBArc::New();
  rightArc2->SetEndNode(0,trhalf);
  rightArc2->InsertNextPoint(5,3,0);
  rightArc2->InsertNextPoint(5,3.5,0);
  rightArc2->InsertNextPoint(5,4,0);
  rightArc2->InsertNextPoint(5,4.5,0);
  rightArc2->SetEndNode(1,tr);

  //render the box
  vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
  renWin->AddRenderer(renderer);

  vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  iren->SetRenderWindow(renWin);

  renderer->SetBackground(0.1, 0.2, 0.4);
  renWin->SetSize(600, 600);

  //create a mapper and actor for each arc
  int numArcs = vtkCMBArcManager::GetInstance()->GetNumberOfArcs();
  for (int i=0; i < numArcs; i++)
    {
    vtkSmartPointer<vtkCMBArcProvider> filter =
      vtkSmartPointer<vtkCMBArcProvider>::New();
    filter->SetArcId(i);

    vtkSmartPointer<vtkPolyDataMapper> mapper =
      vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection( filter->GetOutputPort() );

    vtkSmartPointer<vtkActor> actor =
      vtkSmartPointer<vtkActor>::New();
    actor->SetMapper( mapper );
    renderer->AddViewProp( actor );
    }
  iren->Initialize();
  renWin->Render();

  //Move the left arc to the middle point in preperation
  //of a merge with the update operator
  double middlePoint[3] = {2.5,2.5,5};
  leftArc1->MoveEndNode(1,middlePoint);

  //Merge two end nodes together and make sure everything refreshes
  //correctly
  //take a loop arc, and convert it to an arc
  vtkPolyData* mArc = moved_arc();
  vtkSmartPointer<vtkCMBArcUpdateOperator> updateArc = vtkSmartPointer<vtkCMBArcUpdateOperator>::New();
  updateArc->SetArcId(rightArc1->GetId());
  bool valid = updateArc->Operate(mArc);
  if (!valid)
    {
    cerr << "Update Operator failed" << endl;
    return 1;
    }
  mArc->Delete();

  //Move the merged end node once again
  double middlePoint2[3] = {2.5,-12.5,5};
  rightArc1->MoveEndNode(1,middlePoint2);

  renderer->ResetCamera();
  renWin->Render();

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

  return !retVal;
}
