/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2018 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include "CenterMesh.h"

#include <MeshComponent.h>
#include <Application.h>
#include <Log.h>

using namespace camitk;

#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
//For Vtk 5.10 #include <vtkCenterOfMass.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>

// --------------- constructor -------------------
CenterMesh::CenterMesh(ActionExtension* extension) : Action(extension) {
    setName("Center Mesh");
    setEmbedded(false);
    setDescription("Center current mesh component (at the end the barycenter of the mesh is in (0,0,0)");
    setComponent("MeshComponent");
    setFamily("Basic Mesh");
    addTag("Transform");
    addTag("Translate");
}


// --------------- apply -------------------
Action::ApplyStatus CenterMesh::apply() {

    // set waiting cursor and status bar
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    Application::showStatusBarMessage("Centering...");
    Application::resetProgressBar();

    // apply the transformation
    MeshComponent* targetMesh;

    for (unsigned int i = 0; i < (unsigned) getTargets().size(); i++) {
        targetMesh = dynamic_cast<MeshComponent*>(getTargets().at(i));
        CAMITK_INFO(tr("Centering \"%1\"").arg(targetMesh->getName()))

        //-- compute barycenter
        double barycenter[3] = {0.0, 0.0, 0.0};

        for (vtkIdType j = 0; j < targetMesh->getPointSet()->GetNumberOfPoints(); j++) {
            double* position = targetMesh->getPointSet()->GetPoints()->GetPoint(j);

            for (unsigned int k = 0; k < 3; k++) {
                barycenter[k] += position[k];
            }
        }

        for (unsigned int k = 0; k < 3; k++) {
            barycenter[k] /= targetMesh->getPointSet()->GetNumberOfPoints();
        }

        //-- create the transformation to center the barycenter
        vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
        transform->Translate(-barycenter[0], -barycenter[1], -barycenter[2]);

        //-- transform the mesh using the filter
        vtkSmartPointer<vtkTransformFilter> filter = vtkSmartPointer<vtkTransformFilter>::New();
        filter->SetInputConnection(targetMesh->getDataPort());
        filter->SetTransform(transform);
        filter->Update();

        //-- get the resulting mesh
        vtkSmartPointer<vtkPointSet> result = vtkPointSet::SafeDownCast(filter->GetOutputDataObject(0));
        if (result) {
            targetMesh->setPointSet(result);
            targetMesh->setModified();
        }
        else {
            CAMITK_ERROR(tr("Transform filter output is of type: %1, no vtkPointSet found.").arg(QString(filter->GetOutputDataObject(0)->GetClassName())))
            return ERROR;
        }

        Application::setProgressBarValue(100.0 * (i + 1.0) / ((double)getTargets().size()));

    }

    // restore the normal cursor and progress bar
    Application::refresh();
    Application::resetProgressBar();
    QApplication::restoreOverrideCursor();

    return SUCCESS;
}

