From 376c4e36934b9ed21caa438c96c7f9dd8bd03d37 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 25 Jun 2024 13:29:23 +0200 Subject: [PATCH] EgtGeomKernel : - In calcPocketing migliorate e semplificate le gestioni dei lati aperti, sia di bordi che di isole, anche con la superficie limite. --- CalcPocketing.cpp | 220 ++++++++++++++++++++-------------------------- 1 file changed, 95 insertions(+), 125 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index fca8c03..2f9c12d 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -389,7 +389,7 @@ GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc) // creo l'ombra del tool nel punto medio PtrOwner pCrvTool( CreateCurveArc()) ; - pCrvTool->Set( ptMid, Z_AX, dDiam) ; + pCrvTool->Set( ptMid, Z_AX, dDiam / 2) ; if ( ! pCrvTool->IsValid()) return false ; @@ -919,109 +919,7 @@ CreateSurfFrIncidence( const ICurveComposite* pCrv, const Vector3d& vtTanS_, con return pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0 ; } - // 1) *** - // La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto - // per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp - // ( tolgo i semi-dischi agli estremi ) - - // 2) *** - // La regione di incidenza deve seguire seguire in tangenza il percorso agli estremi del tratto - // aperto corrente, creo due FlatRegion a rettangolo, orientate come le tangenza dei chiusi che andrò - // a sottrarre alla pSfrInc_tmp - - - // 1) *** - - // Rettangolo all'inizio - Vector3d vtTanS ; pCrv->GetStartDir( vtTanS) ; - Point3d ptS ; pCrv->GetStartPoint( ptS) ; - Vector3d vtOut = vtTanS ; vtOut.Rotate( Z_AX, - 90) ; - PtrOwner pCrvRectSBorder( CreateCurveComposite()) ; - if ( IsNull( pCrvRectSBorder)) - return false ; - pCrvRectSBorder->AddPoint( ptS + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRectSBorder->AddLine( ptS - ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRectSBorder->AddLine( ptS - ( dRad + 500 * EPS_SMALL) * vtOut - vtTanS * ( dRad + 500 * EPS_SMALL)) ; - pCrvRectSBorder->AddLine( ptS + ( dRad + 500 * EPS_SMALL) * vtOut - vtTanS * ( dRad + 500 * EPS_SMALL)) ; - pCrvRectSBorder->Close() ; - PtrOwner pSfrRectStart( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrRectStart) || - ! pSfrRectStart->AddExtLoop( Release( pCrvRectSBorder)) || - ! pSfrRectStart->IsValid()) - return false ; - if ( AreOppositeVectorApprox( pSfrInc->GetNormVersor(), pSfrRectStart->GetNormVersor())) - pSfrRectStart->Invert() ; - - // Rettangolo alla fine - Vector3d vtTanE ; pCrv->GetEndDir( vtTanE) ; - Point3d ptE ; pCrv->GetEndPoint( ptE) ; - vtOut = vtTanE ; vtOut.Rotate( Z_AX, - 90) ; - PtrOwner pCrvRectEBorder( CreateCurveComposite()) ; - if ( IsNull( pCrvRectEBorder)) - return false ; - pCrvRectEBorder->AddPoint( ptE + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRectEBorder->AddLine( ptE - ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRectEBorder->AddLine( ptE - ( dRad + 500 * EPS_SMALL) * vtOut + vtTanE * ( dRad + 500 * EPS_SMALL)) ; - pCrvRectEBorder->AddLine( ptE + ( dRad + 500 * EPS_SMALL) * vtOut + vtTanE * ( dRad + 500 * EPS_SMALL)) ; - pCrvRectEBorder->Close() ; - PtrOwner pSfrRectEnd( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrRectEnd) || - ! pSfrRectEnd->AddExtLoop( Release( pCrvRectEBorder)) || - ! pSfrRectEnd->IsValid()) - return false ; - if ( AreOppositeVectorApprox( pSfrInc->GetNormVersor(), pSfrRectEnd->GetNormVersor())) - pSfrRectEnd->Invert() ; - - // 2) *** - - // Rettangolo all'inizio - Vector3d vtTanCS = vtTanS_ ; - Vector3d vtTanCE = vtTanE_ ; - PtrOwner pCrvRect_TanCLS_Border( CreateCurveComposite()) ; - if ( IsNull( pCrvRect_TanCLS_Border)) - return false ; - pCrvRect_TanCLS_Border->AddPoint( ptS) ; - pCrvRect_TanCLS_Border->AddLine( ptS + ( 1.5 * dRad + 500 * EPS_SMALL) * vtTanCS) ; - vtOut = vtTanCS ; vtOut.Rotate( Z_AX, - 90) ; - pCrvRect_TanCLS_Border->AddLine( ptS + ( 1.5 * dRad + 500 * EPS_SMALL) * vtTanCS + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRect_TanCLS_Border->AddLine( ptS + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRect_TanCLS_Border->Close() ; - PtrOwner pSfrRectCLStart( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrRectCLStart) || - ! pSfrRectCLStart->AddExtLoop( Release( pCrvRect_TanCLS_Border)) || - ! pSfrRectCLStart->IsValid()) - return false ; - if ( AreOppositeVectorApprox( pSfrInc->GetNormVersor(), pSfrRectCLStart->GetNormVersor())) - pSfrRectCLStart->Invert() ; - - // Rettangolo alla fine - PtrOwner pCrvRect_TanCLE_Border( CreateCurveComposite()) ; - if ( IsNull( pCrvRect_TanCLE_Border)) - return false ; - pCrvRect_TanCLE_Border->AddPoint( ptE) ; - pCrvRect_TanCLE_Border->AddLine( ptE + ( 1.5 * dRad + 500 * EPS_SMALL) * vtTanCE) ; - vtOut = vtTanCE ; vtOut.Rotate( Z_AX, 90) ; - pCrvRect_TanCLE_Border->AddLine( ptE + ( 1.5 * dRad + 500 * EPS_SMALL) * vtTanCE + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRect_TanCLE_Border->AddLine( ptE + ( dRad + 500 * EPS_SMALL) * vtOut) ; - pCrvRect_TanCLE_Border->Close() ; - PtrOwner pSfrRectCLEEnd( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrRectCLEEnd) || - ! pSfrRectCLEEnd->AddExtLoop( Release( pCrvRect_TanCLE_Border)) || - ! pSfrRectCLEEnd->IsValid()) - return false ; - if ( AreOppositeVectorApprox( pSfrInc->GetNormVersor(), pSfrRectCLStart->GetNormVersor())) - pSfrRectCLStart->Invert() ; - - // alla superficie di incidenza, sottraggo i due rettangoli ricavati - if ( ! pSfrInc->Subtract( *pSfrRectStart) || - ! pSfrInc->Subtract( *pSfrRectEnd)) - return false ; - - // tolgo ora i rettangoli per le tangenze ai chiusi - pSfrInc->Subtract( *pSfrRectCLStart) ; - pSfrInc->Subtract( *pSfrRectCLEEnd) ; - - return pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0 ; + return ( pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0) ; } //---------------------------------------------------------------------------- @@ -1109,11 +1007,30 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI // inverto se necessario if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor())) pSfrBean->Invert() ; + // 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro - bool bDiscard = ! bIsIsland ; // non trascuro se si tratta di un'isola aperta - for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && bDiscard ; ++ cI) - for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && bDiscard ; ++ cB) - bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) != REGC_INTERS) ; + bool bDiscard = false ; + if ( ! bIsIsland) { // se tratto un loop esterno + for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) + for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) + bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) != REGC_INTERS) ; + } + else if ( bIsAllOpen && bIsIsland) { // se isola aperta + for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) { + for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) { + if ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) == REGC_IN1) { + for ( int l = 1 ; l < pSfrBean->GetLoopCount( cB) ; ++ l) { + PtrOwner pSfrTmp( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrTmp) || ! pSfrTmp->AddExtLoop( pSfrBean->GetLoop( cB, l)) || + ! pSfrTmp->Invert()) + return false ; + + bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrTmp, 0) == REGC_IN1) ; + } + } + } + } + } if ( ! bDiscard) { // 8) aggiorno la regione di incidenza if ( ! pSfrInc->Add( *pSfrBean)) @@ -1121,6 +1038,28 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI } pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; // passo al tratto offsettato successivo } + // 9) creo la regione squadrata da rimuovere alla regione di incidenza + OffsetCurve OffsCrvRect ; + if ( ! OffsCrvRect.Make( vpCrvs[cl], dDiamJ * 0.5, ICurve::OFF_FILLET)) + return false ; + // 10) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti + PtrOwner pOffLongestCrvRect( OffsCrvRect.GetLongerCurve()) ; + while ( ! IsNull( pOffLongestCrvRect)) { + + // 11) creo la regione di incidenza di tale curva ( "Curva a rettangolo") + PtrOwner pSfrRect( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrvRect), dDiamJ * 0.5, true, false)) ; + if ( IsNull( pSfrRect) || ! pSfrRect->IsValid()) + return false ; + // inverto se necessario + if ( AreOppositeVectorApprox( pSfrRect->GetNormVersor(), pSfrInc->GetNormVersor())) + pSfrRect->Invert() ; + + // 12) aggiorno la regione di incidenza + if ( ! pSfrInc->Subtract( *pSfrRect)) + return false ; + + pOffLongestCrvRect.Set( OffsCrvRect.GetLongerCurve()) ; // passo al tratto offsettato successivo + } } } @@ -1129,12 +1068,17 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI // lato aperto al di fuori del volume di svuotatura... Devo controllare di non rovinare delle zone al di fuori di // esso ! if ( PockParams.SfrLimit.IsValid()) { - pSfrInc->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; - if ( ! pSfrInc->Subtract( PockParams.SfrLimit)) + // recupero la superficie limite + PtrOwner pSfrLimit( GetSurfFlatRegion( PockParams.SfrLimit.Clone())) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; + // piccolo Offset per sicurezza + pSfrLimit->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + pSfrInc->Subtract( *pSfrLimit) ; // rimuovo la regione limite + // può capitare che la regione Limite mi crei più Chunk sulla pSfrInc // I chunk da togliere sono tutti quelli che si sono separati dalla pCrvBorder - // NB. Il mio obiettivo è quello di avere un'unica curva con estremi i due tratti aperti estremanti + // NB. Il mio obiettivo è quello di avere un'unica curva con estremi i due tratti chiusi estremanti if ( pSfrInc->GetChunkCount() > 1) { // se ottengo più chunks PtrOwner pNewSfrInc( CreateSurfFlatRegion()) ; if ( IsNull( pNewSfrInc)) @@ -1178,13 +1122,29 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI if ( bIsAllOpen) { // pulisco la curva originale pCrvBorder->Clear() ; - if ( bIsIsland) { // se isola inserisco il loop interno della regione - pCrvNewBorder.Set( ConvertCurveToComposite( pSfrInc->GetLoop( 0, 1))) ; - if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid()) - return false ; - // imposto la curva come tutta aperta ( gira come girava già l'isola) - for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u) - pCrvNewBorder->SetCurveTempProp( u, 1, 0) ; + if ( bIsIsland) { // se isola inserisco il loop interno corretto della regione + for ( int l = 1 ; l < pSfrInc->GetLoopCount( 0) ; ++ l) { + // recupero il Loop + PtrOwner pCrvIntLoop( ConvertCurveToComposite( pSfrInc->GetLoop( 0, l))) ; + if ( IsNull( pCrvIntLoop) || ! pCrvIntLoop->IsValid()) + return false ; + // controllo che sia interno alla curva di bordo corrente ( l'isola aperta) + IntersCurveCurve ICC( *pCrvIntLoop, *pCrvCompo) ; + CRVCVECTOR ccClass ; + if ( ICC.GetCurveClassification( 0, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && + ccClass[0].nClass == CRVC_OUT) { + // il loop interno corretto va impostato come unico e nuovo loop interno della regione + pCrvNewBorder->CopyFrom( pCrvIntLoop) ; + if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid()) + return false ; + // imposto la curva come tutta aperta ( gira come girava già l'isola) + for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u) + pCrvNewBorder->SetCurveTempProp( u, 1, 0) ; + break ; + } + } + } // se bordo esterno inserisco il bordo esterno return pCrvBorder->AddCurve( Release( pCrvNewBorder)) ; @@ -6563,8 +6523,8 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, con //---------------------------------------------------------------------------- bool -CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, int nType, bool bSmooth, - ICRVCOMPOPOVECTOR& vCrvCompoRes) +CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, + int nType, bool bSmooth, ISurfFlatRegion* pSfrLimit, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || @@ -6583,20 +6543,30 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double myParams.bSmooth = bSmooth ; myParams.dAngle = dAngle ; myParams.dSideStep = dStep ; + if ( pSfrLimit != nullptr && pSfrLimit->IsValid()) + myParams.SfrLimit.CopyFrom( pSfrLimit) ; // ------------ gestione dei lati aperti ------------------- - // modifico la supericie in base alle proprietà di lato aperto/chiuso + // creo un sistema di riferimento locale Point3d ptCenter ; pSfr->GetCentroid( ptCenter) ; Vector3d vtN = pSfr->GetNormVersor() ; Frame3d frLoc ; if ( ! frLoc.Set( ptCenter, vtN)) return false ; + // porto la superficie da svuotare in tale sistema PtrOwner pSfrAdj( CloneSurfFlatRegion( pSfr)) ; - if ( IsNull( pSfrAdj) || - ! pSfrAdj->ToLoc( frLoc) || - ! ModifySurfByOpenEdges( pSfrAdj, myParams) || - ! pSfrAdj->ToGlob( frLoc)) + if ( IsNull( pSfrAdj) || ! pSfrAdj->ToLoc( frLoc)) return false ; + // porto la superficie limite ( se valida) in tale sistema + if ( myParams.SfrLimit.IsValid()) + myParams.SfrLimit.ToLoc( frLoc) ; + // modifico la superficie da svuotare estendendo i lati aperti + if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams)) + return false ; + // riporto tutto nel frame originale + pSfrAdj->ToGlob( frLoc) ; + if ( myParams.SfrLimit.IsValid()) + myParams.SfrLimit.ToGlob( frLoc) ; // ------------ calcolo delle curve elementari della superficie ------------------- switch ( nType) {