diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index c68f5ea..b613556 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -735,7 +735,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou //------------------------------------------------------------------------------- ISurfBezier* -GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double dSampleLen) +GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen) { // verifica parametri if ( pCurve1 == nullptr || pCurve2 == nullptr) @@ -762,7 +762,7 @@ GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double d // creo e setto la superficie trimesh PtrOwner pSbz( CreateBasicSurfBezier()) ; - if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen)) + if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines)) return nullptr ; // restituisco la superficie diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 3ba9456..3f9b541 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -6429,6 +6429,14 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp //---------------------------------------------------------------------------- bool SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) +{ + BIPNTVECTOR vSyncLines ; + return CreateSmoothRuledByTwoCurves( pCurve0, pCurve1, dSampleLen, vSyncLines) ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) { // converto in bezier le curve iniziali PtrOwner pCrvEdge1( CurveToBezierCurve( pCurve0, 3, false)) ; @@ -6444,7 +6452,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p // Verifico che la distanza di campionamento sia ammissibile double dSampleDist = Clamp( dSampleLen, 2., 30.) ; // 20.0 sembra un passo di campionamento ideale - // Recupero parametri iniziali double dLen1 ; pCrvEdge1->GetLength( dLen1) ; double dLen2 ; pCrvEdge2->GetLength( dLen2) ; @@ -6457,7 +6464,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p Point3d ptPrev1, ptCurr1 ; pCrvEdge1->GetStartPoint( ptPrev1) ; Point3d ptPrev2, ptCurr2 ; pCrvEdge2->GetStartPoint( ptPrev2) ; Vector3d vtCurr1 = V_NULL, vtCurr2 = V_NULL ; - BIPNTVECTOR vSyncLines ; while ( dLenPrev1 + dSampleDist < dLen1 - EPS_ZERO) { // Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento dLenCurr1 = Clamp( dLenPrev1 + dSampleDist, 0., dLen1) ; @@ -6585,6 +6591,7 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p vGeo.push_back( Release( pLine)) ; vCol.push_back( LIME) ; #endif + vSyncLines.emplace_back( ptCurr1, ptCurr2) ; // --- Analisi degli spigoli all'interno della Quadrangolazione corrente --- // NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)... @@ -6634,6 +6641,9 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p SyncLinePrev = SyncLineNext ; } } + // aggiungo le nuove curve ( non importa che siano in ordine di parametro) + vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ; + vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ; #if SAVEPACEDISO for ( int i = 0 ; i < ssize( vTwistSyncLines) ; ++ i) { PtrOwner pLine( CreateCurveLine()) ; pLine->Set( vTwistSyncLines[i].first, vTwistSyncLines[i].second) ; @@ -6651,6 +6661,8 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ; #endif + + // devo riempire vSyncLines return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ; } diff --git a/SurfBezier.h b/SurfBezier.h index 7db854f..c765695 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -155,6 +155,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool SwapParameters( void) ; bool LimitSurfToTrimmedRegion( void) override ; bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ; + bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/Trimming.cpp b/Trimming.cpp index f5fd22a..7e187f4 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -284,58 +284,6 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) return true ; } -//----------------------------------------------------------------------------- -// Funzione per spezzare una curva compo in diversi tratti in corrispondenza -// di cambi di direzione maggiori della tolleranza angolare passata -static bool -SplitCurveCompoByAngTol( const ICurveComposite* pCC, double dAngTol, ICRVCOMPOPOVECTOR& vCC) -{ - int nCurves = pCC->GetCurveCount() ; - vCC.emplace_back( CreateCurveComposite()) ; - vCC.back()->AddCurve( pCC->GetCurve(0)->Clone()) ; - // Cos della tolleranza angolare massima - double dCosTol = cos( dAngTol * DEGTORAD) ; - - for ( int nC = 0 ; nC < nCurves - 2; ++ nC) { - // Recupero l'angolo tra la fine della curva corrente e l'inizio della successiva - const ICurve* pCrvCurr = pCC->GetCurve( nC) ; - const ICurve* pCrvNext = pCC->GetCurve( nC + 1) ; - Vector3d vtCurrEnd ; pCrvCurr->GetEndDir( vtCurrEnd) ; - Vector3d vtNextStart ; pCrvNext->GetStartDir( vtNextStart) ; - // Calcolo il Coseno tra i due versori - double dCos = vtCurrEnd * vtNextStart ; - // Se dentro alla tolleranza, allora i punti apparterranno alla stessa curva - if ( dCos > dCosTol) { - // Aggiungo la curva - vCC.back()->AddCurve( pCrvNext->Clone()) ; - } - // Se tratto al di fuori della tolleranza, devo definire una nuova curva - else { - vCC.emplace_back( CreateCurveComposite()) ; - vCC.back()->AddCurve( pCrvNext->Clone()) ; - } - } - - // Se curva originale chiusa - if ( pCC->IsClosed() && ssize( vCC) > 1) { - // Se ho più tratti, potrei riunire il primo con l'ultimo - const ICurve* pCrvFirst = pCC->GetCurve( 0) ; - const ICurve* pCrvLast = pCC->GetCurve( nCurves - 1) ; - Vector3d vtFirstStart ; pCrvFirst->GetEndDir( vtFirstStart) ; - Vector3d vtLastEnd ; pCrvLast->GetStartDir( vtLastEnd) ; - // Calcolo il Coseno tra i due versori - double dCos = vtFirstStart * vtLastEnd ; - // Se dentro alla tolleranza, allora i punti appartengono alla stessa curva - if ( dCos > dCosTol) { - // Aggiungo la curva - vCC.back()->AddCurve( Release( vCC.front())) ; - vCC.erase( vCC.begin()) ; - } - } - - return true ; -} - ////----------------------------------------------------------------------------- //// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante //// Patches di curve di Bezier @@ -3959,26 +3907,26 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, #endif // Definisco la superficie di Bezier rigata - PtrOwner pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10))) ; + PtrOwner pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncPoints, 10))) ; if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid()) return false ; - // Recupero i punti di sincronizzazione e li restituisco - ICURVEPOVECTOR vCrv ; - pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ; - vSyncPoints.reserve( vCrv.size()) ; - for ( int i = 0 ; i < ssize( vCrv) ; ++ i) { - if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) { - #if DEBUG_SYNC_POINTS - VT.emplace_back( vCrv[i]->Clone()) ; - VC.emplace_back( LIME) ; - #endif - Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ; - Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ; - if ( ! AreSamePointApprox( ptStart, ptEnd)) - vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; - } - } + //// Recupero i punti di sincronizzazione e li restituisco + // ICURVEPOVECTOR vCrv ; + // pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ; + // vSyncPoints.reserve( vCrv.size()) ; + // for ( int i = 0 ; i < ssize( vCrv) ; ++ i) { + // if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) { + // #if DEBUG_SYNC_POINTS + // VT.emplace_back( vCrv[i]->Clone()) ; + // VC.emplace_back( LIME) ; + // #endif + // Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ; + // Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ; + // if ( ! AreSamePointApprox( ptStart, ptEnd)) + // vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ; + // } + // } #if DEBUG_SYNC_POINTS SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ; @@ -4219,7 +4167,8 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1, // Se non ho punti di controllo forzati if ( vSyncPoints.empty()) { - pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10)) ; + BIPNTVECTOR vSyncLines ; + pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncLines, 10)) ; if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) { LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ; return nullptr ; @@ -4972,38 +4921,44 @@ typedef vector PNTINFOVECTOR ; // Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim // Le curve vengono modificate entro una data tolleranza, in modo che bool -RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol) +RegolarizeBordersLocally( ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol) { #if DEBUG_SMOOTH_CURVATURE VT.clear() ; #endif // prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare - int nUS1 = - 1, nUS2 = -1 ; const Point3d& ptS1 = bpIsoStart.first ; const Point3d& ptS2 = bpIsoEnd.first ; + const Point3d& ptE1 = bpIsoStart.second ; + const Point3d& ptE2 = bpIsoEnd.second ; int nDegU, nDegV, nSpanU, nSpanV ; bool bRat, bTrimmed ; pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ; if ( nDegU != 3) return false ; // individuo quali isocurve sono state indicate come inizio e fine - for ( int i = 0 ; i < nDegU * nSpanU + 1 ; ++i) { - bool bOk = false ; - Point3d pt = pSurfBz->GetControlPoint( i, 0, &bOk) ; - if ( nUS1 == -1 && AreSamePointExact(pt, ptS1)) - nUS1 = i ; - else if ( AreSamePointExact( pt, ptS2)) { - nUS2 = i ; - break ; - } + PtrOwner pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ; + PtrOwner pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ; + double dParS1 = -1 ; double dParS2 = -1 ; + if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2)) + return false ; + double dParE1 = -1 ; double dParE2 = -1 ; + if ( ! pCrv2->GetParamAtPoint( ptE1, dParE1) || ! pCrv2->GetParamAtPoint( ptE2, dParE2)) + return false ; + int nUS1 = int ( dParS1) ; + int nUS2 = int ( dParS2) ; + bool bInverted = false ; + if ( nUS1 > nUS2) { + swap( nUS1, nUS2) ; + swap( dParE1, dParE2) ; + bInverted = true ; } // scorro le isocurve a partire dallo start e dell'end della zona indicata // controllo il twist rispetto alla isocurva precedente - int nMid = ( nUS2 + nUS1) / 2 ; Point3d ptPrevS = ptS1 ; - Point3d ptPrevE = bpIsoStart.second ; + Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ; Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ; Point3d ptBez ; Vector3d vtNPrev ; pSurfBz->GetPointNrmD1D2( nUS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNPrev) ; @@ -5017,7 +4972,7 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier* Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ; vPnt1.push_back( ptSecond2Curr) ; // scorro le isocurve di separazione tra patch - for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) { /////////////////// scorro fino in fondo?? + for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) { // recupero precedente e successivo Point3d ptThird1Curr = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ; Point3d ptThird2Curr = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ; @@ -5036,7 +4991,7 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier* if ( abs( dAng) > 0) { // se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente // allora prendo il penultimo punto della curva corrente, l'ultimo e il secondo della prossima e li sposto lungo la normale della superficie - dDist *= dAng * DEGTORAD ; + dDist *= dAng * DEGTORAD / 2 ; ptThird1Curr += vtNPrev * dDist ; ptCurrS += vtNPrev * dDist ; ptSecond1Next += vtNPrev * dDist ; @@ -5074,13 +5029,33 @@ RegolarizeBordersLocally( const ICurve* pCrv1, const ICurve* pCrv2, ISurfBezier* pCC2->AddCurve( Release( cb2)) ; } + // controllo di essere rimasto in tolleranza + PtrOwner pCrvOrig1( pCrv1->CopyParamRange( nUS1, dParE1)) ; + PtrOwner pCrvOrig2( pCrv2->CopyParamRange( nUS2, dParE2)) ; + double dErr = 0 ; + CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ; + if ( dErr > dTol) + return false ; + CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ; + if ( dErr > dTol) + return false ; - //PtrOwner pSB( CreateSurfBezier()) ; - //pSB->CreateSmoothRuledByTwoCurves( pCrv1, pCrv2, 10) ; + // controllo di non aver creato dei cambi di concavità + // se ne trovo allora ruoto i terzetti attorno alla nuova isocurva + ////////////////// DA IMPLEMENTARE (prendendo dalla versione precedente della Regolarize) + + // aggiorno i punti di controllo della superficie di bezier + for ( int i = 0 ; i < ssize( vPnt0) ; ++i) { + pSurfBz->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ; + pSurfBz->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ; + } #if DEBUG_SMOOTH_CURVATURE VT.push_back( Release(pCC1)) ; VT.push_back( Release(pCC2)) ; - SaveGeoObj( VT, "D:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ; + VT.push_back( Release(pCrv1)) ; + VT.push_back( Release(pCrv2)) ; + VT.push_back(pSurfBz->Clone()); + SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ; #endif return true ;