static Plane_3 centerizePlane(const Plane_3 &p, const Point_3 &C, double sign)
{
	Plane_3 pp(p.a(), p.b(), p.c(),	p.d() + p.a() * C.x() + p.b() * C.y()
			+ p.c() * C.z());

	double a = pp.a();
	double b = pp.b();
	double c = pp.c();
	double d = pp.d();
	if (sign * signedDist(pp, C) < 0.)
	{
		a = -a;
		b = -b;
		c = -c;
		d = -d;
	}

	pp = Plane_3(a, b, c, d);

	return pp;
}
static Plane_3 normalizePlane(const Plane_3 &p)
{
	double a = p.a();
	double b = p.b();
	double c = p.c();
	double d = p.d();
	if (d > 0.)
	{
		a = -a;
		b = -b;
		c = -c;
		d = -d;
	}
	double l = sqrt(a * a + b * b + c * c);
	ASSERT(l > 1e-15);
	a /= l;
	b /= l;
	c /= l;
	d /= l;
	return Plane_3(a, b, c, d);
}
Polyhedron_3 obtainPolyhedron(Polyhedron_3 initialP, std::map<int, int> map,
		IpoptTopologicalCorrector *FTNLP)
{
	DEBUG_START;
	std::vector<Vector_3> directions = FTNLP->getDirections();
	std::vector<double> values = FTNLP->getValues();
	std::vector<Plane_3> planes(initialP.size_of_facets());
	unsigned iFacet = 0;
	for (auto I = initialP.facets_begin(), E = initialP.facets_end();
			I != E; ++I)
	{
		auto it = map.find(iFacet);
		if (it != map.end())
		{
			int i = it->second;
			Vector_3 u = directions[i];
			double h = values[i];
			ASSERT(h > 0);
			planes[iFacet] = Plane_3(-u.x(), -u.y(), -u.z(), h);
			std::cout << "Changing plane #" << iFacet << ": "
				<< I->plane() << " |--> " << planes[iFacet]
				<< std::endl;
		}
		else
		{
			planes[iFacet] = I->plane();
		}
		++iFacet;
	}

	Polyhedron_3 intersection(planes);
	std::cout << "Change in facets number: " << initialP.size_of_facets()
		<< " -> " << intersection.size_of_facets() << std::endl;
	ASSERT(initialP.size_of_facets() - intersection.size_of_facets()
			< map.size() &&
			"It seems that all extracted facets have gone");
	DEBUG_END;
	return intersection;
}
void CMeshCutting::Conver2DCurveTo3D(KW_Mesh& Mesh)
{
	if (this->CurvePoint2D.empty())
	{
		return;
	}

	CKWResearchWorkView* pView=(CKWResearchWorkView*)this->pDoc->GetView(RUNTIME_CLASS(CKWResearchWorkView));
	GLdouble* modelview=pView->GetModelview();
	GLdouble* projection=pView->GetProjection();
	GLint* viewport=pView->GetViewport();

	if (!this->hCuttingClosedCurveVertex3d.empty())
	{
		this->iDrawingCurveType=CUTTING_BITE_CURVE;
	}
	else
	{
		this->iDrawingCurveType=CUTTING_ACROSS_CURVE;
	}

	if (iDrawingCurveType==CUTTING_ACROSS_CURVE)
	{
		GeometryAlgorithm compute;
		compute.ProcessCurverPoint(this->CurvePoint2D,10.0);

		//convert UCP into opengl coordinate(on Znear) 
		vector<Point_3> UserCurvePoint;
		for (unsigned int i=0;i<this->CurvePoint2D.size();i++)
		{
			GLdouble  winX, winY, winZ; 
			GLdouble posX, posY, posZ; 

			winX =this->CurvePoint2D.at(i).x;
			winY = viewport[3] - (float)this->CurvePoint2D.at(i).y;
			glReadPixels((int)winX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 
			gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
			Point_3 CurrentPoint(posX,posY,posZ);
			UserCurvePoint.push_back(CurrentPoint);
		}

		vector<Vertex_handle> CuttingClosedCurveVertex3d;
		CPaintingOnMesh Painting;
		if(Painting.PaintingClosedStrokeOnFrontalAndRearMesh(Mesh,UserCurvePoint,modelview,
			CuttingClosedCurveVertex3d))
		{
			this->hCuttingClosedCurveVertex3d=CuttingClosedCurveVertex3d;
			//get the plane for judging which part to cut
			Point_3 Point0=UserCurvePoint.front();
			Point_3 Point1=this->hCuttingClosedCurveVertex3d.front()->point();
			Point_3 Point2=this->hCuttingClosedCurveVertex3d.back()->point();
			this->SidePlane=Plane_3(Point0,Point1,Point2);
		}
	}
	else if (iDrawingCurveType==CUTTING_BITE_CURVE)
	{
		if (this->hCuttingClosedCurveVertex3d.empty())
		{
			this->CurvePoint2D.clear();
			return;
		}
		//convert UCP into opengl coordinate(on Znear) 
		GLdouble  winX, winY, winZ; 
		GLdouble posX, posY, posZ; 
		winX =this->CurvePoint2D.front().x;
		winY = viewport[3] - (float)this->CurvePoint2D.front().y;
		glReadPixels((int)winX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 
		gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
		this->SidePoint=Point_3(posX,posY,posZ);

		CPaintingOnMesh Painting;
		Facet_handle temp;
		if(Painting.PaintingPointOnFrontalMesh(Mesh,this->SidePoint,temp,modelview))
		{
			CutMesh(Mesh);
			OBJHandle::UnitizeCGALPolyhedron(Mesh,false,false);
			Mesh.SetRenderInfo(true,true,true,true,true);
			this->hCuttingClosedCurveVertex3d.clear();
		}
		else
		{
			AfxMessageBox("Invalid Curve,could not judge which part to cut!");
		}
	}
	//else if (iDrawingCurveType==3)
	//{
	//	if (this->Tunel.GetTunVer().size()<2)
	//	{
	//		GeometryAlgorithm compute;
	//		compute.ProcessCurverPoint(this->CurvePoint2D);
	//		compute.MakeClosedStroke2d(this->CurvePoint2D);

	//		//convert UCP into opengl coordinate(on Znear) 
	//		vector<Point_3> UserCurvePoint;
	//		for (unsigned int i=0;i<this->CurvePoint2D.size();i++)
	//		{
	//			GLdouble  winX, winY, winZ; 
	//			GLdouble posX, posY, posZ; 

	//			winX =this->CurvePoint2D.at(i).x;
	//			winY = viewport[3] - (float)this->CurvePoint2D.at(i).y;
	//			glReadPixels((int)winX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 
	//			gluUnProject(winX, winY, 0.0, modelview, projection, viewport, &posX, &posY, &posZ);
	//			Point_3 CurrentPoint(posX,posY,posZ);
	//			UserCurvePoint.push_back(CurrentPoint);
	//		}

	//		vector<Vertex_handle> TunnelCurve3d;
	//		CPaintingOnMesh Painting;
	//		if(Painting.PaintingClosedStrokeOnFrontalMesh(Mesh,UserCurvePoint,modelview,TunnelCurve3d))
	//		{
	//			if (this->Tunel.GetTunVer().size()==0)
	//			{
	//				this->Tunel.InputTunVer(TunnelCurve3d);
	//			}
	//			else if (this->Tunel.GetTunVer().size()==1)//remesh to get the two sketched circles
	//			{
	//				//the result curve is always ccw on screen,so reverse the second curve
	//				//and make it the same direction with the first one
	//				reverse(TunnelCurve3d.begin(),TunnelCurve3d.end());
	//				this->Tunel.InputTunVer(TunnelCurve3d);
	//				this->Tunel.CorrespondTunCircles();
	//				this->Tunel.SetRefPlane(this->BestFittingPlane,this->PlaneBoundaryPoints,
	//					this->RotateXAxisStartPoint,this->RotateXAxisEndPoint);
	//			}
	//			OBJHandle::UnitizeCGALPolyhedron(Mesh,false,false);
	//			Mesh.SetRenderInfo(true,true,true,true,true);
	//		}
	//	}
	//	else if (this->Tunel.GetTunVer().size()==2)//make tunnel along the sketched curve
	//	{
	//		GeometryAlgorithm compute;
	//		compute.ProcessCurverPoint(this->CurvePoint2D,15.0);

	//		vector<Point_3> vecTempPoints;
	//		CPaintingOnMesh PaintingOnMesh;
	//		int iResult=PaintingOnMesh.PaintingOnBFPlane(this->BestFittingPlane,modelview,projection,viewport,
	//			this->CurvePoint2D,vecTempPoints);
	//		if (iResult)
	//		{
	//			this->Tunel.SetTunnelDirectCurve(vecTempPoints);
	//		}

	//		//dig the hole
	//		this->Tunel.Tunnel(pDoc->GetMesh(),this->vecTestPoint);
	//		this->Tunel.clear();

	//		OBJHandle::UnitizeCGALPolyhedron(Mesh,false,false);
	//		Mesh.SetRenderInfo(true,true,true,true,true);
	//	}
	//}
	else
	{
		//do nothing
	}

	this->iDrawingCurveType=NONE_SELECTED;
	this->CurvePoint2D.clear();
}