#include <smoothers/CLaplacianSmoother.h>

//=====================================================================================================================
CLaplacianSmoother::CLaplacianSmoother( double factor, int iterations, int layers )
{
    dFactor     =   factor;
    iIterations =   iterations;
    iLayers     =   layers;
}

//=====================================================================================================================
bool CLaplacianSmoother::smooth( CSmoothingMesh * mesh )
{
    tVertPtrList             nverts;
    tVertPtrList::iterator   nvert_it;

    for ( int i = 0; i < iIterations; i++ )
    {
        vctl::MCVerticeS    * vertices = mesh->GetVerticeS();
        vctl::MCVertex      * vertex   = vertices->GetFirst();
        vctl::MCPoint3D       smoothed, difference;

        std::vector< vctl::MCPoint3D >              smooth_coords( vertices->GetNumber() );
        std::vector< vctl::MCPoint3D >::iterator    smooth_coords_it = smooth_coords.begin();

        while ( vertex )
        {
            smoothed.setXYZ( 0, 0, 0 );
            double dx = 0, dy = 0, dz = 0;

            mesh->getNeighbourVert( vertex, nverts, iLayers );

            for ( nvert_it = nverts.begin(); nvert_it != nverts.end(); nvert_it++ )
            {
                dx += ((*nvert_it)->GetX() - vertex->GetX());
                dy += ((*nvert_it)->GetY() - vertex->GetY());
                dz += ((*nvert_it)->GetZ() - vertex->GetZ());
            }

            difference.SetX( dx / nverts.size() );
            difference.SetY( dy / nverts.size() );
            difference.SetZ( dz / nverts.size() );

            smooth_coords_it->SetX( vertex->GetX() + (dFactor * difference.GetX() ) );
            smooth_coords_it->SetY( vertex->GetY() + (dFactor * difference.GetY() ) );
            smooth_coords_it->SetZ( vertex->GetZ() + (dFactor * difference.GetZ() ) );

            vertex = vertex->GetNext();
            smooth_coords_it++;
        }

        vertex = vertices->GetFirst();
        smooth_coords_it = smooth_coords.begin();

        while ( vertex )
        {
            vertex->SetX( smooth_coords_it->GetX() );
            vertex->SetY( smooth_coords_it->GetY() );
            vertex->SetZ( smooth_coords_it->GetZ() );
            vertex = vertex->GetNext();
            smooth_coords_it++;
        }

    }
    return true;
}

