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); }
/* 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); } } } }
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; }
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; }
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; }
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; }
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_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_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_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::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); }
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); }
YSRESULT YsShellExt_SewingInfo::CrawlOneSegment( YsShellVertexHandle ¤tVtHd, YsShell::Edge ¤tEdge, YsShellPolygonHandle ¤tPlHd, YsVec3 ¤tPos, 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; }