YsArray <YsShellExt_SweepInfoMultiStep::Quad> YsShellExt_SweepInfoMultiStep::MakeSideFaceAndFirstToLastVertexMapping(const YsShellExt &shl)
{
	YsShellExt_Mapping <YsShellVertexHandle,YsShellVertexHandle>::CleanUp();

	YsArray <Quad> quadArray;
	for(YSSIZE_T edIdx=0; edIdx<=srcEdVtHd.GetN()-2; edIdx+=2)
	{
		YSSIZE_T idxInLayer[2];
		if(YSOK==srcVtKeyToMidPointIndex.FindElement(idxInLayer[0],shl.GetSearchKey(srcEdVtHd[edIdx])) &&
		   YSOK==srcVtKeyToMidPointIndex.FindElement(idxInLayer[1],shl.GetSearchKey(srcEdVtHd[edIdx+1])))
		{
			YsShellVertexHandle curEdVtHd[2]={srcEdVtHd[edIdx],srcEdVtHd[edIdx+1]};
			for(auto &layer : layerArray)
			{
				YsShellVertexHandle nxtEdVtHd[2]={layer.pointArray[idxInLayer[0]].vtHd,layer.pointArray[idxInLayer[1]].vtHd};
				quadArray.Increment();
				quadArray.Last().quadVtHd[0]=curEdVtHd[1];
				quadArray.Last().quadVtHd[1]=curEdVtHd[0];
				quadArray.Last().quadVtHd[2]=nxtEdVtHd[0];
				quadArray.Last().quadVtHd[3]=nxtEdVtHd[1];

				curEdVtHd[0]=nxtEdVtHd[0];
				curEdVtHd[1]=nxtEdVtHd[1];
			}

			if(YSTRUE!=YsShellExt_VertexToVertexMapping::CheckMappingExist(shl,srcEdVtHd[edIdx]))
			{
				YsShellExt_VertexToVertexMapping::AddMapping(shl,srcEdVtHd[edIdx],  curEdVtHd[0]);
			}
			if(YSTRUE!=YsShellExt_VertexToVertexMapping::CheckMappingExist(shl,srcEdVtHd[edIdx+1]))
			{
				YsShellExt_VertexToVertexMapping::AddMapping(shl,srcEdVtHd[edIdx+1],curEdVtHd[1]);
			}
		}
	}
	return quadArray;
}
YsArray <YsShellExt_RoundUtil::VertexPositionPair> YsShellExt_RoundUtil::MakeRoundedVertexSequence(const YsShell &shl,YSSIZE_T nVt,const YsShellVertexHandle vtHdArrayIn[],YSBOOL isLoop) const
{
	YsArray <YsShellVertexHandle> orgVtHdArray(nVt,vtHdArrayIn);
	YsArray <VertexPositionPair> newVtHdArray;

	for(YSSIZE_T orgVtIdx=0; orgVtIdx<orgVtHdArray.GetN(); ++orgVtIdx)
	{
		YSBOOL rounded=YSFALSE;
		for(const auto &roundCorner : cornerArray)
		{
			if(roundCorner.fromVtHd==orgVtHdArray[orgVtIdx])
			{
				int forward=0,backward=1;

				if(roundCorner.toVtHd[0]==orgVtHdArray.GetCyclic(orgVtIdx-1))
				{
					forward=1;
					backward=0;
				}
				else if(roundCorner.toVtHd[1]==orgVtHdArray.GetCyclic(orgVtIdx-1))
				{
					forward=0;
					backward=1;
				}
				else
				{
					continue;
				}

				YSBOOL skipFirst=YSFALSE;

				if(0<newVtHdArray.GetN() && newVtHdArray.Last().pos==roundCorner.subDiv[backward].Last().pos)
				{
					skipFirst=YSTRUE;
				}

				newVtHdArray.Append(roundCorner.subDiv[backward]);

				newVtHdArray.Increment();
				newVtHdArray.Last().vtHd=orgVtHdArray[orgVtIdx];
				newVtHdArray.Last().pos=roundCorner.roundedCornerPos;

				for(YSSIZE_T i=roundCorner.subDiv[forward].GetN()-1; 0<=i; --i)
				{
					if(YSTRUE==skipFirst)
					{
						skipFirst=YSFALSE;
						continue;
					}
					newVtHdArray.Append(roundCorner.subDiv[forward][i]);
				}

				rounded=YSTRUE;
			}
		}
		if(YSTRUE!=rounded)
		{
			newVtHdArray.Increment();
			newVtHdArray.Last().vtHd=orgVtHdArray[orgVtIdx];
			newVtHdArray.Last().pos=shl.GetVertexPosition(newVtHdArray.Last().vtHd);
		}
	}

	if(2<=newVtHdArray.GetN() && YSTRUE==isLoop && newVtHdArray[0].pos==newVtHdArray.Last().pos)
	{
		newVtHdArray.DeleteLast();
	}

	return newVtHdArray;
}
YSRESULT YsShellExt_RoundUtil3d::SetUpForAroundPolygonGroup(
    const YsShellExt &shl,
    YSSIZE_T nPl,const YsShellPolygonHandle plHdArray[])
{
	CleanUp();

	if(YSTRUE!=shl.IsSearchEnabled())
	{
		YsPrintf("%s\n",__FUNCTION__);
		YsPrintf("  This function requires a search table.\n");
		return YSERR;
	}

	YsShellExt_BoundaryInfo boundary;

	boundary.MakeInfo((const YsShell &)shl,nPl,plHdArray);
	if(YSOK!=boundary.CacheContour((const YsShell &)shl))
	{
		return YSERR;
	}

	YsShellPolygonStore sideAPolygon((const YsShell &)shl),sideBPolygon((const YsShell &)shl);
	sideAPolygon.AddPolygon(nPl,plHdArray);

	YsArray <YsShellPolygonHandle> sideAPolygonArray(nPl,plHdArray),sideBPolygonArray;

	YsShellEdgeStore boundaryEdge((const YsShell &)shl);
	for(YSSIZE_T contourIdx=0; contourIdx<boundary.GetNumContour(); ++contourIdx)
	{
		YsArray <YsShellVertexHandle> contourVtHd;
		boundary.GetContour(contourVtHd,contourIdx);

		if(3<=contourVtHd.GetN())
		{
			if(contourVtHd[0]!=contourVtHd.Last())
			{
				const YsShellVertexHandle vtHd0=contourVtHd[0];
				contourVtHd.Append(vtHd0);
			}

			for(YSSIZE_T vtIdx=0; vtIdx<contourVtHd.GetN()-1; ++vtIdx)
			{
				boundaryEdge.AddEdge(contourVtHd[vtIdx],contourVtHd[vtIdx+1]);

				YSSIZE_T nVtPl;
				const YsShellPolygonHandle *vtPlHd;
				shl.FindPolygonFromVertex(nVtPl,vtPlHd,contourVtHd[vtIdx]);

				for(YSSIZE_T plIdx=0; plIdx<nVtPl; ++plIdx)
				{
					if(YSTRUE!=sideAPolygon.IsIncluded(vtPlHd[plIdx]) &&
					   YSTRUE!=sideBPolygon.IsIncluded(vtPlHd[plIdx]))
					{
						sideBPolygon.AddPolygon(vtPlHd[plIdx]);
						sideBPolygonArray.Append(vtPlHd[plIdx]);
					}
				}
			}
		}
	}
	return SetUpForVertexSequenceAndPolygonArray(
	    shl,
	    boundary.GetContourAll(),
	    sideAPolygonArray,
	    sideBPolygonArray);
}
void YsShellExt_PatchBetweenTwoConstEdge::MinimizeDihedralAngleSum(void)
{
	YsArray <YsStaticArray <YsShellVertexHandle,2> > allEdge;

	YsShellEdgeEnumHandle edHd=NULL;
	while(YSOK==shl.MoveToNextEdge(edHd))
	{
		YsShellVertexHandle edVtHd[2];
		shl.GetEdge(edVtHd,edHd);
		if(0==shl.GetNumConstEdgeUsingEdgePiece(edVtHd))
		{
			allEdge.Increment();
			allEdge.Last()[0]=edVtHd[0];
			allEdge.Last()[1]=edVtHd[1];
		}
	}

	for(;;)
	{
		YSBOOL improvement=YSFALSE;

		for(auto &edVtHd : allEdge)
		{
printf("%s %d\n",__FUNCTION__,__LINE__);
YsVec3 edVtPos[2]={shl.GetVertexPosition(edVtHd[0]),shl.GetVertexPosition(edVtHd[1])};
printf("%s %s\n",edVtPos[0].Txt(),edVtPos[1].Txt());
			YsShell_SwapInfo swapInfo;
			if(YSOK==swapInfo.MakeInfo((const YsShell &)shl,edVtHd))
			{
printf("%s %d\n",__FUNCTION__,__LINE__);
				if(0<shl.GetNumPolygonUsingEdge(swapInfo.newDiagonal[0],swapInfo.newDiagonal[1]))
				{
printf("%s %d\n",__FUNCTION__,__LINE__);
					continue;
				}

				int seqId[2];
				if(YSOK!=patchVtKeyToSeqId.FindElement(seqId[0],shl.GetSearchKey(swapInfo.newDiagonal[0])) ||
				   YSOK!=patchVtKeyToSeqId.FindElement(seqId[1],shl.GetSearchKey(swapInfo.newDiagonal[1])) ||
				   seqId[0]==seqId[1])
				{
printf("%s %d\n",__FUNCTION__,__LINE__);
					continue;
				}

				const double oldDhaTotal=YsShellExt_CalculateTotalDihedralAngleAroundEdge(shl,swapInfo.orgDiagonal);

				YsArray <YsShellVertexHandle,4> oldTriVtHd[2];
				shl.GetPolygon(oldTriVtHd[0],swapInfo.triPlHd[0]);
				shl.GetPolygon(oldTriVtHd[1],swapInfo.triPlHd[1]);

				shl.SetPolygonVertex(swapInfo.triPlHd[0],3,swapInfo.newTriVtHd[0]);
				shl.SetPolygonVertex(swapInfo.triPlHd[1],3,swapInfo.newTriVtHd[1]);

				const double newDhaTotal=YsShellExt_CalculateTotalDihedralAngleAroundEdge(shl,swapInfo.newDiagonal);
printf("%lf %lf\n",newDhaTotal,oldDhaTotal);
				if(newDhaTotal<oldDhaTotal-YsTolerance)
				{
printf("%s %d\n",__FUNCTION__,__LINE__);
					improvement=YSTRUE;
					edVtHd[0]=swapInfo.newDiagonal[0];
					edVtHd[1]=swapInfo.newDiagonal[1];
				}
				else
				{
					shl.SetPolygonVertex(swapInfo.triPlHd[0],oldTriVtHd[0]);
					shl.SetPolygonVertex(swapInfo.triPlHd[1],oldTriVtHd[1]);
				}
			}
		}

		if(YSTRUE!=improvement)
		{
			break;
		}
	}
}