//
//	Copyright © 2005 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#pragma once

namespace VWFC
{
	namespace Math
	{
		class VWPolygonOperation
		{
		public:
							VWPolygonOperation(const VWPolygon2D& clipPoly);
			virtual			~VWPolygonOperation();

			bool			BooleanOR(const VWPolygon2D& polygon, TSTLPolygons2DArray&/*out*/ resultPolygons);
			bool			BooleanAND(const VWPolygon2D& polygon, TSTLPolygons2DArray&/*out*/ resultPolygons);
			bool			BooleanEXOR(const VWPolygon2D& polygon, TSTLPolygons2DArray&/*out*/ resultPolygons);
			bool			BooleanPoly_SUB_Clip(const VWPolygon2D& polygon, TSTLPolygons2DArray&/*out*/ resultPolygons);
			bool			BooleanClip_SUB_Poly(const VWPolygon2D& polygon, TSTLPolygons2DArray&/*out*/ resultPolygons);
			// cut the specified polygon by cutter
			// the result are those parts of the polygon that lie inside the cutter
			// NOTE! the cut preserve the vertex types inside the cutter. New points are corners
			bool			CutPolygon(const VWPolygon2D& inPoly, TSTLPolygons2DArray&/*out*/ resultPolygons);

			// tools
		public:
			// clip the 'poly' using 'clipper' polygon as clipping object
			static bool		ClipToPoly(TSTLPolygons2DArray&/*out*/ resultPolygons, const VWPolygon2D& inPoly, const VWPolygon2D& inClipper);
			static bool		CombinePolygons(VWPolygon2D&/*out*/ resultPolygon, const VWPolygon2D& inPoly1, const VWPolygon2D& inPoly2);
			// result = poly1 - poly2
			static bool		SubtractPolygons(TSTLPolygons2DArray&/*out*/ resultPolygons, const VWPolygon2D& inPoly1, const VWPolygon2D& inPoly2);
			// cut the specified polygon by cutter
			// the result are those parts of the polygon that lie inside the cutter
			// NOTE! the cut preserve the vertex types inside the cutter. New points are corners
			static bool		CutPolygon(TSTLPolygons2DArray&/*out*/ resultPolygons, const VWPolygon2D& inPoly, const VWPolygon2D& inCutter);

			// removes vertices of a polygogon causing it to smooth
			// 'smoothAber' is used within the smooth algorithm to define how much
			// the smoothed curve may deviate from the original
			static bool		SmoothPolygon(VWPolygon2D&/*out*/ resultPolygon, const VWPolygon2D& polygon, double smoothAber=10.0);

			// add points when segments polygon intersect with source polyg
			// and hide those segments that are inside the specified segment polygons
			static void		HideSetmentsBeloPolygon(TSTLPolygons2DArray&/*out*/ resultPolygons, const VWPolygon2D& inPoly, const TSTLPolygons2DArray& arrSegmentPolys);

		protected:
			void*				m_pBooleanEngine;
			const VWPolygon2D&	m_clipPoly;

			// return true if the two polygons are overlapping -- meaning will make sense clipping
			static bool			AreOverlapping(const VWPolygon2D& a, const VWPolygon2D& b);

			// data for the 'CutPolygon' routine
			struct SVertex {
				SVertex();

				size_t		index;
				bool		bInters;
				bool		bOnCutter;
				bool		bInCutter;
				SVertex*	pNextVertex;
				VWPoint2D	pt;
				double		z;
				EVertexType	type;			// type of this vertex (corner, bezier, cubic, arc)
				double		radius;			// radius for arc vertex
				bool		bVisible;
			};
			static void		AddIntersectionVerticesForCut(SVertex* pFirstVertex, size_t& vertsCnt, const VWPolygon2D& cutter);
			static void		AddIntersectionVertices(SVertex* pFirstVertex, size_t& vertsCnt, const VWPolygon2D& cutter);
			void			WalkValidVertexsForCut(SVertex* pFirstVertex, size_t vertsCnt);
			virtual void	AddValidVertex(SVertex* pVertex);
			virtual void	FinishValidVerticesForPoly(bool bClosed);

			TSTLPolygons2DArray*	m_pSTLCutResultArray;
			VWPolygon2D				m_cutResutPoly;
		};
	}
}