EgtGeomKernel :

- In calcPocketing migliorate e semplificate le gestioni dei lati aperti, sia di bordi che di isole, anche con la superficie limite.
This commit is contained in:
Riccardo Elitropi
2024-06-25 13:29:23 +02:00
parent 88bf84cca1
commit 376c4e3693
+95 -125
View File
@@ -389,7 +389,7 @@ GetCoeffLinArc( const ICurveArc* pArc, double dDiam, double& dSubArc)
// creo l'ombra del tool nel punto medio
PtrOwner<ICurveArc> 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<ICurveComposite> 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<ISurfFlatRegion> 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<ICurveComposite> 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<ISurfFlatRegion> 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<ICurveComposite> 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<ISurfFlatRegion> 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<ICurveComposite> 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<ISurfFlatRegion> 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<ISurfFlatRegion> 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<ICurve> pOffLongestCrvRect( OffsCrvRect.GetLongerCurve()) ;
while ( ! IsNull( pOffLongestCrvRect)) {
// 11) creo la regione di incidenza di tale curva ( "Curva a rettangolo")
PtrOwner<ISurfFlatRegion> 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<ISurfFlatRegion> 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<ISurfFlatRegion> 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<ICurveComposite> 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<ISurfFlatRegion> 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) {