void Ctr2SufManager::CheckCCW()
{
	int iTotal=0;
	for( int i = 0; i < this->mesh->suffacenum; i ++)
	{
		if (this->mesh->sufmat[i*2]==1)
		{
			int temp=this->mesh->sufface[3*i+0];
			this->mesh->sufface[3*i+0]=this->mesh->sufface[3*i+1];
			this->mesh->sufface[3*i+1]=temp;
			iTotal++;
		}
	}

	DBWindowWrite("%d triangles permuted when checking ccw\n",iTotal);

	return;
}
void CMeshEditing::Convert2DProfileTo3D()
{
	if (this->UserInput2DProfile.empty())
	{
		return;
	}

	//judge the type of curve: open/closed according to the distance of the first and last point
	//get the average length
	double dTotalLen=0;
	for (unsigned int i=0;i<this->UserInput2DProfile.size()-1;i++)
	{
		Point_2 CurrentPoint(this->UserInput2DProfile.at(i).x,this->UserInput2DProfile.at(i).y);
		Point_2 NextPoint(this->UserInput2DProfile.at(i+1).x,this->UserInput2DProfile.at(i+1).y);
		dTotalLen=dTotalLen+sqrt(CGAL::squared_distance(CurrentPoint,NextPoint));
	}
	double dAverageLen=dTotalLen/(double)(this->UserInput2DProfile.size()-1);

	//get length between the first and last point
	Point_2 FirstPoint(this->UserInput2DProfile.front().x,this->UserInput2DProfile.front().y);
	Point_2 FinalPoint(this->UserInput2DProfile.back().x,this->UserInput2DProfile.back().y);
	double dFinalLen=sqrt(CGAL::squared_distance(FirstPoint,FinalPoint));

	//judge
	if (dFinalLen>dAverageLen*3)//open curve
	{
		CKWResearchWorkView* pView=(CKWResearchWorkView*)this->pDoc->GetView(RUNTIME_CLASS(CKWResearchWorkView));
		GLdouble* modelview=pView->GetModelview();
		GLdouble* projection=pView->GetProjection();
		GLint* viewport=pView->GetViewport();

		Point_3 StartPoint,EndPoint;
		Facet_handle FhPaintFacet;
		CPaintingOnMesh Painting;
		bool bResultStart=Painting.PaintingScrPointOnFrontalMesh(pDoc->GetMesh(),this->UserInput2DProfile.front(),StartPoint,
			FhPaintFacet,modelview,projection,viewport);
		bool bResultEnd=Painting.PaintingScrPointOnFrontalMesh(pDoc->GetMesh(),this->UserInput2DProfile.back(),EndPoint,
			FhPaintFacet,modelview,projection,viewport);
		
		if (bResultStart&&bResultEnd)//two points on mesh,deformation
		{
			DBWindowWrite("Deformation Handle Curve...\n");
			pDoc->GetMeshDeformation().SetDrawingCurveType(DEFORMATION_HANDLE_CURVE);//handle curve, if more than one point
			pDoc->GetMeshDeformation().SetCurvePoint2D(this->UserInput2DProfile);
			pDoc->GetMeshDeformation().Conver2DCurveTo3D(pDoc->GetMesh());
			pDoc->OnModeDeformation();
		}
		else if (!bResultStart && !bResultEnd)//two points not on mesh,cutting
		{
			DBWindowWrite("Cutting Curve...\n");
			pDoc->GetMeshCutting().SetDrawingCurveType(CUTTING_ACROSS_CURVE);
			pDoc->GetMeshCutting().SetCurvePoint2D(this->UserInput2DProfile);
			pDoc->GetMeshCutting().Conver2DCurveTo3D(pDoc->GetMesh());
			pDoc->OnModeCutting();
		}
		else
		{
			AfxMessageBox("Invalid Input!");
		}
	}
	else//closed curve
	{
		DBWindowWrite("Extrusion Curve...\n");
		pDoc->GetMeshExtrusion().SetDrawingCurveType(EXTRUSION_CLOSED_CURVE);
		pDoc->GetMeshExtrusion().SetCurvePoint2D(this->UserInput2DProfile);
		pDoc->GetMeshExtrusion().Conver2DCurveTo3D(pDoc->GetMesh());
		pDoc->OnModeExtrusion();
	}
	this->UserInput2DProfile.clear();
}
void Ctr2SufManager::ctr2sufProc(vector<vector<Point_3> >& MeshBoundingProfile3D,vector<Point_3>& vecTestPoint)
{
	clock_t   start   =   clock();   
	struct __timeb64 timebuffer;
	char *timeline;
	_ftime64( &timebuffer );
	timeline = _ctime64( & ( timebuffer.time ) );
	printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );

	//common line case
	//compute the common line
	if( isComnCase )	
	{
		float tempparam[ 8 ];
		for( int i = 0; i < 8; i ++)
		{
			tempparam[ i  ] = pparam[ i ];
		}

		//////////////////////////////////////////////////////////////////////////
		/*for( int i = 0 ; i < 8; i ++ )
		{
			cout<<tempparam[ i ]<<",";
		}
		cout<<endl;*/
		//////////////////////////////////////////////////////////////////////////

		computeComnLine( tempparam, tempparam + 4, comndir, comnpt);
		//////////////////////////////////////////////////////////////////////////
		/*for( int i = 0 ; i < 8; i ++ )
		{
			cout<<tempparam[ i ]<<",";
		}
		cout<<endl;*/
		//////////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////////
		//writeComnLineDB( tempparam, tempparam + 4, comndir, comnpt);
		//////////////////////////////////////////////////////////////////////////
	}

	//////////////////////////////////////////////////////////////////////////
	/*for( int i = 0; i < planenum + 4; i ++ )
	{
		cout<<pparam[ 4* i ]<<","
			<<pparam[ 4*i + 1]<<","
			<<pparam[ 4*i + 2]<<","
			<<pparam[ 4*i + 3]<<endl;
	}
	cout<<endl;*/
	//////////////////////////////////////////////////////////////////////////

	//preprocess data first
	int** pctrvermark;

	if( !ispreproced || isComnCase)
	{
		pctrvermark = preProcData(isComnCase);
		//reset showcontourvers
		for( int i = 0; i < showplanenum; i ++)
			delete []showctrvers[ i ];
		delete []showctrvers;

		//copy the data from processed data, and reset size
		showplanenum = planenum;
		showctrvers = new float*[ showplanenum ];
		showctredgenum = new int[ showplanenum ];
		showctredges = new int*[ showplanenum ];
		for( int i = 0; i < showplanenum; i++ )
		{
			int versize = pctrvernum[ i ]*3; 
			showctrvers[ i ] = new float[ versize ];
			for( int j = 0 ; j < versize;  j ++ )
				showctrvers[ i ][ j ] = pctrvers[ i ][ j ]*DIM/PROCSIZE;

			showctredgenum[ i ] = pctredgenum[ i ];
			int edgesize = pctredgenum[ i ] * 2;			
			showctredges[ i ] = new int[ edgesize ];
			for( int  j = 0; j < showctredgenum[ i ]; j ++)
			{
				showctredges[ i ][ 2*j ] = pctredges[ i ][ 4*j ];
				showctredges[ i ][ 2*j + 1 ] = pctredges[ i ][ 4*j + 1];
			}
		}

		for( int i = 0; i < planenum; i ++)
		{
			int iVerIndBase=0;
			vector<Point_3> CurrentProfile3D;
			for( int j = 0;j < showctredgenum[ i ]; j++)
			{

				int v1 = showctredges[ i ][ 2*j ];
				int v2 = showctredges[ i ][ 2*j + 1 ];

				CurrentProfile3D.push_back(Point_3(showctrvers[ i ][ v1* 3],
					showctrvers[ i ][ v1* 3+1],
					showctrvers[ i ][ v1* 3+2]));

				if (v2==iVerIndBase)
				{
					iVerIndBase=iVerIndBase+CurrentProfile3D.size();
					MeshBoundingProfile3D.push_back(CurrentProfile3D);
					CurrentProfile3D.clear();
				}
			}
		}
		//for( int i = 0; i < planenum; i ++)
		//{	
		//	vector<Point_3> CurrentProfile3D;
		//	for( int j = 0;j < showctredgenum[ i ]; j++)
		//	{
		//		int v1 = showctredges[ i ][ 2*j ];
		//		glVertex3fv( &showctrvers[ i ][ v1* 3] );
		//		CurrentProfile3D.push_back(Point_3(showctrvers[ i ][ v1* 3],
		//								showctrvers[ i ][ v1* 3+1],
		//								showctrvers[ i ][ v1* 3+2]));
		//	}
		//	MeshBoundingProfile3D.push_back(CurrentProfile3D);
		//}

	}
	//////////////////////////////////////////////////////////////////////////
	//for( int i = 0; i < planenum + 4; i ++ )
	//{
	//	cout<<pparam[ 4* i ]<<","
	//		<<pparam[ 4*i + 1]<<","
	//		<<pparam[ 4*i + 2]<<","
	//		<<pparam[ 4*i + 3]<<endl;
	//}
	//cout<<endl;
	//////////////////////////////////////////////////////////////////////////
	//partition
//	cout<<"------------------ PARTITION ------------------"<<endl;
//	cout<<"Starting............"<<endl;
	partition();	

	///////////////////////////////////////////////////////////B///////////////
	/*writePartitionOut("mmdebug/partition.txt");*/
	//////////////////////////////////////////////////////////////////////////
//	cout<<"DONE!"<<endl<<endl;
	
	//process data
//	cout<<"------------------ PUT CONTOUR INTO FACE ------------------"<<endl;
	putContourIntoFace( pctrvermark );

	//SaveCtr2FaceInfo();


	if( isComnCase )
	{
		for( int i = 0; i < planenum; i ++ )
			delete []pctrvermark[ i ];
		delete []pctrvermark;
	}

	//////////////////////////////////////////////////////////////////////////
//	ContourHandler::writeContourInFace( ssfacenum, ctrfvernum, ctrfverpos, ctrfvertype, 
//		ctrfverval, ctrfedgenum, ctrfedge, ctrfedgetype, ctrfedgeval );	
	//////////////////////////////////////////////////////////////////////////
//	cout<<"DONE!"<<endl<<endl;

	
	//go through each subspace to generate mesh
//	cout<<"-------- GENERATING MESH IN EACH SUBSPACE ------------"<<endl;
	//kw noted: vertices, edges and faces in each subspace
	//stitch them together finally
	floatvector* subMeshVer;
	intvector* subMeshEdge;
	intvector* subMeshFace;
	subMeshVer = new floatvector[ ssspacenum ];
	subMeshEdge = new intvector[ ssspacenum ];
	subMeshFace = new intvector[ ssspacenum ];

	//initialize registration informaiton for stitching
	sverreg = new intvector[ ssvernum ];
	sedgereg = new vector<intvector>[ ssedgenum ];
	sedgesubedgemark = new intvector[ ssedgenum ];
	sfacectrei = new intset[ ssfacenum ];
	sfacespaci = new int[ ssfacenum * 2 ];
	sfaceregface = new vector<intvector>[ ssfacenum ];
	sfaceregver = new intvector[ ssfacenum ];
	sfaceregedgever = new intvector[ ssfacenum ];
	for( int i = 0; i < ssfacenum*2; i ++)
	{
		sfacespaci[ i ] = -1;
	}
	for( int spacei = 0; spacei < ssspacenum; spacei ++)
	{
		for( int facej = 0; facej < ssspacefacenum[ spacei ]; facej ++)
		{
			int facei = ssspace[ spacei ][ facej ];
			if( sfacespaci[ 2 * facei ] == -1)
				sfacespaci[ 2 * facei ] = spacei;
			else
				sfacespaci[ 2*facei + 1 ] = spacei;
		}
	}
	
	//////////////////////////////////////////////////////////////////////////
	/*ancestorlist.resize( ssfacenum * 2 );
	ancestorlist_split.resize( ssfacenum * 2 );*/
	//////////////////////////////////////////////////////////////////////////

	//return;

	dbSpaceNum = ssspacenum; 
	if( dbOneSpaceMode )
	{
		if( dbCurSpace < dbSpaceNum )
		{
			ctr2sufSubspaceProc( dbCurSpace, subMeshVer[ dbCurSpace ], subMeshEdge[ dbCurSpace ], subMeshFace[ dbCurSpace ]);

			//submeshedge is useless for stitching!
			subMeshEdge[ dbCurSpace ].clear();
		}
	}
	//kw: here can use multi-thread to compute each submesh in parallel
	else{
		//	for( int i = 7; i< 8; i ++)

		for( int i = 0; i < ssspacenum; i ++)
			//	for( int i = 2; i < 3; i ++)
			//	for( int i = 54; i < 55; i ++)
			//	for(int i = 0; i < 12; i ++)
			//	for( int i = 14; i < 15; i ++)
		{
					cout<<"--- subspace " << i <<endl;
			ctr2sufSubspaceProc( i, subMeshVer[ i ], subMeshEdge[ i ], subMeshFace[ i ]);

			//submeshedge is useless for stitching!
			subMeshEdge[ i ].clear();
		}
	}

	delete []subMeshEdge;

	//////////////////////////////////////////////////////////////////////////
	//cout<<"before splitting, ancestors:"<<endl;
	//for( int i = 0; i < ssfacenum*2; i +=2 )
	//{
	//	if( ancestorlist[ i ].size() == 0 )
	//	{
	//		if( ancestorlist[ i + 1].size() == 0 )
	//			continue;
	//	}
	//	intset::iterator iter = ancestorlist[ i ].begin();
	////	intset::iterator iter2 = ancestorlist[ i + 1].begin();
	//	while( iter != ancestorlist[ i ].end() )
	//	{
	//		cout<<*iter<<" ";
	//		iter++;
	//	}
	//	cout<<endl;
	//	iter = ancestorlist[ i+1 ].begin();
	//	while( iter != ancestorlist[ i + 1 ].end() )
	//	{
	//		cout<<*iter <<" ";
	//		iter ++;
	//	}
	//	cout<<endl;
	//	cout<<"\n";
	//}
	//cout<<"=============================\n";
	//cout<<"after splitting ancestors:"<<endl;
	//for( int i= 0; i < ssfacenum*2; i += 2 )
	//{
	//	if( ancestorlist_split[ i ].size() == 0 )
	//	{
	//		if( ancestorlist_split[ i + 1].size() == 0)
	//			continue;
	//	}
	//	intset::iterator iter = ancestorlist_split[ i ].begin();
	//	while( iter != ancestorlist_split[ i ].end() )
	//	{
	//		cout<<*iter <<" ";
	//		iter++;
	//	//	cout<<endl;
	//	}
	//	cout<<endl;
	//	iter = ancestorlist_split[ i + 1].begin();
	//	while( iter != ancestorlist_split[ i + 1].end() )
	//	{
	//		cout<<*iter <<" ";
	//		iter ++;
	//	}
	//	cout<<endl<<endl;
	//}


	//////////////////////////////////////////////////////////////////////////
	//cout the faces registered on the contour edges 
	/*for( int i = 0; i < ssfacenum; i ++ )
	{
		int ctrnum = sfaceregface[ i ].size()/2;
		if( ctrnum == 0 )
			continue;
		intset::iterator iter = ancestorlist_split[2* i ].begin();
		for( int j = 0; j < ctrnum; j ++ )
		{
			cout<<"("<<*iter<<":"<<sfaceregface[ i ][ 2*j ] .size()<<","<<
				sfaceregface[ i ][ 2*j +1 ].size()<<")  ";
			iter++;
		}
		cout<<endl;
	}*/
	//////////////////////////////////////////////////////////////////////////

	//for( int i = 0; i < ssfacenum; i ++)
	//{
	//	ancestorlist[ i].clear();
	//	ancestorlist_split[ i ].clear();
	//}
	//ancestorlist_split.clear();
	//ancestorlist.clear();
	//////////////////////////////////////////////////////////////////////////


	//stitch all the subspaces together
	stitchMesh(subMeshVer,subMeshFace);

	clock_t   endt   =   clock();
	cout<<"time difference is:"<<endt - start<<endl;
	DBWindowWrite("Reconstruction finished,taking: %d ms\n",endt - start);
//	struct __timeb64 timebuffer;
//	char *timeline;
	_ftime64( &timebuffer );
	timeline = _ctime64( & ( timebuffer.time ) );
	printf( "The time is %.19s.%hu %s", timeline, timebuffer.millitm, &timeline[20] );


//	FaceGenerator::writeSubMeshOut( mver, mface, 99);

	//clear all the allocated space
	//for( int i = 0; i < ssspacenum; i ++)
	//{
	//	//subMeshVer[ i ].clear();
	////	subMeshEdge[ i ].clear();
	//	subMeshFace[ i ].clear();
	//}
	////delete []subMeshVer;
	////delete []subMeshEdge;
	//delete []subMeshFace;
	/*subMeshFace = NULL;
	subMeshVer = NULL;*/

	//clear the registration information for subspace vertex, edge and face
	//sverreg
	for( int i = 0; i < ssvernum; i ++)
		sverreg[ i ].clear();
	delete []sverreg;
	sverreg = NULL;

	//sedgereg
	for( int i= 0; i < ssedgenum; i ++)
	{
		for(unsigned int j = 0; j < sedgereg[ i ].size(); j ++)
			sedgereg[ i ][ j ].clear();
		sedgereg[ i ].clear();
	}
	delete []sedgereg;
	sedgereg = NULL;

	//sfacectrei, sfacespaci, sfaceregface, sfaceregver
	for( int i= 0; i < ssfacenum; i ++)
	{
		sfacectrei[ i ].clear();
		
	//	for( int j = 0; j < sfaceregface[ i ].size();  j ++ )
    //       sfaceregface[ i ][ j ].clear();
	//	sfaceregface[ i ].clear();
		sfaceregver[ i ].clear();
	}	
	delete []sfacectrei;
	delete []sfacespaci;
	//delete []sfaceregface;
	delete []sfaceregver;
	sfacectrei = NULL;
	sfacespaci = NULL;
	//sfaceregface = NULL;
	sfaceregver = NULL;

	//set the mesh
	//clear
	if( mesh!= NULL )
		delete mesh;

	//set
	mesh = new Mesh( mver, mface, ctrmedge, 
		center,  unitlen, PROCSIZE );
	
	////kw: get constrained vertices
	//set<int> ConstrVer;
	//for (unsigned int i=0;i<ctrmedge.size();i++)
	//{
	//	ConstrVer.insert(ctrmedge.at(i));
	//}
	//for (set<int>::iterator SetIter=ConstrVer.begin();SetIter!=ConstrVer.end();SetIter++)
	//{
	//	vecTestPoint.push_back(Point_3(mver.at(3*(*SetIter))*DIM/PROCSIZE,mver.at(3*(*SetIter)+1)*DIM/PROCSIZE,
	//		mver.at(3*(*SetIter)+2)*DIM/PROCSIZE));
	//}

	mesh->setGLParam( width, height, nearplane, farplane);

	//clear
	mver.clear();
	mface.clear();
	ctrmedge.clear();
}
void KW_CS2Surf::GetSSMesh()
{
	//faces in each subspace,each vector<int> represents a face composed of vertices with indices <int>
	vector<vector<vector<int>>> vecTotalFaceVer;
	//faces in each subspace,each int represents the face id of the facet in a subspace (a face may contain many facets(eg,triangles))
	vector<vector<int>> vecTotalFace;
	//the order of each element in vecTotalFaceVer&vecTotalFace is consistent with the order of subspaces
	vecTotalFaceVer.resize(this->iSSspacenum);
	vecTotalFace.resize(this->iSSspacenum);
	for (unsigned int i=0;i<this->vecResortFace.size();i++)
	{
		ResortedFace currFace=vecResortFace.at(i);
		vector<int> currFaceVertexInd=currFace.vecFaceVertexInd;
		//the two subspace this face belongs to
		for (unsigned int j=0;j<currFace.vecOrient.size();j++)
		{
			int icurrSSId=currFace.vecSubspaceId.at(j);
			if (!currFace.vecOrient.at(j))
			{
				reverse(currFaceVertexInd.begin(),currFaceVertexInd.end());
			}
			vecTotalFaceVer.at(icurrSSId).push_back(currFaceVertexInd);
			vecTotalFace.at(icurrSSId).push_back(i);
			//reverse back to the originally saved order
			if (!currFace.vecOrient.at(j))
			{
				reverse(currFaceVertexInd.begin(),currFaceVertexInd.end());
			}
		}
	}

	//id of vertices stored in vecTotalFaceVer is the global vertex id,need to convert it 
	//to the id within each subspace mesh
	//all the vertices are collected from the faces, so isolated vertices caused by the 
	//subspace combination will not be taken account into consideration

	//subspace number after combination
	int iSSNumAfterComb=0;
	for (unsigned int i=0;i<vecTotalFaceVer.size();i++)
	{
		set<int> setSSVer;
		vector<vector<set<int>::iterator>> vecFaceSetIter;
		//put all vertex indices in, store the iterator
		for (unsigned int j=0;j<vecTotalFaceVer.at(i).size();j++)
		{
			vector<set<int>::iterator> currFaceSetIter;
			for (unsigned int k=0;k<vecTotalFaceVer.at(i).at(j).size();k++)
			{
				pair<set<int>::iterator, bool> pairResult=setSSVer.insert(vecTotalFaceVer.at(i).at(j).at(k));
				currFaceSetIter.push_back(pairResult.first);
			}
			vecFaceSetIter.push_back(currFaceSetIter);
		}
		//get the id within the subspace according to the iterator
		vector<vector<int>> vecLocalVerInd;
		for (unsigned int j=0;j<vecFaceSetIter.size();j++)
		{
			vector<int> LocalFace;
			for (unsigned int k=0;k<vecFaceSetIter.at(j).size();k++)
			{
				int iLocalId=distance(setSSVer.begin(),vecFaceSetIter.at(j).at(k));
				LocalFace.push_back(iLocalId);
			}
			vecLocalVerInd.push_back(LocalFace);
		}
		//convert to triangular mesh
		//a simple method (012345->012 023 034 045),may have bug 
		vector<vector<int>> vecTriLocalVerInd;
		vector<int> vecTriFaceId;//the subspace face id of each triangle
		for (unsigned int j=0;j<vecLocalVerInd.size();j++)
		{
			vector<int> vecCurrFace=vecLocalVerInd.at(j);
			int iSecondVerLocalId=1;
			int iFacetFaceId=vecTotalFace.at(i).at(j);
			for (unsigned int k=0;k<vecCurrFace.size()-2;k++)
			{
				vector<int> vecTriFace;
				vecTriFace.push_back(vecCurrFace.at(0));
				vecTriFace.push_back(vecCurrFace.at(iSecondVerLocalId));
				vecTriFace.push_back(vecCurrFace.at(iSecondVerLocalId+1));
				iSecondVerLocalId++;
				vecTriLocalVerInd.push_back(vecTriFace);
				vecTriFaceId.push_back(iFacetFaceId);
			}
		}
		//store all the points
		vector<Point_3> vecAllPoint;
		for (set<int>::iterator SetIter=setSSVer.begin();SetIter!=setSSVer.end();SetIter++)
		{
			vecAllPoint.push_back(Point_3(vecSSver.at(3*(*SetIter)),
				vecSSver.at(3*(*SetIter)+1),
				vecSSver.at(3*(*SetIter)+2)));
		}
		KW_Mesh currSSMesh;
		//if a subspace has been combined into others,still save it as an empty one,
		//in order to keep the order of subspaces
		if (!vecAllPoint.empty() && !vecTriLocalVerInd.empty())
		{
			//Convert_Array_To_KW_Mesh<HalfedgeDS> triangle(vecAllPoint,vecLocalVerInd);
			Convert_Array_To_KW_Mesh<HalfedgeDS> triangle(vecAllPoint,vecTriLocalVerInd);
			currSSMesh.delegate(triangle);
			//record the face id of each triangle
			assert(currSSMesh.size_of_facets()==vecTriFaceId.size());
			Facet_iterator FaceIter=currSSMesh.facets_begin();
			for (unsigned int j=0;j<vecTriFaceId.size();j++)
			{
				FaceIter->SetReserved(vecTriFaceId.at(j));
				FaceIter++;
			}
		}
		//save the subspace mesh
		if (!currSSMesh.empty())
		{
			iSSNumAfterComb++;
			OBJHandle::UnitizeCGALPolyhedron(currSSMesh,false,false);
		}
		this->vecSSMesh.push_back(currSSMesh);
		////test
		//if (!currSSMesh.empty())
		//{
		//	OBJHandle::UnitizeCGALPolyhedron(currSSMesh,false,false);
		//	this->vecSinglePoly.push_back(currSSMesh);
		//}
	}
	DBWindowWrite("initial subzone no.: %d\n",this->iSSspacenum);
	DBWindowWrite("subzone no. after combination: %d\n",iSSNumAfterComb);
}
void KW_CS2Surf::CombineSS()
{
	//iteratively combine until no SS can be combined
	while (true)
	{
		//collect subspaces need to be combined
		//pairs of subspaces to combine
		vector<Int_Int_Pair> vecSpacesToCombine;
		//the only face having CSs on in each subspace need to combine
		vector<int> vecValidFace;
		CollectSSToCombine(vecSpacesToCombine,vecValidFace);
		if (vecSpacesToCombine.empty())//no SS can be combined
		{
			break;
		}
		//start combination
		//in each list<int>,the first element is the id after combination,
		//the following elements are the id of subspaces to delete(note that this is opposite with the order in vecSpacesToCombine)
		vector<list<int>> vecSSComb;
		for (unsigned int i=0;i<vecSpacesToCombine.size();i++)
		{
			int iLeftSSId=-1;//id of subspace to be left
			int iDelSSId=-1;//id of subspace to delete
			for (unsigned int j=0;j<vecSSComb.size();j++)
			{
				list<int>::iterator pFindFirst=find(vecSSComb.at(j).begin(),vecSSComb.at(j).end(),vecSpacesToCombine.at(i).first);
				if (pFindFirst!=vecSSComb.at(j).end())
				{
					if (pFindFirst==vecSSComb.at(j).begin())
					{
						vecSSComb.at(j).push_front(vecSpacesToCombine.at(i).second);
						iLeftSSId=vecSpacesToCombine.at(i).second;
						iDelSSId=vecSpacesToCombine.at(i).first;
					}
					else
					{
						DBWindowWrite("error pair in subspace combination\n");
					}
					break;
				}
				list<int>::iterator pFindSecond=find(vecSSComb.at(j).begin(),vecSSComb.at(j).end(),vecSpacesToCombine.at(i).second);
				if (pFindSecond!=vecSSComb.at(j).end())
				{
					if (pFindSecond==vecSSComb.at(j).begin())
					{
						vecSSComb.at(j).push_back(vecSpacesToCombine.at(i).first);
						iLeftSSId=vecSpacesToCombine.at(i).second;
						iDelSSId=vecSpacesToCombine.at(i).first;
					}
					else
					{
						vecSSComb.at(j).push_back(vecSpacesToCombine.at(i).first);
						iLeftSSId=vecSSComb.at(j).front();
						iDelSSId=vecSpacesToCombine.at(i).first;
					}
					break;
				}
			}
			if (iLeftSSId==-1 && iDelSSId==-1)
			{
				//a fresh new pair
				list<int> ListNewPair;
				ListNewPair.push_back(vecSpacesToCombine.at(i).second);
				ListNewPair.push_back(vecSpacesToCombine.at(i).first);
				vecSSComb.push_back(ListNewPair);
				iLeftSSId=vecSpacesToCombine.at(i).second;
				iDelSSId=vecSpacesToCombine.at(i).first;
			}
			CombineTwoSS(iLeftSSId,iDelSSId,vecValidFace.at(i));
		}
	}
	//compute mesh formed by each subspace
	GetSSMesh();
}
void CKWResearchWorkDoc::OnHelpTest()
{
	// TODO: Add your command handler code here
	vector<Point_3> SamplePoints;
	GeometryAlgorithm::SampleCircle(Point_3(0,0,0),0.3,20,SamplePoints);
	FILE* pfile=fopen("circle0.contour","w");
	for (unsigned int i=0;i<SamplePoints.size();i++)
	{
		fprintf(pfile,"%.3f %.3f %.3f\n",SamplePoints.at(i).x(),SamplePoints.at(i).y(),SamplePoints.at(i).z());
	}
	fclose(pfile);




	Polygon_2 PolyTest;
	PolyTest.push_back(Point_2(0,0));
	PolyTest.push_back(Point_2(1,1));
	PolyTest.push_back(Point_2(2,0));
	PolyTest.push_back(Point_2(2,2));
	PolyTest.push_back(Point_2(0,2));

	Point_2 ResultPoint;
	bool bResult=GeometryAlgorithm::GetArbiPointInPolygon(PolyTest,ResultPoint);
	DBWindowWrite("result point: %f %f\n",ResultPoint.x(),ResultPoint.y());



	SparseMatrix LHMatrix(2);
	LHMatrix.m = 3;
	LHMatrix[0][0] = 2;
	LHMatrix[0][1] = -1;
	LHMatrix[0][2] = 1;
	LHMatrix[1][1] = 1;
	LHMatrix[1][2] = 1;

	SparseMatrix LHMatrixAT(LHMatrix.NCols());
	CMath MathCompute;
	MathCompute.TAUCSFactorize(LHMatrix,LHMatrixAT);

	vector<vector<double>> RightMatB,ResultMat;
	vector<double> BRow;
	BRow.push_back(5);BRow.push_back(3);
	RightMatB.push_back(BRow);
	BRow.clear();
	BRow.push_back(10);BRow.push_back(1);
	RightMatB.push_back(BRow);
	BRow.clear();


	MathCompute.TAUCSComputeLSE(LHMatrixAT,RightMatB,ResultMat);

	return;

	int iVer=this->Mesh.size_of_vertices();
	int iEdge=this->Mesh.size_of_halfedges();
	int iFacet=this->Mesh.size_of_facets();

	Polygon_2 BoundingPolygon0;
	Polygon_2 BoundingPolygon1;

	bool bSimple0=BoundingPolygon0.is_simple();
	bool bSimple1=BoundingPolygon1.is_simple();
	bool bConvex0=BoundingPolygon0.is_convex();
	bool bConvex1=BoundingPolygon1.is_convex();
	bool bOrien0=BoundingPolygon0.is_clockwise_oriented();
	bool bOrien1=BoundingPolygon1.is_clockwise_oriented();

	BoundingPolygon0.reverse_orientation();
	BoundingPolygon1.reverse_orientation();
	//float?
	bool bIntersect=CGAL::do_intersect(BoundingPolygon0,BoundingPolygon1);

	bool bCW=BoundingPolygon0.is_clockwise_oriented();
	bool bConvex=BoundingPolygon0.is_convex();


	Plane_3 plane(1,1,1,0);
	vector<vector<Point_3>> IntersectCurves;
	int iNum=GeometryAlgorithm::GetMeshPlaneIntersection(this->Mesh,plane,IntersectCurves);



	CMath CMathTest;
	CMathTest.testTAUCS();



//	Vector_3 vec0(Point_3(0,0,1),Point_3(0,0,0));
	Vector_3 vec0(Point_3(0,0,0),Point_3(0,0,1));
//	Vector_3 vec0(0,0,1);
//	Vector_3 vec1(0,-1,-1);
	Vector_3 vec1(Point_3(0,0,0),Point_3(0,-1,-1));
	double dAngle=GeometryAlgorithm::GetAngleBetweenTwoVectors3d(vec0,vec1);


	vector<double> number;
	number.push_back(2);
	number.push_back(4);
	number.push_back(4);
	number.push_back(4);
	number.push_back(5);
	number.push_back(5);
	number.push_back(7);
	number.push_back(9);
	double dderi=GeometryAlgorithm::GetDerivation(number);





	Point_3 center(0,0,0);
	Sphere_3 sphere(center,1);
	Line_3 line(Point_3(0,2,1),Point_3(0,2,-1));
	vector<Point_3> points;
	GeometryAlgorithm::GetLineSphereIntersection(line,sphere,points);



	vector<Point_3> Group0,Group1;
	vector<Int_Int_Pair> GroupResult;

	Group0.push_back(Point_3(3,3,2));
	Group0.push_back(Point_3(5,3,2));
	Group0.push_back(Point_3(2,3,2));
	Group0.push_back(Point_3(6,3,2));
	Group0.push_back(Point_3(4,3,2));
	Group0.push_back(Point_3(1,3,2));

	Group1.push_back(Point_3(3,4,2));
	Group1.push_back(Point_3(1,4,2));
	Group1.push_back(Point_3(6,4,2));
	Group1.push_back(Point_3(2,4,2));
	Group1.push_back(Point_3(5,4,2));
	Group1.push_back(Point_3(4,4,2));

	vector<Point_3> vecMidPoint;
	GeometryAlgorithm::GroupNearestPoints(Group0,Group1,GroupResult,vecMidPoint);//

	vector<Point_3> OriginalCurve;
	OriginalCurve.push_back(Point_3(-1,0,2));
	OriginalCurve.push_back(Point_3(1,0,2));
	OriginalCurve.push_back(Point_3(1,0,0));
	OriginalCurve.push_back(Point_3(-1,0,0));
	vector<Point_3> NewCurve=OriginalCurve;
	vector<int> HandleInd;
	HandleInd.push_back(0);
	HandleInd.push_back(1);
	vector<Point_3> NewPos;
	NewPos.push_back(Point_3(-1,0,3));
	NewPos.push_back(Point_3(1,0,3));
//	CCurveDeform::ClosedCurveNaiveLaplacianDeform(NewCurve,HandleInd,NewPos,1);




	vector<vector<float>> MatrixA,MatrixB,Result;
	vector<float> CurrentRow;
	CurrentRow.push_back(2);CurrentRow.push_back(0);CurrentRow.push_back(1);
	MatrixA.push_back(CurrentRow);
	CurrentRow.clear();
	CurrentRow.push_back(3);CurrentRow.push_back(1);CurrentRow.push_back(2);
	MatrixA.push_back(CurrentRow);
	CurrentRow.clear();
	CurrentRow.push_back(0);CurrentRow.push_back(1);CurrentRow.push_back(0);
	MatrixA.push_back(CurrentRow);
	CurrentRow.clear();

	CurrentRow.push_back(1);CurrentRow.push_back(3);CurrentRow.push_back(0);
	MatrixB.push_back(CurrentRow);
	CurrentRow.clear();
	CurrentRow.push_back(2);CurrentRow.push_back(0);CurrentRow.push_back(2);
	MatrixB.push_back(CurrentRow);
	CurrentRow.clear();
	CurrentRow.push_back(1);CurrentRow.push_back(0);CurrentRow.push_back(1);
	MatrixB.push_back(CurrentRow);
	CurrentRow.clear();



	int iANonZeroSize=0;
	for (unsigned int i=0;i<MatrixA.size();i++)
	{
		for (unsigned int j=0;j<MatrixA.front().size();j++)
		{
			if (MatrixA.at(i).at(j)!=0)
			{
				iANonZeroSize++;
			}
		}
	}
	KW_SparseMatrix A(MatrixA.size(),MatrixA.front().size(),iANonZeroSize);
	for (unsigned int i=0;i<MatrixA.size();i++)
	{
		for (unsigned int j=0;j<MatrixA.front().size();j++)
		{
			if (MatrixA.at(i).at(j)!=0)
			{
				A.fput(i,j,MatrixA.at(i).at(j));
			}
		}
	}

	int iBNonZeroSize=0;
	for (unsigned int i=0;i<MatrixB.size();i++)
	{
		for (unsigned int j=0;j<MatrixB.front().size();j++)
		{
			if (MatrixB.at(i).at(j)!=0)
			{
				iBNonZeroSize++;
			}
		}
	}
	KW_SparseMatrix B(MatrixB.size(),MatrixB.front().size(),iBNonZeroSize);
	for (unsigned int i=0;i<MatrixB.size();i++)
	{
		for (unsigned int j=0;j<MatrixB.front().size();j++)
		{
			if (MatrixB.at(i).at(j)!=0)
			{
				B.fput(i,j,MatrixB.at(i).at(j));
			}
		}
	}


	KW_SparseMatrix C(A.m,B.n,0);
	KW_SparseMatrix::KW_multiply(A,B,C);

	int iIndex=0;
	Result.clear();
	for (int i=0;i<C.m;i++)
	{
		vector<float> CurrentRow;
		for (int j=0;j<C.n;j++)
		{
			iIndex=0;
			while (iIndex<C.vol)
			{
				if (C.indx[iIndex]==i&&C.jndx[iIndex]==j)
				{
					break;
				}
				iIndex++;
			}
			if (iIndex!=C.vol)
			{
				CurrentRow.push_back(C.array[iIndex]);
			}
			else
			{
				CurrentRow.push_back(0);
			}
		}
		Result.push_back(CurrentRow);
	}
}