/*
    Scan Tailor - Interactive post-processing tool for scanned pages.
    Copyright (C) 2015  Joseph Artsimovich <joseph.artsimovich@gmail.com>

    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, either version 3 of the License, or
    (at your option) any later version.

    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/>.
*/

#ifndef IMAGEPROC_POLYGONUTILS_H_
#define IMAGEPROC_POLYGONUTILS_H_

#include "imageproc_config.h"
#include <vector>

class QPolygonF;
class QPointF;
class QLineF;

namespace imageproc
{

class IMAGEPROC_EXPORT PolygonUtils
{
public:
	/**
	 * \brief Adjust vertices to more round coordinates.
	 *
	 * This method exists to workaround bugs in QPainterPath and QPolygonF
	 * composition operations.  It turns out rounding vertex coordinates
	 * solves many of those bugs.  We don't round to integer values, we
	 * only make very minor adjustments.
	 */
	static QPolygonF round(QPolygonF const& poly);
	
	/**
	 * \brief Test if two polygons are logically equal.
	 *
	 * By logical equality we mean that the following differences don't matter:
	 * \li Direction (clockwise vs counter-clockwise).
	 * \li Closed vs unclosed.
	 * \li Tiny differences in vertex coordinates.
	 *
	 * \return true if polygons are logically equal, false otherwise.
	 */
	static bool fuzzyCompare(QPolygonF const& poly1, QPolygonF const& poly2);

	static QPolygonF convexHull(std::vector<QPointF> point_cloud);
private:
	class Before;
	
	static QPointF roundPoint(QPointF const& p);
	
	static double roundValue(double val);
	
	static std::vector<QLineF> extractAndNormalizeEdges(QPolygonF const& poly);
	
	static void maybeAddNormalizedEdge(
		std::vector<QLineF>& edges, QPointF const& p1, QPointF const& p2);
	
	static bool fuzzyCompareImpl(
		std::vector<QLineF> const& lines1,
		std::vector<QLineF> const& lines2);
	
	static bool fuzzyCompareImpl(QLineF const& line1, QLineF const& line2);
	
	static bool fuzzyCompareImpl(QPointF const& p1, QPointF const& p2);
	
	static double const ROUNDING_MULTIPLIER;
	static double const ROUNDING_RECIP_MULTIPLIER;
};

} // namespace imageproc

#endif
