//===========================================================================
// Copyright (C) 1998, 2000-2007, 2010, 2011, 2012 SINTEF ICT, Applied
// Mathematics, Norway.
//
// This file is part of GoTools
//
// This program is free software; you can redistribute it and/or          
// modify it under the terms of the GNU General Public License            
// as published by the Free Software Foundation version 2 of the License. 
//
// This program 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 General Public License for more details.                           
//
// You should have received a copy of the GNU General Public License      
// along with this program; if not, see <http://www.gnu.org/licenses>
//
// Contact information: E-mail: tor.dokken@sintef.no                      
// SINTEF ICT, Department of Applied Mathematics,                         
// P.O. Box 124 Blindern,                                                 
// 0314 Oslo, Norway.                                                     
//
// Other licenses are also available for this software, notably licenses
// for:
// - Building commercial software.                                        
// - Building software whose source code you wish to keep private.        
//===========================================================================

#ifndef _IMPLICITIZEPOINTCLOUDALGO_H
#define _IMPLICITIZEPOINTCLOUDALGO_H


#include "GoTools/implicitization/BernsteinTetrahedralPoly.h"
#include "GoTools/geometry/PointCloud.h"
#include "GoTools/utils/BaryCoordSystem.h"


namespace Go {


/**
 * Class that implements an algorithm for finding an implicit surface
 * from a 3D point cloud.
 *
 * Input: A point cloud of type PointCloud3D, and the degree that is
 * chosen for the implicit representation.
 *
 * Output: A barycentric coordinate system, and the Bernstein
 * polynomial that represents the implicit surface.
 *
 * The algorithm first defines a barycentric coordinate system in
 * terms of a tetrahedron that is slightly larger than the bounding box
 * of the point cloud. It then computes the Bernstein polynomial
 * representing the implicit surface. If the chosen degree is too low to
 * produce the exact result, an approximate implicit surface is
 * produced. If the degree is too high, the resulting polynomial will
 * be reducible and contain the exact implicitization as a factor.
 */

class ImplicitizePointCloudAlgo {
public:
    /// Default constructor
    ImplicitizePointCloudAlgo() : tol_(3.0e-15) { }
    /// Constructor.
    /// \param deg degree of the implicit representation
    explicit ImplicitizePointCloudAlgo(int deg)
	: deg_(deg), tol_(3.0e-15) { }
    /// Constructor.
    /// \param cloud point cloud to be implicitized
    /// \param deg degree of the implicit representation
    ImplicitizePointCloudAlgo(const PointCloud3D& cloud, int deg)
	: cloud_(cloud), deg_(deg), tol_(3.0e-15) { }

    /// Load the point cloud to be implicitized.
    /// \param cloud point cloud on PointCloud3D form
    void usePointCloud(const PointCloud3D& cloud)
    { cloud_ = cloud; }

    /// Choose the degree of the implicit representation.
    /// \param deg degree
    void setDegree(int deg)
    { deg_ = deg; }

    /// Set the tolerance.
    /// \param tol tolerance; default value is 3.0e-15
    void setTolerance(double tol)
    { tol_ = tol; }

    /// Perform the implicitization.
    /// This function runs the implicitization algorithm.
    void perform();

    /// Get the result of the implicitization.
    /// \retval implicit a BernsteinTetrahedralPoly representing the
    /// implicit surface
    /// \retval bc the barycentric coordinate system in which the
    /// BernsteinTetrahedralPoly is defined
    void getResultData(BernsteinTetrahedralPoly& implicit,
		       BaryCoordSystem3D& bc, double& sigma_min)
    {
	implicit = implicit_;
	bc = bc_;
	sigma_min = sigma_min_;
    }

private:
    PointCloud3D cloud_;
    BernsteinTetrahedralPoly implicit_;
    BaryCoordSystem3D bc_;
    int deg_;
    double tol_;
    double sigma_min_;

};


} // namespace Go


#endif // _IMPLICITIZEPOINTCLOUDALGO_H

