/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
#include <basegfx/polygon/b2dpolygontriangulator.hxx>
#include <osl/diagnose.h>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <algorithm>

//////////////////////////////////////////////////////////////////////////////

namespace basegfx
{
	namespace
	{
		class EdgeEntry
		{
			EdgeEntry*								mpNext;
			B2DPoint								maStart;
			B2DPoint								maEnd;
			double									mfAtan2;

		public:
			EdgeEntry(const B2DPoint& rStart, const B2DPoint& rEnd)
			:	mpNext(0L),
				maStart(rStart),
				maEnd(rEnd),
				mfAtan2(0.0)
			{
				// make sure edge goes down. If horizontal, let it go to the right (left-handed).
				bool bSwap(false);

				if(::basegfx::fTools::equal(maStart.getY(), maEnd.getY()))
				{
					if(maStart.getX() > maEnd.getX())
					{
						bSwap = true;
					}
				}
				else if(maStart.getY() > maEnd.getY())
				{
					bSwap = true;
				}

				if(bSwap)
				{
					maStart = rEnd;
					maEnd = rStart;
				}

				mfAtan2 = atan2(maEnd.getY() - maStart.getY(), maEnd.getX() - maStart.getX());
			}

			~EdgeEntry()
			{
			}

			bool operator<(const EdgeEntry& rComp) const
			{
				if(::basegfx::fTools::equal(maStart.getY(), rComp.maStart.getY()))
				{
					if(::basegfx::fTools::equal(maStart.getX(), rComp.maStart.getX()))
					{
						// same in x and y -> same start point. Sort emitting vectors from left to right.
						return (mfAtan2 > rComp.mfAtan2);
					}

					return (maStart.getX() < rComp.maStart.getX());
				}

				return (maStart.getY() < rComp.maStart.getY());
			}

			bool operator==(const EdgeEntry& rComp) const
			{
				return (maStart.equal(rComp.maStart) && maEnd.equal(rComp.maEnd));
			}

			bool operator!=(const EdgeEntry& rComp) const
			{
				return !(*this == rComp);
			}

			const B2DPoint& getStart() const { return maStart; }
			const B2DPoint& getEnd() const { return maEnd; }

			EdgeEntry* getNext() const { return mpNext; }
			void setNext(EdgeEntry* pNext) { mpNext = pNext; }
		};

		//////////////////////////////////////////////////////////////////////////////

		typedef ::std::vector< EdgeEntry > EdgeEntries;
		typedef ::std::vector< EdgeEntry* > EdgeEntryPointers;

		//////////////////////////////////////////////////////////////////////////////

		class Triangulator
		{
			EdgeEntry*										mpList;
			EdgeEntries										maStartEntries;
			EdgeEntryPointers								maNewEdgeEntries;
			B2DPolygon										maResult;
	
			void handleClosingEdge(const B2DPoint& rStart, const B2DPoint& rEnd);
			bool CheckPointInTriangle(EdgeEntry* pEdgeA, EdgeEntry* pEdgeB, const B2DPoint& rTestPoint);
			void createTriangle(const B2DPoint& rA, const B2DPoint& rB, const B2DPoint& rC);

		public:
			Triangulator(const B2DPolyPolygon& rCandidate);
			~Triangulator();

			const B2DPolygon getResult() const { return maResult; }
		};

		void Triangulator::handleClosingEdge(const B2DPoint& rStart, const B2DPoint& rEnd)
		{
			// create an entry, else the comparison might use the wrong edges
			EdgeEntry aNew(rStart, rEnd);
			EdgeEntry* pCurr = mpList;
			EdgeEntry* pPrev = 0L;

			while(pCurr 
				&& pCurr->getStart().getY() <= aNew.getStart().getY()
				&& *pCurr != aNew)
			{
				pPrev = pCurr;
				pCurr = pCurr->getNext();
			}

			if(pCurr && *pCurr == aNew)
			{
				// found closing edge, remove
				if(pPrev)
				{
					pPrev->setNext(pCurr->getNext());
				}
				else
				{
					mpList = pCurr->getNext();
				}
			}
			else
			{
				// insert closing edge
				EdgeEntry* pNew = new EdgeEntry(aNew);
				maNewEdgeEntries.push_back(pNew);
				pCurr = mpList;
				pPrev = 0L;

				while(pCurr && *pCurr < *pNew)
				{
					pPrev = pCurr;
					pCurr = pCurr->getNext();
				}

				if(pPrev)
				{
					pNew->setNext(pPrev->getNext());
					pPrev->setNext(pNew);
				}
				else
				{
					pNew->setNext(mpList);
					mpList = pNew;
				}
			}
		}

		bool Triangulator::CheckPointInTriangle(EdgeEntry* pEdgeA, EdgeEntry* pEdgeB, const B2DPoint& rTestPoint)
		{
			// inside triangle or on edge?
			if(tools::isPointInTriangle(pEdgeA->getStart(), pEdgeA->getEnd(), pEdgeB->getEnd(), rTestPoint, true))
			{
				// but not on point
				if(!rTestPoint.equal(pEdgeA->getEnd()) && !rTestPoint.equal(pEdgeB->getEnd()))
				{
					// found point in triangle -> split triangle inserting two edges
					EdgeEntry* pStart = new EdgeEntry(pEdgeA->getStart(), rTestPoint);
					EdgeEntry* pEnd = new EdgeEntry(*pStart);
					maNewEdgeEntries.push_back(pStart);
					maNewEdgeEntries.push_back(pEnd);
					
					pStart->setNext(pEnd);
					pEnd->setNext(pEdgeA->getNext());
					pEdgeA->setNext(pStart);

					return false;
				}
			}

			return true;
		}

		void Triangulator::createTriangle(const B2DPoint& rA, const B2DPoint& rB, const B2DPoint& rC)
		{
			maResult.append(rA);
			maResult.append(rB);
			maResult.append(rC);
		}

		// consume as long as there are edges
		Triangulator::Triangulator(const B2DPolyPolygon& rCandidate)
		:	mpList(0L)
		{
			// add all available edges to the single linked local list which will be sorted
			// by Y,X,atan2 when adding nodes
			if(rCandidate.count())
			{
				for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
				{
					const B2DPolygon aPolygonCandidate(rCandidate.getB2DPolygon(a));
					const sal_uInt32 nCount(aPolygonCandidate.count());

					if(nCount > 2L)
					{
						B2DPoint aPrevPnt(aPolygonCandidate.getB2DPoint(nCount - 1L));

						for(sal_uInt32 b(0L); b < nCount; b++)
						{
							B2DPoint aNextPnt(aPolygonCandidate.getB2DPoint(b));

							if( !aPrevPnt.equal(aNextPnt) )
							{
								maStartEntries.push_back(EdgeEntry(aPrevPnt, aNextPnt));
							}

							aPrevPnt = aNextPnt;
						}
					}
				}

				if(maStartEntries.size())
				{
					// sort initial list
					::std::sort(maStartEntries.begin(), maStartEntries.end());

					// insert to own simply linked list
					EdgeEntries::iterator aPos(maStartEntries.begin());
					mpList = &(*aPos++);
					EdgeEntry* pLast = mpList;

					while(aPos != maStartEntries.end())
					{
						EdgeEntry* pEntry = &(*aPos++);
						pLast->setNext(pEntry);
						pLast = pEntry;
					}
				}
			}

			while(mpList)
			{
				if(mpList->getNext() && mpList->getNext()->getStart().equal(mpList->getStart()))
				{
					// next candidate. There are two edges and start point is equal.
					// Length is not zero.
					EdgeEntry* pEdgeA = mpList;
					EdgeEntry* pEdgeB = pEdgeA->getNext();

					if( pEdgeA->getEnd().equal(pEdgeB->getEnd()) )
					{
						// start and end equal -> neutral triangle, delete both
						mpList = pEdgeB->getNext();
					}
					else
					{
						const B2DVector aLeft(pEdgeA->getEnd() - pEdgeA->getStart());
						const B2DVector aRight(pEdgeB->getEnd() - pEdgeA->getStart());

						if(ORIENTATION_NEUTRAL == getOrientation(aLeft, aRight))
						{
							// edges are parallel and have different length -> neutral triangle,
							// delete both edges and handle closing edge
							mpList = pEdgeB->getNext();
							handleClosingEdge(pEdgeA->getEnd(), pEdgeB->getEnd());
						}
						else
						{
							// not parallel, look for points inside
							B2DRange aRange(pEdgeA->getStart(), pEdgeA->getEnd());
							aRange.expand(pEdgeB->getEnd());
							EdgeEntry* pTestEdge = pEdgeB->getNext();
							bool bNoPointInTriangle(true);

							// look for start point in triangle
							while(bNoPointInTriangle && pTestEdge)
							{
								if(aRange.getMaxY() < pTestEdge->getStart().getY())
								{
									// edge is below test range and edges are sorted -> stop looking
									break;
								}
								else
								{
									// do not look for edges with same start point, they are sorted and cannot end inside.
									if(!pTestEdge->getStart().equal(pEdgeA->getStart()))
									{
										if(aRange.isInside(pTestEdge->getStart()))
										{
											bNoPointInTriangle = CheckPointInTriangle(pEdgeA, pEdgeB, pTestEdge->getStart());
										}
									}
								}

								// next candidate
								pTestEdge = pTestEdge->getNext();
							}

							if(bNoPointInTriangle)
							{
								// look for end point in triange
								pTestEdge = pEdgeB->getNext();
								
								while(bNoPointInTriangle && pTestEdge)
								{
									if(aRange.getMaxY() < pTestEdge->getStart().getY())
									{
										// edge is below test range and edges are sorted -> stop looking
										break;
									}
									else
									{
										// do not look for edges with same end point, they are sorted and cannot end inside.
										if(!pTestEdge->getEnd().equal(pEdgeA->getStart()))
										{
											if(aRange.isInside(pTestEdge->getEnd()))
											{
												bNoPointInTriangle = CheckPointInTriangle(pEdgeA, pEdgeB, pTestEdge->getEnd());
											}
										}
									}

									// next candidate
									pTestEdge = pTestEdge->getNext();
								}
							}

							if(bNoPointInTriangle)
							{
								// create triangle, remove edges, handle closing edge
								mpList = pEdgeB->getNext();
								createTriangle(pEdgeA->getStart(), pEdgeB->getEnd(), pEdgeA->getEnd());
								handleClosingEdge(pEdgeA->getEnd(), pEdgeB->getEnd());
							}
						}
					}
				}
				else
				{
					// only one entry at start point, delete it
					mpList = mpList->getNext();
				}
			}
		}

		Triangulator::~Triangulator()
		{
			EdgeEntryPointers::iterator aIter(maNewEdgeEntries.begin());

			while(aIter != maNewEdgeEntries.end())
			{
				delete (*aIter++);
			}
		}

	} // end of anonymous namespace
} // end of namespace basegfx

//////////////////////////////////////////////////////////////////////////////

namespace basegfx
{
	namespace triangulator
	{
		B2DPolygon triangulate(const B2DPolygon& rCandidate)
		{
			B2DPolygon aRetval;

			// subdivide locally (triangulate does not work with beziers), remove double and neutral points
            B2DPolygon aCandidate(rCandidate.areControlPointsUsed() ? tools::adaptiveSubdivideByAngle(rCandidate) : rCandidate);
			aCandidate.removeDoublePoints();
			aCandidate = tools::removeNeutralPoints(aCandidate);

			if(2L == aCandidate.count())
			{
				// candidate IS a triangle, just append
				aRetval.append(aCandidate);
			}
			else if(aCandidate.count() > 2L)
			{
				if(tools::isConvex(aCandidate))
				{
					// polygon is convex, just use a triangle fan
					tools::addTriangleFan(aCandidate, aRetval);
				}
				else
				{
					// polygon is concave.
                    const B2DPolyPolygon aCandPolyPoly(aCandidate);
					Triangulator aTriangulator(aCandPolyPoly);
					aRetval = aTriangulator.getResult();
				}
			}

			return aRetval;
		}

		B2DPolygon triangulate(const B2DPolyPolygon& rCandidate)
		{
			B2DPolygon aRetval;

			// subdivide locally (triangulate does not work with beziers)
            B2DPolyPolygon aCandidate(rCandidate.areControlPointsUsed() ? tools::adaptiveSubdivideByAngle(rCandidate) : rCandidate);

			if(1L == aCandidate.count())
			{
				// single polygon -> single polygon triangulation
				const B2DPolygon aSinglePolygon(aCandidate.getB2DPolygon(0L));
				aRetval = triangulate(aSinglePolygon);
			}
			else
			{
				Triangulator aTriangulator(aCandidate);
				aRetval = aTriangulator.getResult();
			}

			return aRetval;
		}
	} // end of namespace triangulator
} // end of namespace basegfx

//////////////////////////////////////////////////////////////////////////////
// eof
