YSRESULT YsShellExt_RoundUtil3d::SetUpForVertexSequence(
	const YsShellExt &shl,
	YSSIZE_T nVt,const YsShellVertexHandle vtHdArray[])
{
	CleanUp();

	if(2>nVt || YSTRUE!=shl.IsSearchEnabled())
	{
		return YSERR;
	}

	YSSIZE_T nEdPl;
	const YsShellPolygonHandle *edPlHd;
	if(YSOK==shl.FindPolygonFromEdgePiece(nEdPl,edPlHd,vtHdArray[0],vtHdArray[1]) && 2==nEdPl)
	{
		YsArray <YsShellPolygonHandle> sideAPolygonArray=YsShellExt_TrackingUtil::TrackPolygonOneSideOfVertexSequence(
		    shl,nVt,vtHdArray,1,edPlHd);
		YsArray <YsShellPolygonHandle> sideBPolygonArray=YsShellExt_TrackingUtil::TrackPolygonOneSideOfVertexSequence(
		    shl,nVt,vtHdArray,1,edPlHd+1);

		if(0==sideAPolygonArray.GetN() || 0==sideBPolygonArray.GetN())
		{
			return YSERR;
		}

		YsArray <YsArray <YsShellVertexHandle> > allBoundary(1,NULL);
		allBoundary[0].Set(nVt,vtHdArray);
		return YsShellExt_RoundUtil3d::SetUpForVertexSequenceAndPolygonArray(shl,allBoundary,sideAPolygonArray,sideBPolygonArray);
	}
	return YSERR;
}
Exemplo n.º 2
0
Arquivo: main.cpp Projeto: HLH15/24783
/* static */ void FsLazyWindowApplication::YsShellToVtxNom(std::vector <float> &vtx,std::vector <float> &nom,std::vector <float> &col,const YsShellExt &shl)
{
	vtx.clear();
	nom.clear();
	col.clear();
	for(auto plHd : shl.AllPolygon())
	{
		auto plVtHd=shl.GetPolygonVertex(plHd);
		if(3<=plVtHd.GetN())
		{
			auto plNom=shl.GetNormal(plHd);
			for(auto vtHd : plVtHd)
			{
				auto vtPos=shl.GetVertexPosition(vtHd);
				vtx.push_back(vtPos.xf());
				vtx.push_back(vtPos.yf());
				vtx.push_back(vtPos.zf());
				nom.push_back(plNom.xf());
				nom.push_back(plNom.yf());
				nom.push_back(plNom.zf());
				col.push_back(0);
				col.push_back(0);
				col.push_back(1);
				col.push_back(0.5);
			}
		}
	}
}
void YsShellExt_SewingInfo::MakeEdgeMidVertexInfo(const YsShellExt &shl)
{
	edgeMidVtx.CleanUp();
	edgeMidVtx.SetShell(shl.Conv());
	for(auto &vone : vtxOnEdge)
	{
		YsShell_LocalOperation::EdgeMidVertex *midVtx=edgeMidVtx.FindAttrib(vone.edVtHd[0],vone.edVtHd[1]);
		if(NULL==midVtx)
		{
			YsShell_LocalOperation::EdgeMidVertex newEdgeMidVtx;
			newEdgeMidVtx.edge[0]=vone.edVtHd[0];
			newEdgeMidVtx.edge[1]=vone.edVtHd[1];
			newEdgeMidVtx.midVtHd.MakeUnitLength(vone.createdVtHd);
			edgeMidVtx.SetAttrib(vone.edVtHd,newEdgeMidVtx);
		}
		else
		{
			midVtx->midVtHd.Append(vone.createdVtHd);
		}
	}

	for(auto hd : edgeMidVtx.AllHandle())
	{
		auto &edgVtxInfo=edgeMidVtx.GetAttrib(hd);
		if(1<edgVtxInfo.midVtHd.GetN())
		{
			YsArray <double> dist(edgVtxInfo.midVtHd.GetN(),NULL);
			for(YSSIZE_T idx=0; idx<edgVtxInfo.midVtHd.GetN(); ++idx)
			{
				dist[idx]=shl.GetEdgeLength(edgVtxInfo.edge[0],edgVtxInfo.midVtHd[idx]);
			}
			YsQuickSort(dist.GetN(),dist.GetEditableArray(),edgVtxInfo.midVtHd.GetEditableArray());
		}
	}
}
YSRESULT YsShellExt_RoundUtil::SetUpRoundConstEdge(const YsShellExt &shl,YsShellExt::ConstEdgeHandle ceHd,const YsShellVertexStore *roundVtx)
{
	YsArray <YsShellVertexHandle> ceVtHd;
	YSBOOL isLoop;
	shl.GetConstEdge(ceVtHd,isLoop,ceHd);

	if(YSTRUE==isLoop && 3>ceVtHd.GetN())
	{
		return YSERR;
	}
	else if(YSTRUE!=isLoop && 2>ceVtHd.GetN())
	{
		return YSERR;
	}

	if(YSTRUE==isLoop)
	{
		ceVtHd.Append(ceVtHd[0]);
		ceVtHd.Append(ceVtHd[1]);
	}

	for(YSSIZE_T idx=1; idx<ceVtHd.GetN()-1; ++idx)
	{
		if(NULL==roundVtx || YSTRUE==roundVtx->IsIncluded(ceVtHd[idx]))
		{
			const YsShellVertexHandle toVtHd[2]={ceVtHd[idx-1],ceVtHd[idx+1]};
			AddRoundCorner((const YsShell &)shl,ceVtHd[idx],toVtHd);
		}
	}

	targetCeKeyArray.Append(shl.GetSearchKey(ceHd));

	return YSOK;
}
void YsShellExt_SweepInfo::MakeInfo(
    const YsShellExt &shl,
    YSSIZE_T nPl,const YsShellPolygonHandle plHdArray[],
    YSSIZE_T nCe,const YsShellExt::ConstEdgeHandle ceHdArray[])
{
	CleanUp();

	YsShellExt_BoundaryInfo::MakeInfo(*(const YsShell *)&shl,nPl,plHdArray);

	allSrcVtHd.SetShell((const YsShell &)shl);
	for(YSSIZE_T idx=0; idx<nPl; ++idx)
	{
		YsArray <YsShellVertexHandle,4> plVtHd;
		shl.GetPolygon(plVtHd,plHdArray[idx]);
		for(auto vtHd : plVtHd)
		{
			allSrcVtHd.AddVertex(vtHd);
		}
	}
	for(YSSIZE_T idx=0; idx<nCe; ++idx)
	{
		YsArray <YsShellVertexHandle,4> ceVtHd;
		YSBOOL isLoop;
		shl.GetConstEdge(ceVtHd,isLoop,ceHdArray[idx]);
		for(auto vtHd : ceVtHd)
		{
			allSrcVtHd.AddVertex(vtHd);
		}
	}

	for(YSSIZE_T ceIdx=0; ceIdx<nCe; ++ceIdx)
	{
		YSBOOL isLoop;
		YsArray <YsShellVertexHandle,16> ceVtHd;
		shl.GetConstEdge(ceVtHd,isLoop,ceHdArray[ceIdx]);

		if(2<=ceVtHd.GetN())
		{
			if(YSTRUE==isLoop)
			{
				YsShellVertexHandle first=ceVtHd[0];
				ceVtHd.Append(first);
			}

			for(int edIdx=0; edIdx<ceVtHd.GetN()-1; ++edIdx)
			{
				if(YSTRUE!=visited.IsIncluded(ceVtHd[edIdx],ceVtHd[edIdx+1]))
				{
					visited.AddEdge(ceVtHd[edIdx],ceVtHd[edIdx+1]);
					srcEdVtHd.Append(ceVtHd[edIdx]);
					srcEdVtHd.Append(ceVtHd[edIdx+1]);
				}
			}
		}
	}
}
YSRESULT YsShellExt_SweepInfoMultiStep::SetUpSolidOfRevolution(
    const YsShellExt &shl,const YsVec3 &axiso,const YsVec3 &axisv,int nStep,const double stepAngle,const YsVec3 &stepOffset,YSBOOL closeSolid)
{
	if(0<nStep)
	{
		const auto &allVtHd=GetVertexAll(); // Need the original normal.

		const YSSIZE_T nMidLayer=(YSTRUE==closeSolid ? nStep-1 : nStep);
		SetUpNLayer(shl,nStep+1); // 2015/03/05 I think I ended up making the second parameter to be (number of layers)+1....

		for(auto layerIdx=0; layerIdx<nMidLayer; ++layerIdx)
		{
			const double angle=(double)(layerIdx+1)*stepAngle;
			YsRotation rot(axisv,angle);

			for(auto vtHd : allVtHd)
			{
				YSSIZE_T indexInLayer;
				if(YSOK==srcVtKeyToMidPointIndex.FindElement(indexInLayer,shl.GetSearchKey(vtHd)))
				{
					auto &point=layerArray[layerIdx].pointArray[indexInLayer];
					point.pos=rot*shl.GetVertexPosition(vtHd)+stepOffset*(double)(layerIdx+1);
					if(point.pos==shl.GetVertexPosition(vtHd))  // Vertex on axis
					{
						point.vtHd=vtHd;
					}
					else
					{
						point.vtHd=NULL;
					}
				}
			}
		}
		if(YSTRUE==closeSolid)
		{
			for(auto vtHd : allVtHd)
			{
				YSSIZE_T indexInLayer;
				if(YSOK==srcVtKeyToMidPointIndex.FindElement(indexInLayer,shl.GetSearchKey(vtHd)))
				{
					auto &point=layerArray[nStep-1].pointArray[indexInLayer];
					point.vtHd=vtHd;
					point.pos=shl.GetVertexPosition(vtHd);
				}
			}
		}

		return YSOK;
	}
	return YSERR;
}
/*static*/ YsArray <double> YsShellExt_SweepInfoMultiStep::CalculateScalingForParallelSweepWithPathAndGuideLine(
    const YsShellExt &shl,const YsVec3 &sweepDir,const YsArray <YsShellVertexHandle> &pathVtHdArray,const YsArray <YsShellVertexHandle> &guideVtHdArray)
{
	YsArray <YsVec3> pathVtPosArray,guideVtPosArray;
	for(auto vtHd : pathVtHdArray)
	{
		pathVtPosArray.Append(shl.GetVertexPosition(vtHd));
	}
	for(auto vtHd : guideVtHdArray)
	{
		guideVtPosArray.Append(shl.GetVertexPosition(vtHd));
	}
	return CalculateScalingForParallelSweepWithPathAndGuideLine(sweepDir,pathVtPosArray,guideVtPosArray);
}
void YsShellExt_SweepInfoMultiStep::SetUpNLayer(const YsShellExt &shl,YSSIZE_T nLayer)
{
	// For nLayers, layerArray needs to be nLayer-1 long.

	layerArray.Set(nLayer-1,NULL);
	for(auto &layer : layerArray)
	{
		layer.Initialize();
	}

	for(auto srcVtHd : allSrcVtHd)
	{
		const YSSIZE_T nextIdx=layerArray[0].pointArray.GetN();
		layerArray[0].pointArray.Increment();
		srcVtKeyToMidPointIndex.UpdateElement(shl.GetSearchKey(srcVtHd),nextIdx);
	}

	for(auto idx : layerArray.AllIndex())
	{
		if(0<idx)
		{
			layerArray[idx].pointArray.Set(layerArray[0].pointArray.GetN(),NULL);
		}
		for(auto &point : layerArray[idx].pointArray)
		{
			point.Initialize();
		}
	}
}
YSRESULT YsShellExt_SweepInfoMultiStep::SetUpParallelSweepWithPath(const YsShellExt &shl,YSSIZE_T nPathVt,const YsShellVertexHandle pathVtHdArray[],const double scaling[])
{
	CleanUpLayer();

	if(2<=nPathVt)
	{
		YsArray <YsVec3> pathPnt(nPathVt,NULL);
		for(YSSIZE_T idx=0; idx<nPathVt; ++idx)
		{
			pathPnt[idx]=shl.GetVertexPosition(pathVtHdArray[idx]);
		}

		SetUpNLayer(shl,nPathVt);

		for(auto vtHd : allSrcVtHd)
		{
			YSSIZE_T indexInLayer;
			if(YSOK==srcVtKeyToMidPointIndex.FindElement(indexInLayer,shl.GetSearchKey(vtHd)))
			{
				if(vtHd==pathVtHdArray[0])
				{
					for(auto idx : layerArray.AllIndex())
					{
						auto &point=layerArray[idx].pointArray[indexInLayer];
						point.vtHd=pathVtHdArray[idx+1];
						point.pos=shl.GetVertexPosition(pathVtHdArray[idx+1]);
					}
				}
				else
				{
					for(auto idx : layerArray.AllIndex())
					{
						auto &point=layerArray[idx].pointArray[indexInLayer];
						point.pos=(shl.GetVertexPosition(vtHd)-pathPnt[0])*scaling[idx+1]+pathPnt[idx+1];
					}
				}
			}
		}

		return YSOK;
	}
	return YSERR;

}
Exemplo n.º 10
0
Arquivo: main.cpp Projeto: HLH15/24783
void FsLazyWindowApplication::VtxNomToYsShell(YsShellExt &shl,const std::vector <float> &vtx,const std::vector <float> &nom)
{
	PrepareLatticeForConnection(ltc,vtx);

	shl.CleanUp();
	for(int i=0; i<vtx.size()/9; ++i)
	{
		const YsVec3 plNom(nom[i*9],nom[i*9+1],nom[i*9+2]);
		const YsVec3 vtPos[3]=
		{
			YsVec3(vtx[i*9  ],vtx[i*9+1],vtx[i*9+2]),
			YsVec3(vtx[i*9+3],vtx[i*9+4],vtx[i*9+5]),
			YsVec3(vtx[i*9+6],vtx[i*9+7],vtx[i*9+8]),
		};
		YsShell::VertexHandle vtHd[3];
		for(int i=0; i<3; ++i)
		{
			vtHd[i]=nullptr;
			auto idx=ltc.GetBlockIndex(vtPos[i]);
			if(true==ltc.IsInRange(idx))
			{
				for(auto tstVtHd : ltc.Elem(idx.x(),idx.y(),idx.z()))
				{
					if(shl.GetVertexPosition(tstVtHd)==vtPos[i])
					{
						vtHd[i]=tstVtHd;
						break;
					}
				}
			}
			if(nullptr==vtHd[i])
			{
				vtHd[i]=shl.AddVertex(vtPos[i]);
				if(true==ltc.IsInRange(idx))
				{
					ltc.Elem(idx.x(),idx.y(),idx.z()).push_back(vtHd[i]);
				}
			}
		}
		YsShell::PolygonHandle plHd;
		plHd=shl.AddPolygon(3,vtHd);
		shl.SetPolygonNormal(plHd,plNom);
	}
}
YSRESULT YsShellExt_SewingInfo::MakeInfo(const YsShellExt &shl,YSSIZE_T nVt,const YsShellVertexHandle vtHd[])
{
	if(0<nVt)
	{
		YsArray <YsVec3> pathPnt(nVt,NULL);
		for(YSSIZE_T idx=0; idx<nVt; ++idx)
		{
			pathPnt[idx]=shl.GetVertexPosition(vtHd[idx]);
		}
		return MakeInfoWithVertexHandle(shl,vtHd[0],nVt,pathPnt,vtHd);
	}
	return YSERR;
}
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;
}
YSRESULT YsShellExt_SewingInfo::MakeInfoWithVertexHandle(
	    const YsShellExt &shl,YsShellVertexHandle vtHdFrom,
	    YSSIZE_T nPathIn,const YsVec3 pathPntIn[],const YsShellVertexHandle pathVtHdIn[])
{
	// if(NULL!=goalVtHd), goalVtHd must be at path[nPath-1].

	if(0>=nPathIn)
	{
		return YSERR;
	}
	if(0<nPathIn && pathPntIn[0]==shl.GetVertexPosition(vtHdFrom))
	{
		return MakeInfoWithVertexHandle(shl,vtHdFrom,nPathIn-1,pathPntIn+1,pathVtHdIn+1);
	}


	YsConstArrayMask <YsVec3> pathPnt(nPathIn,pathPntIn);
	YsConstArrayMask <YsShellVertexHandle> pathVtHd(nPathIn,pathVtHdIn);

	CleanUp();

	YsShellVertexHandle currentVtHd=vtHdFrom;
	YsShell::Edge currentEdge(NULL,NULL);
	YsShellPolygonHandle currentPlHd=NULL;
	YsVec3 currentPos=shl.GetVertexPosition(vtHdFrom);

	for(YSSIZE_T idx=0; idx<pathPnt.GetN(); ++idx)
	{
		if(YSOK!=CrawlOneSegment(
		    currentVtHd,currentEdge,currentPlHd,currentPos,shl,pathPnt[idx],pathVtHd[idx]))
		{
			return YSERR;
		}
	}

	return YSOK;
}
Exemplo n.º 14
0
Arquivo: main.cpp Projeto: HLH15/24783
YsShell::PolygonHandle FsLazyWindowApplication::PickedTriangle(int mx,int my) const
{
	YsVec3 o,v;
	drawEnv.TransformScreenCoordTo3DLine(o,v,mx,my);

	YsShell::PolygonHandle picked=nullptr;
	double pickedDist=0.0;
	for(auto plHd : shl.AllPolygon())
	{
		auto plVtHd=shl.GetPolygonVertex(plHd);
		const YsVec3 tri[3]=
		{
			shl.GetVertexPosition(plVtHd[0]),
			shl.GetVertexPosition(plVtHd[1]),
			shl.GetVertexPosition(plVtHd[2]),
		};
		YsPlane pln;
		pln.MakePlaneFromTriangle(tri[0],tri[1],tri[2]);

		YsVec3 itsc;
		if(YSOK==pln.GetIntersection(itsc,o,v))
		{
			auto side=YsCheckInsideTriangle3(itsc,tri);
			if(YSINSIDE==side || YSBOUNDARY==side)
			{
				auto dist=(itsc-o)*v; // Gives distance
				if(0.0<dist && (picked==nullptr || dist<pickedDist))
				{
					picked=plHd;
					pickedDist=dist;
				}
			}
		}
	}

	return picked;
}
YSBOOL YsShellExt_RoundUtil3d::IsPolygonOnTheSameContour(const YsShellExt &shl,YsShellPolygonHandle plHd,const YsHashTable <YSSIZE_T> &vtKeyToBoundaryIdx)
{
	auto plVtHd=shl.GetPolygonVertex(plHd);
	if(0<plVtHd.GetN())
	{
		YSSIZE_T boundaryIdx0;
		if(YSOK!=vtKeyToBoundaryIdx.FindElement(boundaryIdx0,shl.GetSearchKey(plVtHd[0])))
		{
			return YSFALSE;
		}

		for(auto vtHd : plVtHd)
		{
			YSSIZE_T boundaryIdx;
			if(YSOK!=vtKeyToBoundaryIdx.FindElement(boundaryIdx,shl.GetSearchKey(vtHd)) || boundaryIdx!=boundaryIdx0)
			{
				return YSFALSE;
			}
		}

		return YSTRUE;
	}
	return YSFALSE;
}
YSRESULT YsShellExt_SewingInfo::MakeInfo(const YsShellExt &shl,YsShellVertexHandle vtHdFrom,YsShellVertexHandle vtHdTo)
{
	const YsVec3 pathPnt[1]={shl.GetVertexPosition(vtHdTo)};
	const YsShellVertexHandle pathVtHd[1]={vtHdTo};
	return MakeInfoWithVertexHandle(shl,vtHdFrom,1,pathPnt,pathVtHd);
}
void YsShellExt_SewingInfo::MakePolygonSplitInfo(const YsShellExt &shl)
{
	// A concave polygon may be cut twice by one crawling.
	YsShellPolygonAttribTable <YsArray <YsArray <YsShellVertexHandle,2> > > plHdToDivider(shl.Conv());

	for(auto &v : vtxSequence)
	{
		if(NULL==v.vtHd)
		{
			if(0<=v.vtxOnEdgeIdx)
			{
				v.vtHd=vtxOnEdge[v.vtxOnEdgeIdx].createdVtHd;
			}
			else if(0<=v.vtxOnPlgIdx)
			{
				v.vtHd=vtxOnPlg[v.vtxOnPlgIdx].vtHd;
			}
		}
	}

	{
		YsShellPolygonHandle currentPlHd=NULL;
		YsArray <YsShellVertexHandle,2> currentDivider;
		for(YSSIZE_T idx=0; idx<vtxSequence.GetN(); ++idx)
		{
			if(0==currentDivider.GetN())
			{
				currentPlHd=vtxSequence[idx].plHd;
				currentDivider.Append(vtxSequence[idx].vtHd);
			}
			else
			{
				currentDivider.Append(vtxSequence[idx].vtHd);

				if(idx==vtxSequence.GetN()-1 || vtxSequence[idx].plHd!=currentPlHd)
				{
					if(2<=currentDivider.GetN())
					{
						YsArray <YsArray <YsShellVertexHandle,2> > *pldv=plHdToDivider[currentPlHd];
						if(NULL==pldv)
						{
							YsArray <YsArray <YsShellVertexHandle,2> > newDividerArray(1,NULL);
							newDividerArray[0].MoveFrom(currentDivider);
							plHdToDivider.SetAttrib(currentPlHd,newDividerArray);
						}
						else
						{
							pldv->Append(currentDivider);
						}
					}

					currentDivider.CleanUp();
					currentDivider.Append(vtxSequence[idx].vtHd);
				}

				currentPlHd=vtxSequence[idx].plHd;
			}
		}
	}

	for(auto hashHd : plHdToDivider.AllHandle())
	{
		auto plKey=plHdToDivider.GetKey(hashHd);
		auto plHd=shl.FindPolygon(plKey);
		auto &divider=*plHdToDivider[plHd];

		YsSegmentedArray <YsArray <YsShellVertexHandle,4>,4> plVtHd(1,NULL);
		plVtHd[0]=shl.GetPolygonVertex(plHd);

		for(auto d : divider)
		{
			YsArray <YsShellVertexHandle,4> fragment;
			for(auto &pl : plVtHd)
			{
				if(YSOK==YsShellExt_SplitLoopByHandleAndMidNode(pl,fragment,d))
				{
					plVtHd.Append(fragment);
					break;
				}
			}
		}

		plgSplit.Increment();
		plgSplit.Last().plHd=plHd;
		plgSplit.Last().plVtHdArray=plVtHd;
	}
}
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);
}
Exemplo n.º 19
0
Arquivo: main.cpp Projeto: HLH15/24783
void FsLazyWindowApplication::CacheBoundingBox(void)
{
	shl.GetBoundingBox(min,max);
}
YSRESULT YsShellExt_SweepInfoMultiStep::SetUpNonParallelSweepWithPath(const YsShellExt &shl,YSSIZE_T nPathVt,const YsShellVertexHandle pathVtHdArrayIn[],YSBOOL isLoop,const double scaling[],ORIENTATION_CONTROL_TYPE oriconTypeMid,ORIENTATION_CONTROL_TYPE oriconTypeLast)
{
	YsArray <YsShellVertexHandle> pathVtHd(nPathVt,pathVtHdArrayIn);
	for(auto idx=pathVtHd.GetN()-1; 0<idx; --idx)
	{
		if(pathVtHd[idx]==pathVtHd[idx-1])
		{
			pathVtHd.Delete(idx);
		}
	}

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

	if(2>pathVtHd.GetN() || (YSTRUE==isLoop && 3>pathVtHd.GetN()))
	{
		return YSERR;
	}



	const auto &allVtHd=GetVertexAll();
	YsArray <YsVec3> iniPos;
	for(auto vtHd : allVtHd)
	{
		iniPos.Append(shl.GetVertexPosition(vtHd));
	}
	YsVec3 lfpNom;
	if(YSOK!=YsFindLeastSquareFittingPlaneNormal(lfpNom,iniPos))
	{
		return YSERR;
	}

	if(0.0>lfpNom*(shl.GetVertexPosition(pathVtHd[1])-shl.GetVertexPosition(pathVtHd[0])))
	{
		lfpNom=-lfpNom;
	}



	YsArray <YsVec3> nomArray(nPathVt,NULL);
	nomArray[0]=lfpNom;

	for(YSSIZE_T idx=1; idx<nPathVt-1; ++idx)
	{
		switch(oriconTypeMid)
		{
		case ORICON_PREVIOUS_SEGMENT:
			nomArray[idx]=YsUnitVector(shl.GetVertexPosition(pathVtHd[idx])-shl.GetVertexPosition(pathVtHd[idx-1]));
			break;
		case ORICON_NEXT_SEGMENT:
			nomArray[idx]=YsUnitVector(shl.GetVertexPosition(pathVtHd[idx+1])-shl.GetVertexPosition(pathVtHd[idx]));
			break;
		case ORICON_AVERAGE_ANGLE:
			{
				auto v1=YsUnitVector(shl.GetVertexPosition(pathVtHd[idx])-shl.GetVertexPosition(pathVtHd[idx-1]));
				auto v2=YsUnitVector(shl.GetVertexPosition(pathVtHd[idx+1])-shl.GetVertexPosition(pathVtHd[idx]));
				nomArray[idx]=YsUnitVector(v1+v2);
			}
			break;
		case ORICON_FROMPREVPOINT_TO_NEXTPOINT:
			nomArray[idx]=YsUnitVector(shl.GetVertexPosition(pathVtHd[idx+1])-shl.GetVertexPosition(pathVtHd[idx-1]));
			break;
		}
	}

	switch(oriconTypeLast)
	{
	case ORICON_PREVIOUS_SEGMENT:
	case ORICON_NEXT_SEGMENT:
		nomArray.Last()=YsUnitVector(shl.GetVertexPosition(pathVtHd[nPathVt-1])-shl.GetVertexPosition(pathVtHd[nPathVt-2]));
		break;
	case ORICON_AVERAGE_ANGLE:               // There's no next point
	case ORICON_FROMPREVPOINT_TO_NEXTPOINT:  // There's no next point
		if(YSTRUE==isLoop)
		{
			YsVec3 v1=YsUnitVector(shl.GetVertexPosition(pathVtHd[0])-shl.GetVertexPosition(pathVtHd[nPathVt-1]));
			YsVec3 v2=YsUnitVector(shl.GetVertexPosition(pathVtHd[nPathVt-1])-shl.GetVertexPosition(pathVtHd[nPathVt-2]));
			v1.Normalize();
			v2.Normalize();
			nomArray.Last()=YsUnitVector(v1+v2);
		}
		else
		{
			nomArray.Last()=YsUnitVector(shl.GetVertexPosition(pathVtHd[nPathVt-1])-shl.GetVertexPosition(pathVtHd[nPathVt-2]));
		}
		break;
	}

	return SetUpNonParallelSweepWithPath(shl,nPathVt,pathVtHd,isLoop,nomArray,scaling);
}
YSRESULT YsShellExt_SweepInfoMultiStep::SetUpNonParallelSweepWithPath(const YsShellExt &shl,YSSIZE_T nPathVt,const YsShellVertexHandle pathVtHdArrayIn[],YSBOOL isLoop,const YsVec3 nom[],const double scaling[])
{
	const auto &allVtHd=GetVertexAll(); // Need the original normal.


	CleanUpLayer();

	if(2<=nPathVt)
	{
		YsConstArrayMask <YsShellVertexHandle> pathVtHd(nPathVt,pathVtHdArrayIn);
		YsArray <YsVec3> pathPnt(nPathVt,NULL);
		for(YSSIZE_T idx=0; idx<pathVtHd.GetN(); ++idx)
		{
			pathPnt[idx]=shl.GetVertexPosition(pathVtHd[idx]);
		}

		const YSSIZE_T nLayer=(YSTRUE==isLoop ? nPathVt : nPathVt-1);
		SetUpNLayer(shl,nLayer+1);   // First set of vertices are not counted as a layer.  Number of layers will be nPathVt-1.

		// Rotation must be progressive.  Why?  Assume nom[0] and nom[5] are 180 degrees opposite.
		// If the rotation is calculated for each layer by YsRotation::MakeAtoB(nom[0],nom[layerIndex]),
		// rotational axis for nom[5] may become different from other layers, and thus the continuity is lost.
		// The solution is calculating the rotation for each step progressively.

		YsArray <YsMatrix3x3> rot(nPathVt-1,NULL);
		YsMatrix3x3 prevRot;
		for(int layerIdx=0; layerIdx<nPathVt-1; ++layerIdx)
		{
			YsRotation thisRot;
			thisRot.MakeAtoB(nom[layerIdx],nom[layerIdx+1]);
			prevRot*=thisRot;
			rot[layerIdx]=prevRot;
		}

		for(auto layerIdx=0; layerIdx<nPathVt-1; ++layerIdx)
		{
			YsMatrix4x4 tfm;

			tfm.Translate(pathPnt[layerIdx+1]);
			tfm*=rot[layerIdx];
			tfm.Scale(scaling[layerIdx+1],scaling[layerIdx+1],scaling[layerIdx+1]);
			tfm.Translate(-pathPnt[0]);

			for(auto vtHd : allVtHd)
			{
				YSSIZE_T indexInLayer;
				if(YSOK==srcVtKeyToMidPointIndex.FindElement(indexInLayer,shl.GetSearchKey(vtHd)))
				{
					auto &point=layerArray[layerIdx].pointArray[indexInLayer];
					if(vtHd==pathVtHd[0])
					{
						point.vtHd=pathVtHd[layerIdx+1];
						point.pos=shl.GetVertexPosition(pathVtHd[layerIdx+1]);
					}
					else
					{
						point.vtHd=NULL;
						point.pos=tfm*shl.GetVertexPosition(vtHd);
					}
				}
			}
		}

		if(YSTRUE==isLoop)
		{
			for(auto vtHd : allVtHd)
			{
				YSSIZE_T indexInLayer;
				if(YSOK==srcVtKeyToMidPointIndex.FindElement(indexInLayer,shl.GetSearchKey(vtHd)))
				{
					auto &point=layerArray[nLayer-1].pointArray[indexInLayer];
					point.vtHd=vtHd;
					point.pos=shl.GetVertexPosition(vtHd);
				}
			}
		}

		return YSOK;
	}
	return YSERR;
}
YSRESULT YsShellExt_RoundUtil3d::SetUpForVertexSequenceAndPolygonArray(
    const YsShellExt &shl,
    const YsArray <YsArray <YsShellVertexHandle> > &allBoundary,
    const YsArray <YsShellPolygonHandle> &sideAPolygonArray,
    const YsArray <YsShellPolygonHandle> &sideBPolygonArray)
{
	YsHashTable <YSSIZE_T> vtKeyToBoundaryIdx;
	YsShellEdgeStore boundaryEdge((const YsShell &)shl);
	for(auto idx : allBoundary.AllIndex())
	{
		YsArray <YsShellVertexHandle> contourVtHd=allBoundary[idx];

		for(YSSIZE_T vtIdx=0; vtIdx<contourVtHd.GetN()-1; ++vtIdx)
		{
			if(YSTRUE!=boundaryEdge.IsIncluded(contourVtHd[vtIdx],contourVtHd[vtIdx+1]))
			{
				boundaryEdge.AddEdge(contourVtHd[vtIdx],contourVtHd[vtIdx+1]);
				roundEdgeArray.Increment();
				roundEdgeArray.Last().Initialize();
				roundEdgeArray.Last().edVtHd[0]=contourVtHd[vtIdx];
				roundEdgeArray.Last().edVtHd[1]=contourVtHd[vtIdx+1];
			}
		}
		for(auto vtHd : contourVtHd)
		{
			vtKeyToBoundaryIdx.AddElement(shl.GetSearchKey(vtHd),idx);
		}
	}

	// Boundary edge hash and sideBPolygon store have been constructed.
	YsShellExt_OffsetUtil2d &sideAOffset=offsetUtil[0],&sideBOffset=offsetUtil[1];

	YsShellPolygonStore sideAPolygon((const YsShell &)shl),sideBPolygon((const YsShell &)shl);
	sideAPolygon.AddPolygon(sideAPolygonArray);
	sideBPolygon.AddPolygon(sideBPolygonArray);



	YSBOOL sideAOffsetNecessary=YSFALSE,sideBOffsetNecessary=YSFALSE;
	if(YSTRUE==alwaysUseOffset)
	{
		sideAOffsetNecessary=YSTRUE;
		sideBOffsetNecessary=YSTRUE;
	}
	else
	{
		for(auto boundary : allBoundary)
		{
			YsArray <YsShellVertexHandle> contourVtHd=boundary;

			for(auto vtHd : contourVtHd)
			{
				YsArray <YsShellVertexHandle,16> connVtHdArray;
				shl.GetConnectedVertex(connVtHdArray,vtHd);

				YSBOOL sideAEdgePresent=YSFALSE,sideBEdgePresent=YSFALSE;
				for(auto connVtHd : connVtHdArray)
				{
					if(YSTRUE==boundaryEdge.IsIncluded(vtHd,connVtHd))
					{
						continue;
					}

					if(YSTRUE==IsEdgeUsing(vtHd,connVtHd,shl.Conv(),sideAPolygon))
					{
						sideAEdgePresent=YSTRUE;
					}
					else if(YSTRUE==IsEdgeUsing(vtHd,connVtHd,shl.Conv(),sideBPolygon))
					{
						sideBEdgePresent=YSTRUE;
					}
				}
				if(YSTRUE!=sideAEdgePresent)
				{
					sideAOffsetNecessary=YSTRUE;
				}
				if(YSTRUE!=sideBEdgePresent)
				{
					sideBOffsetNecessary=YSTRUE;
				}
			}
		}
	}

	printf("%s %d\n",__FUNCTION__,__LINE__);
	printf("%d %d\n",sideAOffsetNecessary,sideBOffsetNecessary);

	if(YSTRUE==sideAOffsetNecessary)
	{
		if(YSOK!=sideAOffset.SetUpForOneSideOfVertexSequence(shl,allBoundary,sideAPolygonArray))
		{
			return YSERR;
		}
		for(YSSIZE_T idx=0; idx<sideAOffset.newVtxArray.GetN(); ++idx)
		{
			auto newVtx=sideAOffset.newVtxArray[idx];
			cornerArray.Increment();
			cornerArray.Last().Initialize();
			cornerArray.Last().fromVtHd=newVtx.fromVtHd;
			cornerArray.Last().toVtHd=NULL;
			cornerArray.Last().toPos=newVtx.fromPos+newVtx.dir*newVtx.maxDist;
			cornerArray.Last().offsetUtil=&sideAOffset;
			cornerArray.Last().offsetUtil_newVtxIdx=idx;
			cornerArray.Last().notReallyDistanceLimited=IsPolygonOnTheSameContour(shl,newVtx.limitingPlHd,vtKeyToBoundaryIdx);
		}
	}
	if(YSTRUE==sideBOffsetNecessary)
	{
		if(YSOK!=sideBOffset.SetUpForOneSideOfVertexSequence(shl,allBoundary,sideBPolygonArray))
		{
			return YSERR;
		}
		for(YSSIZE_T idx=0; idx<sideBOffset.newVtxArray.GetN(); ++idx)
		{
			auto newVtx=sideBOffset.newVtxArray[idx];
			cornerArray.Increment();
			cornerArray.Last().Initialize();
			cornerArray.Last().fromVtHd=newVtx.fromVtHd;
			cornerArray.Last().toVtHd=NULL;
			cornerArray.Last().toPos=newVtx.fromPos+newVtx.dir*newVtx.maxDist;
			cornerArray.Last().offsetUtil=&sideBOffset;
			cornerArray.Last().offsetUtil_newVtxIdx=idx;
			cornerArray.Last().notReallyDistanceLimited=IsPolygonOnTheSameContour(shl,newVtx.limitingPlHd,vtKeyToBoundaryIdx);
		}
	}

printf("%s %d\n",__FUNCTION__,__LINE__);

	for(auto boundary : allBoundary)
	{
		YsArray <YsShellVertexHandle> contourVtHd=boundary;

		if(3<=contourVtHd.GetN())
		{
			if(contourVtHd[0]==contourVtHd.Last())
			{
				contourVtHd.DeleteLast();
			}
		}

		for(auto vtHd : contourVtHd)
		{
			YsArray <YsShellVertexHandle,16> connVtHdArray;
			shl.GetConnectedVertex(connVtHdArray,vtHd);

			for(auto connVtHd : connVtHdArray)
			{
				if(YSTRUE==boundaryEdge.IsIncluded(vtHd,connVtHd))
				{
					continue;
				}
				else if((YSTRUE!=sideAOffsetNecessary && YSTRUE==IsEdgeUsing(vtHd,connVtHd,(const YsShell &)shl,sideAPolygon)) ||
				        (YSTRUE!=sideBOffsetNecessary && YSTRUE==IsEdgeUsing(vtHd,connVtHd,(const YsShell &)shl,sideBPolygon)))
				{
					cornerArray.Increment();
					cornerArray.Last().Initialize();
					cornerArray.Last().fromVtHd=vtHd;
					cornerArray.Last().toVtHd=connVtHd;
					cornerArray.Last().toPos=shl.GetVertexPosition(connVtHd);
				}
			}
		}
	}

printf("%s %d\n",__FUNCTION__,__LINE__);

	for(YSSIZE_T cornerIdx=0; cornerIdx<cornerArray.GetN(); ++cornerIdx)
	{
		if(NULL!=cornerArray[cornerIdx].offsetUtil)
		{
			cornerArray[cornerIdx].offsetUtil->newVtxArray[cornerArray[cornerIdx].offsetUtil_newVtxIdx].cornerIdx=cornerIdx;
		}
	}

printf("%s %d\n",__FUNCTION__,__LINE__);

	if(YSOK==CalculateRoundingDirectionAll((const YsShell &)shl))
	{
printf("%s %d\n",__FUNCTION__,__LINE__);
		return YSOK;
	}

printf("%s %d\n",__FUNCTION__,__LINE__);
	CleanUp();
	return YSERR;
}
YSRESULT YsShellExt_SewingInfo::CrawlOneSegment(
		YsShellVertexHandle &currentVtHd,
		YsShell::Edge &currentEdge,
		YsShellPolygonHandle &currentPlHd,
		YsVec3 &currentPos,
		const YsShellExt &shl,
		const YsVec3 &goalPos,
		YsShellVertexHandle goalVtHd)
{
	auto startDir=YsUnitVector(goalPos-currentPos);

	YsShellCrawler crawler;
	crawler.crawlingMode=YsShellCrawler::CRAWL_TO_GOAL;
	crawler.goal=goalPos;

	YSRESULT started=YSERR;
	if(NULL!=currentVtHd)
	{
		started=crawler.Start(shl.Conv(),currentPos,startDir,currentVtHd);
	}
	else if(NULL!=currentEdge[0] && NULL!=currentEdge[1])
	{
		started=crawler.Start(shl.Conv(),currentPos,startDir,currentEdge);
	}
	else if(NULL!=currentPlHd)
	{
		started=crawler.Start(shl.Conv(),currentPos,startDir,currentPlHd);
	}

	if(YSOK==started)
	{
		if(0==vtxSequence.GetN())
		{
			vtxSequence.Increment();
			vtxSequence.Last().Initialize();
			vtxSequence.Last().vtHd=currentVtHd;
			vtxSequence.Last().plHd=crawler.currentPlHd;
			vtxSequence.Last().pos=crawler.currentPos;
		}
		else
		{
			vtxSequence.Last().plHd=crawler.currentPlHd;
		}

// Debugging sphere.srf 371 276 375
// [Selected Vertices]
// Vertex Id:     370  Internal Hash Key:     371  Position: -3.467600  -0.689748   3.535534
// Vertex Id:     275  Internal Hash Key:     276  Position: -4.530637  -1.876651   0.975452
// Vertex Id:     374  Internal Hash Key:     375  Position: -1.964237  -2.939689   3.535534


		YSBOOL watch=YSFALSE;
		while(YSOK==crawler.Crawl(shl.Conv(),0.0,watch))
		{
			if((crawler.currentState==YsShellCrawler::STATE_ON_VERTEX || crawler.currentEdVtHd[0]==crawler.currentEdVtHd[1]) &&
			   crawler.currentEdVtHd[0]==vtxSequence.Last().vtHd)
			{
				vtxSequence.Last().plHd=crawler.currentPlHd;
			}
			else
			{
				switch(crawler.currentState)
				{
				case YsShellCrawler::STATE_IN_POLYGON:
					if(crawler.currentPos==goalPos || 
					   ((NULL==goalVtHd || 0==shl.GetNumPolygonUsingVertex(goalVtHd)) && YSTRUE==crawler.reachedDeadEnd)) // Can happen in the end.
					{
						vtxSequence.Increment();
						vtxSequence.Last().Initialize();
						vtxSequence.Last().plHd=crawler.currentPlHd;
						vtxSequence.Last().vtHd=goalVtHd;
						vtxSequence.Last().pos=crawler.currentPos;
						if(NULL==goalVtHd)
						{
							vtxSequence.Last().vtxOnPlgIdx=(int)vtxOnPlg.GetN();
							vtxOnPlg.Increment();
							vtxOnPlg.Last().plHd=crawler.currentPlHd;
							vtxOnPlg.Last().vtHd=goalVtHd;
							vtxOnPlg.Last().pos=goalPos;
						}
					}
					break;
				case YsShellCrawler::STATE_ON_VERTEX:
					vtxSequence.Increment();
					vtxSequence.Last().Initialize();
					vtxSequence.Last().plHd=crawler.currentPlHd;
					vtxSequence.Last().vtHd=crawler.currentEdVtHd[0];
					vtxSequence.Last().pos=crawler.currentPos;
					break;
				case YsShellCrawler::STATE_ON_EDGE:
					if(crawler.currentEdVtHd[0]==crawler.currentEdVtHd[1])
					{
						vtxSequence.Increment();
						vtxSequence.Last().Initialize();
						vtxSequence.Last().plHd=crawler.currentPlHd;
						vtxSequence.Last().vtHd=crawler.currentEdVtHd[0];
						vtxSequence.Last().pos=crawler.currentPos;
					}
					else
					{
						YsShellVertexHandle onThisVtHd=(crawler.currentPos==goalPos ? goalVtHd : NULL);

						vtxSequence.Increment();
						vtxSequence.Last().Initialize();
						vtxSequence.Last().plHd=crawler.currentPlHd;
						vtxSequence.Last().vtHd=onThisVtHd;
						vtxSequence.Last().vtxOnEdgeIdx=(int)vtxOnEdge.GetN();
						vtxOnEdge.Increment();
						vtxOnEdge.Last().edVtHd[0]=crawler.currentEdVtHd[0];
						vtxOnEdge.Last().edVtHd[1]=crawler.currentEdVtHd[1];
						vtxOnEdge.Last().createdVtHd=onThisVtHd;
						vtxOnEdge.Last().pos=crawler.currentPos;
					}
					break;
				}
			}

			if(YSTRUE==crawler.reachedDeadEnd || goalPos==crawler.currentPos)
			{
				break;
			}
		}


		currentPos=crawler.currentPos;
		switch(crawler.currentState)
		{
		case YsShellCrawler::STATE_IN_POLYGON:
			currentVtHd=NULL;
			currentEdge.edVtHd[0]=NULL;
			currentEdge.edVtHd[1]=NULL;
			currentPlHd=crawler.currentPlHd;
			break;
		case YsShellCrawler::STATE_ON_VERTEX:
			currentVtHd=crawler.currentEdVtHd[0];
			currentEdge.edVtHd[0]=NULL;
			currentEdge.edVtHd[1]=NULL;
			currentPlHd=NULL;
			break;
		case YsShellCrawler::STATE_ON_EDGE:
			if(crawler.currentEdVtHd[0]!=crawler.currentEdVtHd[1])
			{ // Minor glitch that needs to be fixed.
				currentVtHd=NULL;
				currentEdge.edVtHd[0]=crawler.currentEdVtHd[0];
				currentEdge.edVtHd[1]=crawler.currentEdVtHd[1];
				currentPlHd=NULL;
			}
			else
			{
				currentVtHd=crawler.currentEdVtHd[0];
				currentEdge.edVtHd[0]=NULL;
				currentEdge.edVtHd[1]=NULL;
				currentPlHd=NULL;
			}
			break;
		default:
			printf("%s %d\n",__FUNCTION__,__LINE__);
			printf("%d\n",crawler.currentState);
			return YSERR;
		}



		if(crawler.currentPos==goalPos)
		{
			if(NULL==vtxSequence.Last().vtHd)
			{
				if(0<=vtxSequence.Last().vtxOnEdgeIdx)
				{
					printf("%d %d\n",shl.GetSearchKey(vtxOnEdge[vtxSequence.Last().vtxOnEdgeIdx].edVtHd[0]),shl.GetSearchKey(vtxOnEdge[vtxSequence.Last().vtxOnEdgeIdx].edVtHd[1]));
					printf("Landed between %s %s\n",
					   shl.GetVertexPosition(vtxOnEdge[vtxSequence.Last().vtxOnEdgeIdx].edVtHd[0]).Txt(),
					   shl.GetVertexPosition(vtxOnEdge[vtxSequence.Last().vtxOnEdgeIdx].edVtHd[1]).Txt());
				}
				else
				{
					printf("Nowhere to go.\n");
				}
			}
			if(goalVtHd!=vtxSequence.Last().vtHd)
			{
				printf("Could not reach the goal vertex.\n");
				return YSERR;
			}

			return YSOK;
		}

		// If crawler didn't reach the goal, it might mean the goal is slightly off the polygon.
		// It should be allowed because some polygons may be slightly off the plane.
		if((NULL==goalVtHd || 0==shl.GetNumPolygonUsingVertex(goalVtHd)) && YSTRUE==crawler.reachedDeadEnd)
		{
			// vtxSequence is supposed to be incremented in [case YsShellExt::STATE_IN_POLYGON]
			return YSOK;
		}
	}
	return YSERR;
}
YSRESULT YsShellExt_SewingInfo::MakeInfo(const YsShellExt &shl,YsShellVertexHandle fromVtHd,const YsVec3 &passPnt,YsShellVertexHandle toVtHd)
{
	YsVec3 p[2]={passPnt,shl.GetVertexPosition(toVtHd)};
	YsShellVertexHandle v[2]={NULL,toVtHd};
	return MakeInfoWithVertexHandle(shl,fromVtHd,2,p,v);
}