EgtmachKernel :

- primo codice per ricavare Volume di Pocketing.
This commit is contained in:
Riccardo Elitropi
2023-11-14 13:26:09 +01:00
parent cc50f573bc
commit c89683cc0e
2 changed files with 382 additions and 23 deletions
+371 -21
View File
@@ -1140,9 +1140,9 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
if ( ! pCurve->GetExtrusion( vtExtr) || vtExtr.IsSmall())
pCurve->SetExtrusion( Z_AX) ;
// corenza con vtTool
if ( ! m_vtTool.IsValid())
m_vtTool = vtExtr ;
else if ( AreSameVectorApprox( vtExtr, m_vtTool))
if ( ! m_vtNormal.IsValid())
m_vtNormal = vtExtr ;
else if ( ! AreSameVectorApprox( vtExtr, m_vtNormal))
return false ;
// verifico sia piana e se necessario la appiattisco
PtrOwner<ICurve> pFlatCrv( FlattenCurve( *pCurve, 50 * EPS_SMALL, 50 * EPS_ANG_SMALL, FLTCRV_USE_EXTR)) ;
@@ -1177,9 +1177,9 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
if ( ! pCrv->GetExtrusion( vtExtr) || vtExtr.IsSmall())
pCrv->SetExtrusion( Z_AX) ;
// corenza con vtTool
if ( ! m_vtTool.IsValid())
m_vtTool = vtExtr ;
else if ( AreSameVectorApprox( vtExtr, m_vtTool))
if ( ! m_vtNormal.IsValid())
m_vtNormal = vtExtr ;
else if ( ! AreSameVectorApprox( vtExtr, m_vtNormal))
return false ;
// tutte le curve sono chiuse
ResetCurveAllTempProp( pCrv) ;
@@ -1202,14 +1202,16 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
int nFacet = (( Id.nSub == SEL_SUB_ALL) ? 0 : Id.nSub) ;
// recupero la normale esterna della faccia
Vector3d vtN ;
if ( ! pSurf->GetFacetNormal( nFacet, vtN))
if ( ! pStm->GetFacetNormal( nFacet, vtN))
return false ;
if ( ! m_vtTool.IsValid())
m_vtTool = vtN ;
else if ( AreSameVectorApprox( vtN, m_vtTool))
if ( ! m_vtNormal.IsValid())
m_vtNormal = vtN ;
else if ( ! AreSameVectorApprox( vtN, m_vtNormal))
return false ;
// inverto per definire il volume di pocketing
pStm->Invert() ;
// aggiungo la Trimesh
if ( ! pStmTmp->Add( *pSurf))
if ( ! pStmTmp->Add( *pStm))
return false ;
return true ;
}
@@ -1225,16 +1227,16 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
// porto in globale
pSfr->ToGlob( frGlob) ;
// recupero la normale della regione
Vector3d vtN = pReg->GetNormVersor() ;
Vector3d vtN = pSfr->GetNormVersor() ;
if ( vtN.IsSmall())
return false ;
if ( ! m_vtTool.IsValid())
m_vtTool = vtN ;
else if ( AreSameVectorApprox( vtN, m_vtTool))
if ( ! m_vtNormal.IsValid())
m_vtNormal = vtN ;
else if ( ! AreSameVectorApprox( vtN, m_vtNormal))
return false ;
// determino intervallo di chunk
int nCstart = 0 ;
int nCend = pReg->GetChunkCount() ;
int nCend = pSfr->GetChunkCount() ;
if ( Id.nSub != SEL_SUB_ALL) {
nCstart = Id.nSub ;
nCend = nCstart + 1 ;
@@ -1244,8 +1246,8 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
// creo vettore delle curve
CICURVEPVECTOR vCrv ;
// recupero i contorni del chunk
for ( int nL = 0 ; nL < pReg->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pReg->GetLoop( nC, nL))) ;
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ;
if ( IsNull( pCrvLoop))
return false ;
// unisco le eventuali parti allineate
@@ -1258,7 +1260,7 @@ Pocketing::GetCurves( SelData Id, ICURVEPLIST& lstPC, ISurfTriMesh* pStmTmp)
vCrv.emplace_back( Release( pCrvLoop)) ;
}
// creo la TriMesh associata ( tutti i lati sono chiusi)
PtrOwner<ISurfTriMesh> pStm_extr( GetSurfTriMeshByRegionExtrusion( vCrv, vtN)) ;
PtrOwner<ISurfTriMesh> pStm_extr( GetSurfTriMeshByRegionExtrusion( vCrv, 3000 * vtN)) ;
if ( IsNull( pStm_extr) || ! pStm_extr->IsValid())
return false ;
pStmTmp->Add( *pStm_extr) ;
@@ -1450,13 +1452,361 @@ Pocketing::Chain( int nGrpDestId)
vCrvCompo.emplace_back( Release( pCrvCompo)) ;
}
// creazione della TriMesh di pocketing
// ricavo un punto interno per il finito corrente
Point3d ptInside ;
if ( pStm_tmp->GetTriangleCount() > 0)
pStm_tmp->GetCentroid( ptInside) ;
else if ( int( vCrvCompo.size() > 0))
vCrvCompo[0]->GetCentroid( ptInside) ;
else
return false ;
// creazione della TriMesh di pocketing
if ( ! CreateStmForIntersection( pStm_tmp, vCrvCompo))
return false ;
// intersezione della Trimesh con il finito -> rivavo il volume di svuotatura
if ( ! SetPocketingVolume( ptInside, pStm_tmp))
return false ;
// QUIIIIIIIIIIIIIII
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::CreateStmForIntersection( ISurfTriMesh* pStm, ICRVCOMPOPOVECTOR& vCrvCompo)
{
// se non ho entità esco
if ( int( vCrvCompo.size()) == 0)
return true ;
// creo un frame centrato sulla prima curva con Z orientata come m_vtTool
Point3d ptOrig ;
if ( ! vCrvCompo[0]->GetCentroid( ptOrig))
if ( ! vCrvCompo[0]->GetStartPoint( ptOrig))
return false ;
Frame3d frHeight ; frHeight.Set( ptOrig, m_vtNormal) ;
if ( ! frHeight.IsValid())
return false ;
struct CurveQuotes {
int nCrvInd ;
double dQuote ;
} ;
// scorro le curve e ricavo le quote
vector<CurveQuotes> vdCrvQuotes ;
for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) {
vCrvCompo[i]->ToLoc( frHeight) ; // porto in locale
Point3d ptOnCurve ;
if ( ! vCrvCompo[0]->GetCentroid( ptOnCurve))
if ( ! vCrvCompo[0]->GetStartPoint( ptOnCurve))
return false ;
CurveQuotes CrvQt ;
CrvQt.nCrvInd = i ;
CrvQt.dQuote = ptOnCurve.z ;
vdCrvQuotes.push_back( CrvQt) ;
vCrvCompo[i]->ToGlob( frHeight) ; // porto in globale
}
// ordino le quote
sort( vdCrvQuotes.begin(), vdCrvQuotes.end(), []( CurveQuotes &CrvQt0, CurveQuotes &CrvQt1) {
return CrvQt0.dQuote < CrvQt0.dQuote ; }) ;
// creo una FlatRegion con le curve alla stessa quota
ISURFFRPOVECTOR vSfrByQuotes ;
int nInd = 0 ;
while( nInd < int( vdCrvQuotes.size())) {
// regione tempoeranea con la curva attuale
SurfFlatRegionByContours sfrBC ;
sfrBC.AddCurve( vCrvCompo[vdCrvQuotes[nInd].nCrvInd]) ;
++ nInd ;
for ( int j = nInd ; j < int( vdCrvQuotes.size()) ; ++ j) {
nInd = j ;
if ( abs( vdCrvQuotes[j].dQuote - vdCrvQuotes[nInd].dQuote) > EPS_SMALL)
break ;
// se curva successiva alla stessa quota -> aggiungo alla regione
sfrBC.AddCurve( vCrvCompo[vdCrvQuotes[j].nCrvInd]) ;
}
// creo la regione
PtrOwner<ISurfFlatRegion> pSfrCurr( sfrBC.GetSurf()) ;
if ( IsNull( pSfrCurr) || ! pSfrCurr->IsValid())
return false ;
// inverto se necessario
if ( AreOppositeVectorApprox( m_vtNormal, pSfrCurr->GetNormVersor()))
pSfrCurr->Invert() ;
// aggiungo al vettore
vSfrByQuotes.emplace_back( Release( pSfrCurr)) ;
}
// devo allargare i lati aperti della curva esterna, così la superficie si adatterà al finito mediante l'intersezione
for ( int s = 0 ; s < int( vSfrByQuotes.size()) ; ++ s) {
// per ogni superficie ricavo il loop esterno e le sue isole
for ( int c = 0 ; c < vSfrByQuotes[s]->GetChunkCount() ; ++ c) {
// creo il vettore contenente il Loop esterno esteso e le isole
CICURVEPVECTOR vCrv ;
// loop esterno
PtrOwner<ICurveComposite> pCrvLoopExt( ConvertCurveToComposite( vSfrByQuotes[s]->GetLoop( c, 0))) ;
if ( IsNull( pCrvLoopExt) || ! pCrvLoopExt->IsValid())
return false ;
// allargo il loop esterno presso i chiusi
if ( ! GetExtendedLoopToFitStmVolume( pCrvLoopExt))
return false ;
// inserisco la curva nel vettore
vCrv.emplace_back( Release( pCrvLoopExt)) ;
// inserisco le isole
for ( int l = 1 ; l < vSfrByQuotes[s]->GetLoopCount( c) ; ++ l)
vCrv.emplace_back( vSfrByQuotes[s]->GetLoop( c, l)) ;
// creo la TriMesh per l'intersezione con il finito
PtrOwner<ISurfTriMesh> pStmTmp( GetSurfTriMeshByRegionExtrusion( vCrv, 3000 * m_vtNormal)) ;
if ( IsNull( pStmTmp) || ! pStmTmp->IsValid())
return false ;
// aggiungo questa regione a quella passata come parametro alla funzione
pStm->Add( *pStmTmp) ;
}
}
m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStm->Clone()) ;
// intersezione con il finito
return true ;
}
//----------------------------------------------------------------------------
bool
Pocketing::GetExtendedLoopToFitStmVolume( ICurveComposite* pCrvLoop)
{
// controllo del parametro
if ( pCrvLoop == nullptr || ! pCrvLoop->IsValid())
return false ;
// ricavo i parametri della curva
double dThick ; pCrvLoop->GetThickness( dThick) ;
int nTmpProp0 = pCrvLoop->GetTempProp() ;
int nTmpProp1 = pCrvLoop->GetTempProp( 1) ;
// ricavo i tratti omogenei ( campio il punto iniziale della curva nel punto medio del chiuso più lungo se presente)
ICURVEPOVECTOR vCrvOpen, vCrvClose ;
if ( ! GetHomogeneousParts( pCrvLoop, vCrvOpen, vCrvClose, true))
return false ;
// se curva tutta chiusa -> non devo estendere
if ( int( vCrvOpen.size()) == 0)
return true ;
// se curva tutta aperta -> Offset ed esco
else if ( int( vCrvClose.size()) == 0) {
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pCrvLoop, 3000, ICurve::OFF_EXTEND)) {
m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ;
return false ;
}
pCrvLoop->CopyFrom( OffsCrv.GetLongerCurve()) ;
return pCrvLoop->IsClosed() && pCrvLoop->IsValid() ;
}
// scorro i tratti chusi ( se presenti sono almeno due)
for ( int cl = 0 ; cl < int( vCrvClose.size()) - 1 ; ++ cl) {
// linea di estensione sulla parte finale
Point3d ptSL1 ; vCrvClose[cl]->GetEndPoint( ptSL1) ;
Vector3d vtSL1 ; vCrvClose[cl]->GetEndDir( vtSL1) ;
PtrOwner<ICurveLine> pLineS( CreateCurveLine()) ;
if ( IsNull( pLineS) || pLineS->SetPVL( ptSL1, vtSL1, 30000))
return false ;
// linea di estensione sulla parte finale
Point3d ptSL2 ; vCrvClose[cl+1]->GetStartPoint( ptSL2) ;
Vector3d vtSL2 ; vCrvClose[cl+1]->GetStartDir( vtSL2) ; vtSL2.Invert() ;
PtrOwner<ICurveLine> pLineE( CreateCurveLine()) ;
if ( IsNull( pLineE) || pLineE->SetPVL( ptSL2, vtSL2, 30000))
return false ;
// se le linee di intersecano
IntersCurveCurve IntCC( *pLineE, *pLineS) ;
if ( IntCC.GetIntersCount() == 1) {
// ricavo il punto di intersezione
IntCrvCrvInfo aInfo ;
if ( ! IntCC.GetIntCrvCrvInfo( 0, aInfo))
return false ;
Point3d ptInters( aInfo.IciA[0].ptI) ;
// modifico la curva inzile, raccordandola linearmente al punto di intersezione
double dUS, dUE ;
pCrvLoop->GetParamAtPoint( ptSL1, dUS) ;
pCrvLoop->GetParamAtPoint( ptSL2, dUE) ;
// tratto precedente
PtrOwner<ICurveComposite> pCrvPrec( CloneCurveComposite( pCrvLoop)) ;
if ( IsNull( pCrvPrec) || pCrvPrec->TrimEndAtParam( dUS))
return false ;
// tratto successivo
PtrOwner<ICurveComposite> pCrvSucc( CloneCurveComposite( pCrvLoop)) ;
if ( IsNull( pCrvSucc) || pCrvSucc->TrimStartAtParam( dUE))
return false ;
pCrvLoop->Clear() ;
if ( ! pCrvLoop->AddCurve( Release( pCrvPrec)) ||
! pCrvLoop->AddLine( ptInters) ||
! pCrvLoop->AddLine( ptSL2) ||
! pCrvLoop->AddCurve( Release( pCrvSucc)))
return false ;
}
// se invece non ci sono intersezioni tra le linee
else if ( IntCC.GetIntersCount() == 0) {
// estendo il tratto aperto con un Offset
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( vCrvOpen[cl], 300, ICurve::OFF_EXTEND)) {
m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ;
return false ;
}
PtrOwner<ICurve> pCrvOffs( OffsCrv.GetLongerCurve()) ;
if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid())
return false ;
// estendo l'inizio e la fine
if ( ! pCrvOffs->ExtendStartByLen( 30000) ||
! pCrvOffs->ExtendEndByLen( 30000))
return false ;
// intersecon questa curva con le rette
IntersCurveCurve IntCC_S( *pLineS, *pCrvOffs) ;
IntersCurveCurve IntCC_E( *pLineE, *pCrvOffs) ;
Point3d ptInters_S, ptInters_E ;
if ( IntCC_S.GetIntersCount() == 1) {
IntCrvCrvInfo aInfoS ;
if ( ! IntCC_S.GetIntCrvCrvInfo( 0, aInfoS))
return false ;
ptInters_S = aInfoS.IciA[0].ptI ;
}
else
return false ;
if ( IntCC_E.GetCrossIntersCount() == 1) {
IntCrvCrvInfo aInfoE ;
if ( ! IntCC_E.GetIntCrvCrvInfo( 0, aInfoE))
return false ;
ptInters_E = aInfoE.IciA[0].ptI ;
}
else
return false ;
// trimmo la curva Offsettata nei punti di intersezione
double dUS, dUE ;
pCrvOffs->GetParamAtPoint( ptInters_S, dUS) ;
pCrvOffs->GetParamAtPoint( ptInters_E, dUE) ;
if ( ! pCrvOffs->TrimStartEndAtParam( dUS, dUE))
return false ;
// modifico la curva inzile, raccordandola linearmente al trim dell'Offset
pCrvLoop->GetParamAtPoint( ptSL1, dUS) ;
pCrvLoop->GetParamAtPoint( ptSL2, dUE) ;
// tratto precedente
PtrOwner<ICurveComposite> pCrvPrec( CloneCurveComposite( pCrvLoop)) ;
if ( IsNull( pCrvPrec) || pCrvPrec->TrimEndAtParam( dUS))
return false ;
// tratto successivo
PtrOwner<ICurveComposite> pCrvSucc( CloneCurveComposite( pCrvLoop)) ;
if ( IsNull( pCrvSucc) || pCrvSucc->TrimStartAtParam( dUE))
return false ;
pCrvLoop->Clear() ;
if ( ! pCrvLoop->AddCurve( Release( pCrvPrec)) ||
! pCrvLoop->AddLine( ptInters_S) ||
! pCrvLoop->AddCurve( Release( pCrvOffs)) ||
! pCrvLoop->AddLine( ptInters_E) ||
! pCrvLoop->AddCurve( Release( pCrvSucc)))
return false ;
}
else // non definito
return false ;
}
return pCrvLoop->IsClosed() && pCrvLoop->IsValid() ;
}
//----------------------------------------------------------------------------
bool
Pocketing::SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm)
{
// controllo parametro
if ( pStm == nullptr || ! pStm->IsValid())
return false ;
// controllo MachManager e database geometrico
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
return false ;
// TriMesh del finito
PtrOwner<ISurfTriMesh> pStmCurrRawPart( CreateSurfTriMesh()) ;
if ( IsNull( pStmCurrRawPart))
return false ;
// flag per RawPart trovata
bool bFound = false ;
// considero tutte le superfici dei pezzi nei grezzi attivi della fase
int nRawId = m_pMchMgr->GetFirstRawPart() ;
while ( nRawId != GDB_ID_NULL && !bFound) {
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, m_nPhase)) {
// ciclo sui pezzi del grezzo
int nPartId = m_pMchMgr->GetFirstPartInRawPart( nRawId) ;
while ( nPartId != GDB_ID_NULL && !bFound) {
// ciclo sui layer dei pezzi
int nLayId = m_pGeomDB->GetFirstGroupInGroup( nPartId) ;
while ( nLayId != GDB_ID_NULL && !bFound) {
// ciclo sulle entità del layer
int nEntId = m_pGeomDB->GetFirstInGroup( nLayId) ;
while ( nEntId != GDB_ID_NULL && !bFound) {
// se entità superficie e visibile, la aggiungo
int nStat ;
if ( m_pGeomDB->GetGeoType( nEntId) == SRF_TRIMESH) {
// recupero l'ggetto dal databse con tale Id
const IGeoObj* pGObj = m_pGeomDB->GetGeoObj( nEntId) ;
// recupero il frame in cui si trova
Frame3d frPart ;
m_pGeomDB->GetGlobFrame( nEntId, frPart) ;
if ( pGObj == nullptr)
return false ;
// controllo che effettivamente sia una TriMesh
if ( pGObj->GetType() == SRF_TRIMESH) {
// Trimesh della Part
PtrOwner<ISurfTriMesh> pStmRawPart( CloneSurfTriMesh( pGObj)) ;
if ( IsNull( pStmRawPart))
return false ;
// porto la Trimesh in globale
pStmRawPart->LocToLoc( frPart, GLOB_FRM) ;
// controllo se il punto è interno a tale Part
double dElev = 0. ;
DistPointSurfTm DistPtStm( ptInside, *pStmRawPart) ;
if ( DistPtStm.IsPointInside()) {
pStmCurrRawPart->CopyFrom( pStmRawPart) ;
IGeoPoint3d* ptIns( CreateGeoPoint3d()) ; ptIns->Set( ptInside) ;
m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, ptIns) ;
m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStmCurrRawPart->Clone()) ;
if ( ! pStmCurrRawPart->IsValid())
return false ;
bFound = true ;
break ;
}
}
}
// passo alla entità successiva
nEntId = m_pGeomDB->GetNext( nEntId) ;
}
nLayId =m_pGeomDB->GetNextGroup( nLayId) ;
}
nPartId = m_pMchMgr->GetNextPartInRawPart( nPartId) ;
}
}
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
}
// parte non trovata
if ( ! bFound)
return false ;
// interseco la TriMesh complessiva di pocketing con il finito, ottenendo il volume di svuotatura
m_pStmVolPocket.Set( Release( pStmCurrRawPart)) ;
if ( IsNull( m_pStmVolPocket) || ! m_pStmVolPocket->IsValid())
return false ;
if ( ! m_pStmVolPocket->Intersect( *pStm)) // intersezione
return false ;
m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, m_pStmVolPocket->Clone()) ;
return m_pStmVolPocket->IsValid() && m_pStmVolPocket->GetTriangleCount() > 0 ;
}
//----------------------------------------------------------------------------
bool
Pocketing::ProcessPath( int nAuxId, int nPvId, int nClId)
+11 -2
View File
@@ -81,7 +81,16 @@ class Pocketing : public Machining
bool GeneratePocketingPv( int nPathId, const ISurfFlatRegion* pSrfPock) ;
bool CheckSelectedId( void) ;
bool DetectShape( int nId, Frame3d frPocket) ;
bool DetectOpenEdgeInsideRaw ( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw ) ;
bool DetectOpenEdgeInsideRaw ( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmRaw) ;
bool CreateStmForIntersection( ISurfTriMesh* pStm, ICRVCOMPOPOVECTOR& vCrvCompo) ;
bool GetExtendedLoopToFitStmVolume( ICurveComposite* pCrvLoop) ;
bool SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm) ;
bool GetCurrentPart( const Point3d ptInside, ISurfTriMesh* pStmRawPart) ;
// =========================== MIGLIORIE GENERALI ====================
bool ModifyCurveToSmoothed( ICurveComposite* pCrvOffset, double dRightPer, double dleftPer) ;
@@ -371,7 +380,7 @@ class Pocketing : public Machining
double m_dOpenMinSafe ; // minima distanza di sicurezza di attacco su lato aperto
PtrOwner<ISurfTriMesh> m_pStmVolPocket ; // volume delle svuotatura
Vector3d m_vtTool = V_INVALID ; // versore direzione tool
Vector3d m_vtNormal = V_INVALID ; // versore normale ai piani di pocketing