diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index d752710..3f792e7 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -256,4 +256,5 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters) // passo alla successiva ++ j ; } + return true ; } \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c154435..d2cd281 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -36,6 +36,7 @@ #include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Include/EGkCurveComposite.h" #include +#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -1620,15 +1621,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const const ICurve* pCrv0 = pCC->GetCurve( 0) ; PolyLine pl ; Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ; - DistPointSurfTm distPtStm0( pt3D, *GetAuxSurf()) ; - // aggiungo il primo punto - int nTriaIndex ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; - // passo anche i riferimenti del prossimo punto Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; - DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ; - int nTriaIndexNext = -1 ; - distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ; - if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, pt3DEnd, nTriaIndexNext)) + if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd)) return nullptr ; //if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D)) { // Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; @@ -1641,17 +1635,13 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const //} pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi - int nTriaIndexPrev = nTriaIndex ; for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; Point3d pt3DPrev = pt3D ; pCrv->GetEndPoint( pt3D) ; - DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ; - distPtStm.GetMinDistTriaIndex( nTriaIndex) ; - if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D, 5, pt3DPrev, nTriaIndexPrev)) + if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev)) return nullptr ; pl.AddUPoint( i, pt2D) ; - nTriaIndexPrev = nTriaIndex ; } PtrOwner pCC2D ( CreateCurveComposite()) ; pCC2D->FromPolyLine( pl) ; @@ -1660,8 +1650,12 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const //---------------------------------------------------------------------------- bool -SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler) +SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler) { + //debug + vpCC3D.emplace_back( pCrvCompo->Clone()) ; + //debug + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando double dCrvLen ; if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) @@ -1717,6 +1711,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim + ////debug + //PtrOwner pSFRTrim ( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSFRTrim), "D:\\Temp\\inters\\original_trim.nge", GDB_SV_BIN) ; + ////debug + PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; @@ -1731,6 +1730,16 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //////i tagli multipli//////////////////////////////////////////////// IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; + ////debug + //vector vGeoObj3 ; + //for ( int i = 0 ; i < int(m_vCCEdge.size()); ++i ) { + // if ( ! m_vCCEdge[i]->IsValid()) + // continue ; + // vGeoObj3.emplace_back(static_cast( m_vCCEdge[i]->Clone())) ; + //} + //SaveGeoObj( vGeoObj3, "D:\\Temp\\inters\\Edge3D.nge") ; + ////debug + // concateno le curve 3d ChainCurves chainC ; double dToler = EPS_SMALL ; @@ -1750,6 +1759,9 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; + //debug + ICRVCOMPOPOVECTOR vpCC3D ; + //debug while ( chainC.GetChainFromNear( ptNear, false, vId)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; @@ -1798,23 +1810,53 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) else if ( icc3.GetIntersCount() != 0) icc3.GetIntCrvCrvInfo( 0, iccInfo) ; + if ( i == 48 ) { + //debug + vector vGeoObj5 ; + vGeoObj5.emplace_back(static_cast( pLine->Clone())) ; + vGeoObj5.emplace_back(static_cast( m_vCCEdge[1]->GetCurve(12)->Clone())) ; + SaveGeoObj( vGeoObj5, "D:\\Temp\\inters\\inters3D_error.nge") ; + //debug + } + + ICurveLine* pCLPart1 ( CreateCurveLine()) ; // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root Vector3d vtDir ; pLine->GetStartDir( vtDir) ; Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; - pCLPart1->Set( ptStart, ptBeforeTheEdge) ; - pCrvCompo->AddCurve( pCLPart1, true, dToler) ; - bAdded = false ; - AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; - pCrvCompo->Clear() ; - // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato - // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject - //ICurveLine* pCLPart2 ( CreateCurveLine()) ; - Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; - //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; - //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; - ptNear = ptBeyondTheEdge ; - bPrevLineThroughEdge = true ; + // se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova + // a partire dall'intersezione + if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + pCLPart1->Set( ptStart, ptBeforeTheEdge) ; + pCrvCompo->AddCurve( pCLPart1, true, dToler) ; + bAdded = false ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; + pCrvCompo->Clear() ; + // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato + // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject + //ICurveLine* pCLPart2 ( CreateCurveLine()) ; + Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; + //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; + //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; + ptNear = ptBeyondTheEdge ; + bPrevLineThroughEdge = true ; + --i ; + } + else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) { + // se l'intersezione era all'inizio allora aggiungo e basta + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + // se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova + // indipendente dall'interesezione + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; + pCrvCompo->Clear() ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } } } // sennò procedo normalmente aggiungendo il punto @@ -1824,36 +1866,75 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bPrevLineThroughEdge = false ; } } - AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; } + ////debug + //vector vGeoObj4 ; + //for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) + // vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; + //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; + ////debug + + //debug + vector vGeoObj ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + //debug + if ( int( vpCCOpen.size()) != 0) { - // devo verificare se devo giuntare la prima curva aperta con l'ultima + //// devo verificare se devo giuntare la prima curva aperta con l'ultima + //Point3d ptStartOpen, ptEndOpen ; + //vpCCOpen.front()->GetStartPoint( ptStartOpen) ; + //vpCCOpen.back()->GetEndPoint( ptEndOpen) ; + //if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { + // vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; + // Release( vpCCOpen[0]) ; + // vpCCOpen.erase( vpCCOpen.begin()) ; + //} + + // devo controllare se devo giuntare queste curve aperte tra loro Point3d ptStartOpen, ptEndOpen ; - vpCCOpen.front()->GetStartPoint( ptStartOpen) ; - vpCCOpen.back()->GetEndPoint( ptEndOpen) ; - if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { - vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; - Release( vpCCOpen[0]) ; - vpCCOpen.erase( vpCCOpen.begin()) ; + for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) { + // controllo se la fine di questa curva coincide con lo start di un'altra + } } + ////debug + //vector vGeoObj2 ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + ////debug //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie // recupero la regione attuale - unordered_map mInters ; - // costruisco la mappa delle intersezioni + + PtrOwner pNewTrim( CreateBasicSurfFlatRegion()) ; if ( m_bTrimmed) pNewTrim.Set( GetTrimRegion()->Clone()) ; else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; + ////debug + //PtrOwner pSrfCopy( pNewTrim->Clone()) ; + //SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; + ////debug + + // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region + unordered_map mInters ; + //chunk for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + // loop for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + bool bHasSomeIntersection = false ; + // trim for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; // prima curva è il loop, seconda curva è il loop @@ -1866,8 +1947,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vICC.emplace_back( iccInfo) ; } mInters.insert( pair( TRINT(c,l,t), vICC)) ; + bHasSomeIntersection = true ; } } + // se un trim non fa intersezioni allora c'è qualcosa di sbagliato + if ( ! bHasSomeIntersection) + return false ; } } @@ -2102,6 +2187,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW + ////debug + //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + ////debug + // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { if ( ! SetTrimRegion( *pSFR, false) || ! m_pTrimReg->IsValid()) @@ -2112,6 +2202,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } + ////debug + //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + ////debug + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2122,20 +2217,29 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bool SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const { - return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1), -1) ; + return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1)) ; } //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, int nTPrev) const +SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext) const { // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche const ISurfTriMesh* pSurfTm = GetAuxSurf() ; + int nTriaIndex = nT ; + if ( nT == -1) { + DistPointSurfTm distPtStm0( ptI, *pSurfTm) ; + distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; + } + // aggiungo il primo punto // devo subito capire se sono in un polo o no // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto bool bIsPole = false ; int nInters = 0 ; INTVECTOR vInters ; + // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles + if ( int( m_vbPole.size()) == 0) + return false ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3]) { for ( int c = 0 ; c < 4 ; ++c) { if ( ! m_vCCEdge[c]->IsValid()) { @@ -2169,17 +2273,23 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // return false ; // visto che sono in un polo devo verificare di aver ricevuto il triangolo giusto - // mi sposto verso il punto successivo o precedente e ricalcolo il triangolo di appartenenza + // se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza + if ( AreSamePointExact( ptIPrevOrNext, Point3d(-1,-1,-1))){ // controllo che non sia quello definito di default + DistPointSurfTm dPtStm( ptIPrevOrNext, *pSurfTm) ; + double dDist = INFINITO ; dPtStm.GetDist( dDist) ; + if ( dDist > 0.1) + return false ; + } Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ; // ricalcolo il triangolo di appartenenza DistPointSurfTm dPtStm( ptI2, *pSurfTm) ; - dPtStm.GetMinDistTriaIndex( nT) ; + dPtStm.GetMinDistTriaIndex( nTriaIndex) ; } } // recupero i dati dei vertici del triangolo che fa intersezione int nVert[3] ; - pSurfTm->GetTriangle( nT, nVert) ; + pSurfTm->GetTriangle( nTriaIndex, nVert) ; PNTVECTOR vPtPa(3) ; pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; @@ -2211,7 +2321,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in vtDir.Normalize() ; // se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice // siano da correggere per periodicità - if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.95 ) { + if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) { // trovo se dei punti del triangolo sono sul bordo dello spazio parametrico BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { @@ -2250,7 +2360,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } - else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.95) { + else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) { BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { if ( ! m_vCCEdge[0]->IsValid()) { @@ -2395,64 +2505,89 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const +SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const { // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D // ripeto cercando di avvicinarmi il più possibile // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; - int nTriaIndex ; dptSurfTm.GetMinDistTriaIndex( nTriaIndex) ; Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; - if ( ! UnprojectPointFromStm( nTriaIndex, ptI, ptParam)) + if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev)) return false ; Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto double dDistNew = Dist( pt3D, ptBez) ; - double dDistPre = dDistNew ; + double dDistPre ; + double dDist0, dDist1; int nCount = 0 ; double dh = EPS_SMALL ; // metodo di newton in più dimensioni // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. - while ( dDistNew > EPS_SMALL && nCount < 100) { - dDistPre = dDistNew ; - Point3d ptIBzNew1 ; - GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; - dDistNew = Dist( pt3D, ptIBzNew1) ; - double dfdU = ( dDistNew - dDistPre) / dh ; - Point3d ptIBzNew2 ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; - dDistNew = Dist( pt3D, ptIBzNew2) ; - double dfdV = ( dDistNew - dDistPre) / dh ; - //// opzione 0 - ////scelgo h1 e h2 separatamente e in modo da annullare f(x) - //// opzione 1 - //// valore fisso - //double dr = EPS_SMALL ; - //if ( dDistPre > 1) - // dr = 1 ; - //else if ( dDistPre > 0.1) - // dr = 0.1 ; - //else if ( dDistPre > 0.01) - // dr = 0.01 ; - //// opzione 2 - //// valore direttamente vincolato - //double dr = dDistPre ; - //// opzione 3 - //// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve - //double dh1 = Dist( ptIBz, ptIBzNew1) ; - //double dh2 = Dist( ptIBz, ptIBzNew2) ; - // potrei valutare il nuovo spostamento in base all'ultima variazione di dDist - // potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico) - // mi avvicino cercando di annullare la distanza in un colpo solo - double dr = - dDistPre / ( dfdU + dfdV) ; - GetPointD1D2(( ptParam.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptParam.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + bool bRetry = false ; + double dApproach = 0.01 ; + bool bDesperate = false ; + double dAng = 1 ; + double dr = 5 ; + double dfdU, dfdV ; + while ( dDistNew > 3 * EPS_SMALL && nCount < 100) { + if ( ! bRetry) { + dDistPre = dDistNew ; + // derivata in U + Point3d ptIBzNew1 ; + GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + dDist0 = Dist( pt3D, ptIBzNew1) ; + dfdU = ( dDist0 - dDistPre) / dh ; + // derivata in V + Point3d ptIBzNew2 ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + dDist1 = Dist( pt3D, ptIBzNew2) ; + dfdV = ( dDist1 - dDistPre) / dh ; + } + // calcolo le nuove coordinate + Vector3d vtDir ; + double dASum = abs(dfdU) + abs(dfdV) ; + double dSSum = sqrt( pow(dfdU,2) + pow( dfdV,2)) ; + vtDir.Set( - dfdU, - dfdV, 0) ; + if ( ! vtDir.Normalize() ) + vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ; + dr = dDistPre / dASum ; + // in modalità Retry riduco lo spostamento + vtDir *= dr * ( bRetry ? 0.1 : 0.5) ; + if ( bDesperate) { + // in depserate mode riduco lo spostamento e comincio a cambiare progressivamente la direzione oscillando tra destra e sinistra della direzione "naturale" + vtDir *= 0.5 ; + dAng *= -1.25 ; + // riduco ulteriormente lo spostamento dopo qualche giro in desperate mode + if ( abs( dAng) > 5) + vtDir *= 0.5 ; + vtDir.Rotate( Z_AX, dAng) ; + } + ptParam += vtDir ; + // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; dDistNew = Dist( pt3D, ptBez) ; + dApproach = dDistPre - dDistNew ; + // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode + if ( dApproach < EPS_ZERO) { + if ( bRetry) + bDesperate = true ; // entro in desperate mode + ptParam -= vtDir ; + bRetry = true ; + // se ho già fatto 9 giri in desperate mode allora esco + if ( abs( dAng) > 8) + break ; + } + else { + bRetry = false ; + bDesperate = false ; + dAng = 1 ; + } ++nCount ; } - return nCount != 99 ; + return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } //---------------------------------------------------------------------------- @@ -2477,8 +2612,8 @@ SurfBezier::CalcPoles( void) if ( ! bPole0 && ! bPole1) break ; } - m_vbPole[1] = bPole0 ; - m_vbPole[3] = bPole1 ; + m_vbPole[1] = bPole0 ; // u = 0 corrisponde all'edge 1 + m_vbPole[3] = bPole1 ; // u = 1 corrisponde all'edge 3 // controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti Point3d ptV0, ptV1 ; Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ; @@ -2492,8 +2627,8 @@ SurfBezier::CalcPoles( void) if ( ! bPole0 && ! bPole1) break ; } - m_vbPole[0] = bPole0 ; - m_vbPole[2] = bPole1 ; + m_vbPole[0] = bPole1 ; // v = 1 corrisponde all'edge 0 + m_vbPole[2] = bPole0 ; // v = 0 corrisponde all'edge 2 return true ; } diff --git a/SurfBezier.h b/SurfBezier.h index be2d6ff..724cb0f 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -114,8 +114,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetLeaves( std::vector>& vLeaves) const override ; bool GetTriangles2D( std::vector>& vTria2D) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; - bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, int nTPrev = -1) const override ; // a nIL si può passare 5 come valore di default - bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const override ; + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev) const override ; // a nIL si può passare 5 come valore di default + bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const override ; ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; @@ -166,7 +166,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; double GetCurveOnUApproxLen( double dV) const ; double GetCurveOnVApproxLen( double dU) const ; - bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL) ; + bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler = EPS_SMALL) ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto diff --git a/Tree.cpp b/Tree.cpp index 2bc1786..8b56faf 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3616,7 +3616,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; @@ -3630,7 +3631,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; @@ -3644,7 +3646,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ;