Merge branch 'master' into FasterVMill5Axis
This commit is contained in:
+152
-109
@@ -311,7 +311,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
const Frame3d& frGrid, double dDimZ, double dLevel, double dStep, double dAngTol,
|
||||
bool bAdvCorners)
|
||||
{
|
||||
|
||||
// se non ho polylinee, allora esco
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
@@ -341,10 +340,45 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
if ( ! CalcRegionPolyLines( vPL, vtN, mIndMat, vbInv))
|
||||
return false ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
|
||||
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
|
||||
// ombra del tool
|
||||
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
|
||||
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
|
||||
// 1° gruppo, griglia di punti
|
||||
for ( int j = 0 ; j <= nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= nStepX ; ++ i) {
|
||||
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
|
||||
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
|
||||
myPtGrid->Set( ptP) ;
|
||||
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
|
||||
vvCol[0].emplace_back( BLUE) ;
|
||||
}
|
||||
}
|
||||
// 2° gruppo, superfici
|
||||
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
|
||||
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
|
||||
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
|
||||
if ( ! IsNull( pMyStm)) {
|
||||
pMyStm->ToLoc( frGrid) ;
|
||||
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
|
||||
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// vettore delle polyline visitate ( viste però come curve composite)
|
||||
ICRVCOMPOPOVECTOR vPL_AsCompo ; vPL_AsCompo.reserve( vPL.size()) ;
|
||||
|
||||
// scorro i Chunk della matrice di interi, quindi le righe
|
||||
for ( int nChunk = 0 ; nChunk < int( mIndMat.size()) ; ++ nChunk) {
|
||||
// scorro le PolyLinee presenti nel Chunk
|
||||
for ( int nPol = 0 ; nPol < int( vPL.size()) ; ++ nPol) {
|
||||
for ( int nLoop = 0 ; nLoop < int( mIndMat[nChunk].size()) ; ++ nLoop) {
|
||||
// recupero l'indice della PolyLine di riferimento
|
||||
int nPol = mIndMat[nChunk][nLoop] ;
|
||||
if ( nPol < 0 || nPol >= int( vPL.size()))
|
||||
return false ;
|
||||
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla
|
||||
int nPts = vPL[nPol].GetPointNbr() ;
|
||||
if ( nPts < 4)
|
||||
@@ -380,33 +414,6 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
vAdvPt.emplace_back( make_pair( myPt, PointType::VALID)) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
vector<vector<IGeoObj*>> vvpGObj ; vvpGObj.resize( 7) ;
|
||||
vector<vector<Color>> vvCol ; vvCol.resize( 7) ;
|
||||
// ombra del tool
|
||||
PtrOwner<ICurveArc> pCrvToolShape( CreateCurveArc()) ;
|
||||
pCrvToolShape->Set( ORIG, Z_AX, cavTstm.GetToolRadius()) ;
|
||||
// 1° gruppo, griglia di punti
|
||||
for ( int j = 0 ; j <= nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= nStepX ; ++ i) {
|
||||
Point3d ptP = Point3d( i * dStep, j * dStep, dDimZ) ;
|
||||
PtrOwner<IGeoPoint3d> myPtGrid( CreateGeoPoint3d()) ;
|
||||
myPtGrid->Set( ptP) ;
|
||||
vvpGObj[0].emplace_back( static_cast<IGeoObj*>( Release( myPtGrid))) ;
|
||||
vvCol[0].emplace_back( BLUE) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
// 2° gruppo, superfici
|
||||
CISURFTMPVECTOR myStmVector = cavTstm.GetvStm() ;
|
||||
for ( int i = 0 ; i < int( myStmVector.size()) ; ++ i) {
|
||||
PtrOwner<ISurfTriMesh> pMyStm( CloneSurfTriMesh( myStmVector[i])) ;
|
||||
if ( ! IsNull( pMyStm)) {
|
||||
pMyStm->ToLoc( frGrid) ;
|
||||
vvpGObj[1].emplace_back( static_cast<IGeoObj*>( Release( pMyStm))) ;
|
||||
vvCol[1].emplace_back( Color( 0., 1., 0., .5)) ;
|
||||
}
|
||||
}
|
||||
// 3° gruppo, punti della PolyLine
|
||||
for ( int i = 0 ; i < int( vAdvPt.size()) ; ++ i) {
|
||||
PtrOwner<IGeoPoint3d> myPt( CreateGeoPoint3d()) ;
|
||||
@@ -416,23 +423,23 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
}
|
||||
#endif
|
||||
|
||||
// modifico la posizione dei punti
|
||||
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
|
||||
return false ;
|
||||
// modifico la posizione dei punti
|
||||
if ( ! ModifyPolyLineToSharped( vAdvPt, cavTstm, frGrid, dAngTol, dStep, dSegLen))
|
||||
return false ;
|
||||
|
||||
// ricostrusico la polyLine
|
||||
vPL[nPol].Clear() ;
|
||||
// ricostrusico la polyLine a partire da una vuota
|
||||
PolyLine PL_New ;
|
||||
double dPar = -1 ;
|
||||
for ( int j = 0 ; j < int( vAdvPt.size()) ; ++ j) {
|
||||
// se punto valido o sharped di angolo interno, lo aggiungo
|
||||
if ( j == 0 || j == int( vAdvPt.size() - 1) ||
|
||||
vAdvPt[j].second == PointType::VALID || vAdvPt[j].second == PointType::SHARPED_INT)
|
||||
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
// se è un punto sharped di un angolo esterno
|
||||
else if ( vAdvPt[j].second == PointType::SHARPED_EXT) {
|
||||
// se non richiesto il calcolo avanzato del punto a minima distanza dallo spigolo, aggiungo il punto
|
||||
if ( ! bAdvCorners)
|
||||
vPL[nPol].AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
PL_New.AddUPoint( ++ dPar, vAdvPt[j].first) ;
|
||||
else {
|
||||
// ricavo il punto a minima distanza dal materiale mediante metodo di bisezione
|
||||
Vector3d vtPrev = ( vAdvPt[j-1].first - vAdvPt[j].first) ;
|
||||
@@ -463,51 +470,29 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
DistPointLine distPtLSucc( ptTest, vAdvPt[j].first, vAdvPt[j+1].first) ;
|
||||
distPtLPrev.GetMinDistPoint( ptMinDistA) ;
|
||||
distPtLSucc.GetMinDistPoint( ptMinDistB) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptMinDistA) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptTest) ;
|
||||
vPL[nPol].AddUPoint( ++ dPar, ptMinDistB) ;
|
||||
}
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistA) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptTest) ;
|
||||
PL_New.AddUPoint( ++ dPar, ptMinDistB) ;
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 5° gruppo, punti minDist A e B e ptMid
|
||||
/*PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
|
||||
myPtA->Set( ptMinDistA) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
|
||||
myPtB->Set( ptMinDistB) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
|
||||
myPtMid->Set( ptTest) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;*/
|
||||
#endif
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 5° gruppo, punti minDist A e B e ptMid
|
||||
PtrOwner<IGeoPoint3d> myPtA( CreateGeoPoint3d()) ;
|
||||
myPtA->Set( ptMinDistA) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtA))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtB( CreateGeoPoint3d()) ;
|
||||
myPtB->Set( ptMinDistB) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtB))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
PtrOwner<IGeoPoint3d> myPtMid( CreateGeoPoint3d()) ;
|
||||
myPtMid->Set( ptTest) ;
|
||||
vvpGObj[4].emplace_back( static_cast<IGeoObj*>( Release( myPtMid))) ;
|
||||
vvCol[4].emplace_back( BROWN) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// riposiziono la polyLine
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
// 6° gruppo, curve composita derivante dalla polyline
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( vPL[nPol]) ;
|
||||
//pCrvCompoPoly->SetExtrusion( frGrid.VersZ()) ;
|
||||
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||
vvCol[5].emplace_back( RED) ;
|
||||
// 7° gruppo, controOffset
|
||||
OffsetCurve offsCrv ;
|
||||
offsCrv.Make( pCrvCompoPoly, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||
pCrvCompoPoly.Set( ConvertCurveToComposite( offsCrv.GetLongerCurve())) ;
|
||||
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( Release( pCrvCompoPoly))) ;
|
||||
vvCol[6].emplace_back( WHITE) ;
|
||||
string myName = Sharped_Edges_Debug_File_Name +
|
||||
to_string( nChunk) + "_" +
|
||||
to_string( nPol) + "_" +
|
||||
to_string( dLevel) + "_" +
|
||||
to_string( dAngTol) + ".nge" ;
|
||||
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||
#endif
|
||||
|
||||
// se la polyLinea si autointerseca, allora non la modifico ( essendo a distanza R dalla
|
||||
// trimesh rischio di evere Chunk distinti uniti in un unico Chunk
|
||||
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
||||
@@ -515,11 +500,53 @@ TestEdgesClosedPolyLines( POLYLINEVECTOR& vPL, const CAvToolSurfTm& cavTstm, int
|
||||
return false ;
|
||||
pCompo->FromPolyLine( vPL[nPol]) ;
|
||||
SelfIntersCurve SIC( *pCompo) ;
|
||||
if ( SIC.GetCrossOrOverlapIntersCount() > 0)
|
||||
continue ;
|
||||
bool bDiscard = ( SIC.GetCrossOrOverlapIntersCount() > 0) ;
|
||||
if ( ! bDiscard) {
|
||||
// se la polyLine interseca una delle PolyLine precedenti, non la modifico
|
||||
for ( auto& pCompoPL_Prev : vPL_AsCompo) {
|
||||
IntersCurveCurve ICC( *pCompo, *pCompoPL_Prev) ;
|
||||
if ( ICC.GetCrossOrOverlapIntersCount() > 0) {
|
||||
bDiscard = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se nuova approssimazione da conservare, memorizzo i risultati
|
||||
if ( ! bDiscard) {
|
||||
vPL[nPol] = PL_New ;
|
||||
vPL_AsCompo.emplace_back( Release( pCompo)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_SHARPED_EDGES_DEBUG
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
// 6° gruppo, curve composita derivante dalla polyline
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vvpGObj[5].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCrvCompoPoly))) ;
|
||||
vvCol[5].emplace_back( RED) ;
|
||||
vpCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
}
|
||||
// 7° gruppo, controOffset
|
||||
ICURVEPOVECTOR vCrvCompoOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vCrvCompoOffs, - ( cavTstm.GetToolRadius() - 2 * EPS_SMALL), ICurve::OFF_EXTEND)) {
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
return false ;
|
||||
}
|
||||
for ( auto& pCrv : vpCrv) { delete( pCrv) ; pCrv = nullptr ;}
|
||||
for ( const auto& pCvrOffs : vCrvCompoOffs) {
|
||||
vvpGObj[6].emplace_back( static_cast<IGeoObj*>( CloneCurveComposite( pCvrOffs))) ;
|
||||
vvCol[6].emplace_back( WHITE) ;
|
||||
}
|
||||
string myName = Sharped_Edges_Debug_File_Name +
|
||||
to_string( dLevel) + "_" +
|
||||
to_string( dAngTol) + ".nge" ;
|
||||
SaveGeoObj( vvpGObj, vvCol, myName) ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -785,21 +812,31 @@ MarchingSquares( const DBLVECTOR& vdGrid, int nStepX, int nStepY, double dStep,
|
||||
if ( TestEdgesClosedPolyLines( vPL_Sharped, cavTstm, nStepX, nStepY, frGrid, dDimZ, dLevel, dStep, ANG_TOL_STD_DEG, false))
|
||||
swap( vPL_Sharped, vPL) ;
|
||||
|
||||
// se vettore di PolyLine vuoto, non faccio nulla
|
||||
if ( vPL.empty())
|
||||
return true ;
|
||||
|
||||
// se non ho impostato un utensile, devo effettuare un contro-offset
|
||||
if ( ! bTool) {
|
||||
POLYLINEVECTOR vPL_Offs ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
CurveComposite crvCompo ;
|
||||
if ( ! crvCompo.FromPolyLine( vPL[i]))
|
||||
return false ;
|
||||
OffsetCurve offsCompo ;
|
||||
offsCompo.Make( &crvCompo, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND) ;
|
||||
PtrOwner<ICurve> pCrvOffset( offsCompo.GetLongerCurve()) ;
|
||||
while ( ! IsNull( pCrvOffset)) {
|
||||
ICURVEPOVECTOR vpOwCrv ; vpOwCrv.reserve( vPL.size()) ;
|
||||
ICURVEPVECTOR vpCrv ; vpCrv.reserve( vPL.size()) ;
|
||||
for ( const auto& PL : vPL) {
|
||||
PtrOwner<ICurveComposite> pCrvCompoPoly( CreateCurveComposite()) ;
|
||||
pCrvCompoPoly->FromPolyLine( PL) ;
|
||||
vpOwCrv.emplace_back( Release( pCrvCompoPoly)) ;
|
||||
vpCrv.emplace_back( vpOwCrv.back()) ;
|
||||
}
|
||||
// calcolo l'Offset
|
||||
ICURVEPOVECTOR vpCrvOffs ;
|
||||
if ( ! CalcOffsetCurves( vpCrv, vpCrvOffs, - ( dRad - 2 * EPS_SMALL), ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
// resituisco le PolyLine
|
||||
POLYLINEVECTOR vPL_Offs ; vPL_Offs.reserve( vpCrvOffs.size()) ;
|
||||
for ( auto& pCrv : vpCrvOffs) {
|
||||
if ( pCrv != nullptr && pCrv->IsValid()) {
|
||||
PolyLine myPolyLine ;
|
||||
pCrvOffset->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||
pCrv->ApproxWithLines( 10 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, myPolyLine) ;
|
||||
vPL_Offs.emplace_back( myPolyLine) ;
|
||||
pCrvOffset.Set( offsCompo.GetLongerCurve()) ;
|
||||
}
|
||||
}
|
||||
swap( vPL_Offs, vPL) ;
|
||||
@@ -976,28 +1013,13 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
return false ;
|
||||
b3All.Add( b3Surf) ;
|
||||
}
|
||||
|
||||
// calcolo dati della griglia
|
||||
const double EXTRA_XY = ( m_bTool ? m_dRad + 2 : 1.5 * m_dTol) ;
|
||||
// espansione in Z del Box
|
||||
const double EXTRA_Z = 10 * m_dTol + ( m_dMaxDepth > EPS_SMALL ? max( 0., m_dMaxDepth - b3All.GetDimZ()) : 0) ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, EXTRA_Z) ;
|
||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
b3All.Expand( 0., 0., EXTRA_Z) ;
|
||||
m_dDimZ = b3All.GetDimZ() ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
|
||||
// calcolo dei punti della griglia (sul top del cilindro)
|
||||
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
|
||||
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
|
||||
int nInd = i + j * ( m_nStepX + 1) ;
|
||||
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
|
||||
vPntM[nInd] = { ptP, 0.} ;
|
||||
}
|
||||
}
|
||||
|
||||
// esecuzione della verifica
|
||||
// set utensile corrente per calcolo delle collisioni
|
||||
double dExtraXY = m_dRad ;
|
||||
if ( m_dSideAng < EPS_ANG_SMALL)
|
||||
m_cavTstm.SetStdTool( m_dDimZ + m_dOffsR, m_dRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
else {
|
||||
@@ -1015,8 +1037,29 @@ CAvParSilhouettesSurfTm::Prepare( void)
|
||||
|
||||
double dStemRad = m_dRad + dDeltaRad ;
|
||||
double dTipRad = m_dRad ;
|
||||
dExtraXY = dStemRad ;
|
||||
m_cavTstm.SetAdvTool( m_dDimZ + m_dOffsR, dStemRad + m_dOffsR, m_dMaxMat, dTipRad + m_dOffsR, m_dCornRad + m_dOffsR) ;
|
||||
}
|
||||
|
||||
// calcolo dati della griglia
|
||||
const double EXTRA_XY = ( m_bTool ? dExtraXY + 2. : 1.5 * m_dTol) ;
|
||||
b3All.Expand( EXTRA_XY, EXTRA_XY, 0.) ;
|
||||
m_frGrid.ChangeOrig( GetToGlob( b3All.GetMin(), m_frGrid)) ;
|
||||
m_dLevelOffs = - b3All.GetMin().z ;
|
||||
m_nStepX = int( ceil( b3All.GetDimX() / m_dTol)) ;
|
||||
m_nStepY = int( ceil( b3All.GetDimY() / m_dTol)) ;
|
||||
|
||||
// calcolo dei punti della griglia (sul top del cilindro)
|
||||
PNTUVECTOR vPntM( ( m_nStepX + 1) * ( m_nStepY + 1)) ;
|
||||
for ( int j = 0 ; j <= m_nStepY ; ++ j) {
|
||||
for ( int i = 0 ; i <= m_nStepX ; ++ i) {
|
||||
int nInd = i + j * ( m_nStepX + 1) ;
|
||||
Point3d ptP = GetToGlob( Point3d( i * m_dTol, j * m_dTol, m_dDimZ), m_frGrid) ;
|
||||
vPntM[nInd] = { ptP, 0.} ;
|
||||
}
|
||||
}
|
||||
|
||||
// esecuzione verifica della collisione
|
||||
if ( m_vpStm.empty() || ! m_cavTstm.SetSurfTm( *( m_vpStm[0])))
|
||||
return false ;
|
||||
for ( int k = 1 ; k < int( m_vpStm.size()) ; ++ k)
|
||||
|
||||
+229
-111
@@ -56,6 +56,7 @@ struct PocketParams {
|
||||
double dMaxOptSize = 0. ; // dimensione per ottimizzazione
|
||||
double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag
|
||||
double dLiTang = INFINITO ; // valore di LeadIn in ingresso
|
||||
bool bCalcUnclearedRegs = true ; // flag per calcolare o meno le regioni non svuotate
|
||||
bool bOptOffsets = true ; // flag per evitare Offset non necessari
|
||||
bool bAboveHead = true ; // flag per testa da sopra ( Z+)
|
||||
bool bSmooth = false ; // curve smussate
|
||||
@@ -398,6 +399,16 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SwapSideBySecondTempParam( ICurveComposite* pCompo)
|
||||
{
|
||||
if ( pCompo == nullptr || ! pCompo->IsValid())
|
||||
return false ;
|
||||
pCompo->SetTempParam( int( pCompo->GetTempParam( 1)) == MDS_LEFT ? MDS_RIGHT : MDS_LEFT, 1) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll)
|
||||
@@ -462,7 +473,7 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdg
|
||||
pNewCrv->SetTempProp( pCrv->GetTempProp( 0), 0) ;
|
||||
pNewCrv->SetTempProp( pCrv->GetTempProp( 1), 1) ;
|
||||
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
|
||||
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
|
||||
pNewCrv->SetTempParam( pCrv->GetTempParam( 1), 1) ;
|
||||
double dThick ; pCrv->GetThickness( dThick) ;
|
||||
pNewCrv->SetThickness( dThick) ;
|
||||
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
|
||||
@@ -4784,7 +4795,7 @@ CalcSpecialBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart,
|
||||
pZigZagLink->AddLine( ptNew) ;
|
||||
}
|
||||
|
||||
// questa composita contiene al massimo 5 curve e, in generale, quella una curva molto più lunga
|
||||
// questa composita contiene al massimo 5 curve e, in generale, una curva molto più lunga
|
||||
// delle altre ( quella che collega le due estensioni calcolate). Spezzo la composita ottenuta in curve
|
||||
// la cui lunghezza massima è circa il raggio utensile
|
||||
PolyLine PL ;
|
||||
@@ -4965,12 +4976,14 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM
|
||||
double dLenS ; pCrvS->GetLength( dLenS) ;
|
||||
double dLenE ; pCrvE->GetLength( dLenE) ;
|
||||
|
||||
// se ho una curva di primo Offset allora non devo accorciarla ( sia per bordi esterni che per isole)
|
||||
// azzero i parametri per curve di primo Offset
|
||||
for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) {
|
||||
if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE))
|
||||
dLenPercS = 0. ;
|
||||
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
|
||||
dLenPercE = 0. ;
|
||||
#if 0
|
||||
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
|
||||
dLenPercE = 0. ;
|
||||
#endif
|
||||
}
|
||||
#if 0 // nel caso volessi estendere anche prima del punto finale
|
||||
double dLStepS = ( dLenPercS < EPS_SMALL ? 0. : PockParams.dRad) ;
|
||||
@@ -5025,14 +5038,17 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM
|
||||
|
||||
//----------------------------------------------------------
|
||||
static bool
|
||||
GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
|
||||
const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ISurfFlatRegion* pSrfToCut)
|
||||
GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks,
|
||||
const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, ISurfFlatRegion* pSfrUncleared)
|
||||
{
|
||||
// se non devo nè calcolare la Feed nè calcolare le regioni svuotate, allora non faccio nulla
|
||||
if ( ! PockParams.bCalcFeed && ! PockParams.bCalcUnclearedRegs)
|
||||
return true ;
|
||||
|
||||
// controllo dei parametri
|
||||
if ( vFirstOffs.empty() || int( vOffs.size()) < int( vFirstOffs.size()))
|
||||
return false ;
|
||||
pSrfToCut->Clear() ;
|
||||
pSfrUncleared->Clear() ;
|
||||
|
||||
// creo la regione esterna ( definita dalle curve di primo Offset)
|
||||
// NB. Questa regione è diversa dalla pSfrOrig :
|
||||
@@ -5053,7 +5069,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
|
||||
}
|
||||
}
|
||||
|
||||
// 2) creo la regione che all'esterno contiene i lati aperti
|
||||
// creo la regione che all'esterno contiene i lati aperti
|
||||
// NB. Prendendo la superficie originale ( con lati Open/Close impostati), se effettuo un
|
||||
// Offset interno dell'estensione degli aperti, tutto ciò che è all'esterno di tale regione è classificato
|
||||
// come lato aperto
|
||||
@@ -5081,6 +5097,9 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
|
||||
// recupero le proprietà temporanee
|
||||
int nProp0 = vOffs[i]->GetTempProp( 0) ;
|
||||
int nProp1 = vOffs[i]->GetTempProp( 1) ;
|
||||
// il primo TempParam viene settato in proporzione alla Feed
|
||||
// il secondo TempParam contiene l'nSide della curva
|
||||
double dTempPar1 = vOffs[i]->GetTempParam( 1) ;
|
||||
|
||||
// Feed
|
||||
bool bFirstOffs = false ;
|
||||
@@ -5100,10 +5119,11 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
|
||||
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
|
||||
pSfrTool.Set( pSrfToolOffs) ;
|
||||
else
|
||||
pSfrTool->Add( *pSrfToolOffs) ;
|
||||
pSfrTool->Add( *pSrfToolOffs) ;
|
||||
}
|
||||
vOffs[i]->SetTempProp( nProp0, 0) ;
|
||||
vOffs[i]->SetTempProp( nProp1, 1) ;
|
||||
vOffs[i]->SetTempParam( dTempPar1, 1) ;
|
||||
|
||||
// ================= LINK ================================
|
||||
int nLink_Ind = ( bFollowOrder ? i + 1 : i) ;
|
||||
@@ -5125,7 +5145,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
|
||||
if ( ! IsNull( pSfrToolLink)) {
|
||||
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
|
||||
pSfrTool.Set( pSfrToolLink) ;
|
||||
else
|
||||
else
|
||||
pSfrTool->Add( *pSfrToolLink) ;
|
||||
}
|
||||
// risetto il Link come curva composita ...
|
||||
@@ -5136,10 +5156,12 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
|
||||
|
||||
}
|
||||
|
||||
// 4) Creo la regione contenente tutte le parti non svuotate
|
||||
pSrfToCut->CopyFrom( pSrfExtern) ;
|
||||
if ( ! pSrfToCut->Subtract( *pSfrTool))
|
||||
return false ;
|
||||
// se rischiesto, creo la regione contenente tutte le parti non svuotate
|
||||
if ( PockParams.bCalcUnclearedRegs) {
|
||||
pSfrUncleared->CopyFrom( pSrfExtern) ;
|
||||
if ( ! pSfrUncleared->Subtract( *pSfrTool))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -5150,12 +5172,13 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
|
||||
const Point3d& ptToGo, const PocketParams& PockParams,
|
||||
int& nInd, Point3d& ptCloser, bool& bFirstOffs)
|
||||
{
|
||||
/*
|
||||
E' richiesto che le curve di Offset presentino le seguenti TempProps :
|
||||
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
|
||||
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
|
||||
[per SPIRAL le proprietà sono ricavate automaticamente]
|
||||
*/
|
||||
// E' richiesto che le curve di Offset presentino le seguenti proprietà :
|
||||
// - CONFORMAL
|
||||
// * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter)
|
||||
// * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
|
||||
// - SPIRAL
|
||||
// * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno
|
||||
// * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
|
||||
|
||||
// controllo dei parametri
|
||||
nInd = -1 ;
|
||||
@@ -5177,10 +5200,8 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
|
||||
vOffsPtMinDist[i].nInd = i ;
|
||||
// nel caso di Conformal, escludo le curve di primo Offset dalla ricerca
|
||||
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
|
||||
bool bSkip = false ;
|
||||
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) && ! bSkip ; ++ j)
|
||||
bSkip = ( vOffs[i]->GetTempProp( 0) == 0) ; // prima iterazione
|
||||
if ( bSkip) {
|
||||
// prima iterazione
|
||||
if ( vOffs[i]->GetTempProp( 0) == 0) {
|
||||
vOffsPtMinDist[i].bFirstOffs = true ;
|
||||
continue ;
|
||||
}
|
||||
@@ -5190,26 +5211,16 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
|
||||
// in questo modo riesco a creare le curve a ricciolo
|
||||
int nSide ;
|
||||
DistPointCurve DistPtCrv( ptToGo, *vOffs[i]) ;
|
||||
bool bFirstBorderIsland = false ;
|
||||
if ( DistPtCrv.GetSideAtMinDistPoint( EPS_SMALL, Z_AX, nSide)) {
|
||||
// nel caso Spiral
|
||||
if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) {
|
||||
// InVsOut
|
||||
vOffsPtMinDist[i].bInVsOut = ( ( ! PockParams.bInvert && nSide == MDS_LEFT) ||
|
||||
( PockParams.bInvert && nSide == MDS_RIGHT)) ;
|
||||
vOffsPtMinDist[i].bInVsOut = ( int( vOffs[i]->GetTempParam( 1) != nSide)) ;
|
||||
// controllo se la curva in questione è di primo Offset
|
||||
Point3d ptCheck ; vOffs[i]->GetStartPoint( ptCheck) ;
|
||||
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) ; ++ j) {
|
||||
if ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100 * EPS_SMALL)) {
|
||||
vOffsPtMinDist[i].bFirstOffs = true ;
|
||||
// controllo se Isola o di bordo
|
||||
double dArea = 0. ;
|
||||
vOffs[i]->GetAreaXY( dArea) ;
|
||||
bFirstBorderIsland = ( ( ! PockParams.bInvert && dArea < 0.) ||
|
||||
( PockParams.bInvert && dArea > 0.)) ;
|
||||
// se isola di primo Offset, InVsOut va invertito
|
||||
if ( bFirstBorderIsland)
|
||||
vOffsPtMinDist[i].bInVsOut = ( ! vOffsPtMinDist[i].bInVsOut) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
@@ -5228,7 +5239,7 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
|
||||
PockParams.dSideStep + PockParams.dSideStep ;
|
||||
}
|
||||
// se curva di bordo esterno, aggiungo un'altra penalità ( euristica)
|
||||
if ( vOffsPtMinDist[i].bFirstOffs && ! bFirstBorderIsland)
|
||||
if ( vOffsPtMinDist[i].bFirstOffs)
|
||||
vOffsPtMinDist[i].dSqDist *= 2. ;
|
||||
}
|
||||
}
|
||||
@@ -5249,12 +5260,17 @@ static bool
|
||||
RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs,
|
||||
ICRVCOMPOPOVECTOR& vOffsFirstCurve, const PocketParams& PockParams)
|
||||
{
|
||||
/*
|
||||
E' richiesto che le curve di Offset presentino le seguenti TempProps :
|
||||
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
|
||||
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
|
||||
[per SPIRAL le proprietà sono ricavate automaticamente]
|
||||
*/
|
||||
// se non devo calcolare le regioni non svuotate, esco subito
|
||||
if ( ! PockParams.bCalcUnclearedRegs)
|
||||
return true ;
|
||||
|
||||
// E' richiesto che le curve di Offset presentino le seguenti proprietà :
|
||||
// - CONFORMAL
|
||||
// * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter)
|
||||
// * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
|
||||
// - SPIRAL
|
||||
// * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno
|
||||
// * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
|
||||
|
||||
// se non ho nessuna superficie valida da svuotare, allora esco
|
||||
if ( pSfrUncleared == nullptr)
|
||||
@@ -5267,17 +5283,15 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR&
|
||||
for ( int nC = 0 ; nC < pSfrUncleared->GetChunkCount() ; ++ nC) {
|
||||
// recupero il centroide del Chunk da rimuovere
|
||||
Point3d ptCentroid ; pSfrUncleared->GetChunkCentroid( nC, ptCentroid) ;
|
||||
/*
|
||||
Tra tutte le curve di Offset escludo le curve che :
|
||||
- Sono di primo Offset
|
||||
- Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
|
||||
... cerco la più vicina tra le rimanenti
|
||||
*/
|
||||
// Tra tutte le curve di Offset escludo le curve che :
|
||||
// - Sono di primo Offset
|
||||
// - Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
|
||||
// ... cerco la più vicina tra le rimanenti
|
||||
// recupero la curva migliore
|
||||
int nInd = -1 ;
|
||||
Point3d ptCloser ;
|
||||
bool bFirstOffs = false ;
|
||||
if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams,
|
||||
if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams,
|
||||
nInd, ptCloser, bFirstOffs))
|
||||
return false ;
|
||||
// se nessun indice trovato, salto il chunk
|
||||
@@ -5570,6 +5584,9 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
|
||||
vLinks.clear() ;
|
||||
vLinks.resize( int( vOffs.size())) ;
|
||||
|
||||
// NB. Dato che le curve di Offset sono invertite a seconda di dove si trova il materiale,
|
||||
// Utilizzo il secondo TempParam per evere l'nSide
|
||||
|
||||
// scorro tutte le curva di Offset
|
||||
for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) {
|
||||
|
||||
@@ -5577,6 +5594,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
|
||||
Point3d ptS ;
|
||||
if ( ! vOffs[i]->GetStartPoint( ptS))
|
||||
return false ;
|
||||
|
||||
// tra le curve successive cerco la curva interna e più vicina ad essa
|
||||
int nNextInd = -1 ; // indice della curva successiva
|
||||
double dMinDist = INFINITO ; // distanza tra questa curva e la successiva
|
||||
@@ -5588,8 +5606,8 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
|
||||
// se interna
|
||||
if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) &&
|
||||
int( ccClass.size()) == 1 &&
|
||||
( ( ! PockParams.bInvert && ccClass[0].nClass == CRVC_IN) ||
|
||||
( PockParams.bInvert && ccClass[0].nClass == CRVC_OUT))) {
|
||||
( ( ccClass[0].nClass == CRVC_IN && int( vOffs[i]->GetTempParam( 1)) == MDS_RIGHT) ||
|
||||
( ccClass[0].nClass == CRVC_OUT && int( vOffs[i]->GetTempParam( 1)) == MDS_LEFT))) {
|
||||
// calcolo la distanza minima tra essa
|
||||
int nFlag ;
|
||||
double dPar = 0. ;
|
||||
@@ -5649,13 +5667,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
|
||||
// scambio la curva i+1 esima con la j-esima ( se non sono già in ordine)
|
||||
if ( nNextInd != i + 1)
|
||||
swap( vOffs[nNextInd], vOffs[i+1]) ;
|
||||
|
||||
// cambio il suo punto iniziale nel punto più vicino tovato
|
||||
double dUS ;
|
||||
if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL))
|
||||
return false ;
|
||||
vOffs[i+1]->ChangeStartPoint( dUS) ;
|
||||
|
||||
// accorcio la curva per raccordarmi in tangenza con la successiva
|
||||
// se ho più di una curva di Offset
|
||||
if ( int( vOffs.size()) > 1) {
|
||||
// clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle )
|
||||
PtrOwner<ICurveComposite> pCrv_i( vOffs[i]->Clone()) ;
|
||||
@@ -5666,15 +5685,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
|
||||
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvLink))
|
||||
return false ;
|
||||
// NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset
|
||||
double dLenPercS = ( i == 0 ? 0. : 10 * EPS_SMALL) ;
|
||||
double dLenPercE = ( bMinDistAtSmooth ? 0. : 10 * EPS_SMALL) ;
|
||||
if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) ||
|
||||
! pCrvLink->IsValid()) {
|
||||
// se non sono riuscito, cerco una strada più semplice ripristinando le curve
|
||||
pCrvLink->Clear() ;
|
||||
vOffs[i].Set( pCrv_i) ; // chiuso
|
||||
vOffs[i+1].Set( pCrv_ii) ; // chiuso
|
||||
vOffs[i].Set( pCrv_i) ;
|
||||
vOffs[i+1].Set( pCrv_ii) ;
|
||||
// recupero i vettori tangenti iniziali ( le curve sono chiuse )
|
||||
Vector3d vtS, vtE ;
|
||||
if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE))
|
||||
@@ -5728,6 +5746,10 @@ CheckIfOffsetIsNecessary( const ISurfFlatRegion* pSfrAct, const ICurveComposite*
|
||||
if ( ! PockParams.bOptOffsets)
|
||||
return true ;
|
||||
|
||||
// se spiral out non vanno eliminati parti di percorso
|
||||
if ( PockParams.nType == POCKET_SPIRALOUT)
|
||||
return true ;
|
||||
|
||||
if ( nIter != 0) { // controllo se sono almeno al secondo offset...
|
||||
// per ogni curva controllo se il suo Offset massimo non genera alcuna regione
|
||||
double dMaxOffs ;
|
||||
@@ -5819,6 +5841,55 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int
|
||||
CalcInversionForSpiralOffset( const ISurfFlatRegion* pSfrChunk)
|
||||
{
|
||||
// controllo validità della regione
|
||||
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
|
||||
return -1 ;
|
||||
|
||||
// Caso 0 : Non esistono isole
|
||||
// Caso 1 : Loop Esterno Chiuso e, se esiste, Isola Chiusa
|
||||
// Caso 2 : Loop Esterno Chiuso e, se esiste, Isola Aperta
|
||||
// Caso 3 : Loop Esterno Aperto e, se esiste, Isola Chiusa
|
||||
// Caso 4 : Loop Esterno Aperto e, se esiste, Isola Aperta
|
||||
|
||||
// se non esistono isole, allora Caso 0
|
||||
if ( pSfrChunk->GetLoopCount( 0) == 1)
|
||||
return 0 ;
|
||||
|
||||
// Il Loop esterno è considerato chiuso <=> esiste almeno una curva chiusa
|
||||
bool bExtClosed = false ;
|
||||
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, 0) && ! bExtClosed ; ++ nU) {
|
||||
int nTempProp = TEMP_PROP_INVALID ;
|
||||
bExtClosed = ( pSfrChunk->GetCurveTempProp( 0, 0, nU, nTempProp) &&
|
||||
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
|
||||
}
|
||||
|
||||
// Le isole vengono classificate come tutte chiuse <=> esiste almeno un isola chiusa
|
||||
bool bIntClosed = false ;
|
||||
for ( int nLoop = 1 ; nLoop < pSfrChunk->GetLoopCount( 0) && ! bIntClosed ; ++ nLoop) {
|
||||
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, nLoop) && ! bIntClosed ; ++ nU) {
|
||||
int nTempProp = TEMP_PROP_INVALID ;
|
||||
bIntClosed = ( pSfrChunk->GetCurveTempProp( 0, nLoop, nU, nTempProp) &&
|
||||
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
|
||||
}
|
||||
}
|
||||
|
||||
// restituisco il caso corrente
|
||||
if ( bExtClosed && bIntClosed)
|
||||
return 1 ;
|
||||
if ( bExtClosed && ! bIntClosed)
|
||||
return 2 ;
|
||||
if ( ! bExtClosed && bIntClosed)
|
||||
return 3 ;
|
||||
if ( ! bExtClosed && ! bIntClosed)
|
||||
return 4 ;
|
||||
|
||||
return -1 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart,
|
||||
@@ -5833,14 +5904,19 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
// ciclo di offset verso l'interno
|
||||
const int MAX_ITER = 1000 ;
|
||||
int nIter = 0 ;
|
||||
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
|
||||
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
|
||||
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
|
||||
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
|
||||
|
||||
// tengo una copia della regione corrente da svuotare
|
||||
PtrOwner<ISurfFlatRegion> pSrfAct( CloneSurfFlatRegion( pSfrPock)) ;
|
||||
if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0)
|
||||
return false ;
|
||||
|
||||
// ricavo il tipo di relazione descritta tra Open/Close di bordo esterno e/o isole
|
||||
int nCase = CalcInversionForSpiralOffset( pSrfAct) ;
|
||||
if ( nCase == -1)
|
||||
return false ;
|
||||
|
||||
// ricavo le regioni progressive
|
||||
double dOffsPrec = 0. ;
|
||||
int nCrvFirstOffs = 0 ;
|
||||
@@ -5858,12 +5934,15 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
|
||||
// se primo Offset
|
||||
if ( nIter == 0) {
|
||||
// aggiorno il nuovo valore delle regioni totali di primo Offset
|
||||
int my_nReg = nReg ;
|
||||
nReg = pSfrOffsVR->GetChunkCount() ; // aggiorno il nuovo valore delle regioni totali di primo Offset
|
||||
nReg = pSfrOffsVR->GetChunkCount() ;
|
||||
// gli Offset progressivi appartengono al Chunk nReg-esimo
|
||||
pSrfAct.Set( pSfrOffsVR->CloneChunk( my_nReg)) ;
|
||||
if ( IsNull( pSrfAct)) // se supero i chunk ottenuti
|
||||
// se supero i chunk ottenuti
|
||||
if ( IsNull( pSrfAct))
|
||||
return true ;
|
||||
// imposto la regione id svuotatura corrente
|
||||
pSfrOffsVR.Set( pSrfAct->Clone()) ;
|
||||
}
|
||||
|
||||
@@ -5873,24 +5952,28 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
for ( int i = 0 ; i < nChunks ; ++ i) {
|
||||
// per ogni chunk...
|
||||
int nLoops = pSfrOffsVR->GetLoopCount( i) ;
|
||||
for ( int j = 0 ; j < nLoops ; ++ j) {
|
||||
for ( int j = 0 ; j < nLoops ; ++ j) {
|
||||
// per ogni loop...
|
||||
PtrOwner<ICurveComposite> pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
|
||||
if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid())
|
||||
return false ;
|
||||
/*
|
||||
Il materiale deve sempre trovarsi alla destra ( se bInvert -> alla sinistra) del tool
|
||||
soltanto sul primo bordo; Nel caso di isole aperte o nelle passate di Offset intermedio
|
||||
l'orientamente non ha importanza.
|
||||
*/
|
||||
if ( nIter != 0 && j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate)
|
||||
pCrvCompoBorder->Invert() ;
|
||||
// controllo quali regioni di Offset possono essere sostituite
|
||||
bool bInsert = true ;
|
||||
if ( ! CheckIfOffsetIsNecessary( pSrfAct, pCrvCompoBorder, dOffs, dOffsPrec, nIter, PockParams, bInsert))
|
||||
return false ;
|
||||
if ( bInsert)
|
||||
if ( bInsert) {
|
||||
// imposto come secondo TempParam il Side di classificazione
|
||||
pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ;
|
||||
// stabilisco l'orientamento della curva
|
||||
if ( ( nCase == 1 && nIter != 0 && j > 0) ||
|
||||
( nCase == 2 && j > 0) ||
|
||||
( nCase == 3 && j == 0) ||
|
||||
( nCase == 4 && j > 0)) {
|
||||
pCrvCompoBorder->Invert() ;
|
||||
SwapSideBySecondTempParam( pCrvCompoBorder) ;
|
||||
}
|
||||
vOffs.emplace_back( Release( pCrvCompoBorder)) ;
|
||||
}
|
||||
if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT)
|
||||
PtrOwner<ICurveComposite> pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
|
||||
vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ;
|
||||
@@ -5917,9 +6000,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
dOffs = PockParams.dSideStep ;
|
||||
}
|
||||
}
|
||||
// se devo usare un Offset più piccolo...
|
||||
else if ( ! bSmallRad)
|
||||
// se non ho Chunks e devo usare un Offset più piccolo...
|
||||
else if ( ! bSmallRad) {
|
||||
if ( PockParams.dRad < EPS_SMALL)
|
||||
break ;
|
||||
dOffs = dOffsPrec + ( nIter == 0 ? PockParams.dRad + PockParams.dRadialOffset : PockParams.dRad) ;
|
||||
}
|
||||
// altrimenti ho finito la regione da svuotare...
|
||||
else
|
||||
break ;
|
||||
@@ -5936,11 +6022,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
Point3d ptNewStart ;
|
||||
|
||||
// Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte...
|
||||
int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare
|
||||
int nIndexSwap = 0 ;
|
||||
if ( PockParams.nType == POCKET_SPIRALIN) {
|
||||
if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart,
|
||||
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops))
|
||||
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) {
|
||||
vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
@@ -5954,8 +6041,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
|
||||
// se richiesta inversione
|
||||
if ( PockParams.bInvert) {
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i)
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
|
||||
vOffs[i]->Invert() ;
|
||||
SwapSideBySecondTempParam( vOffs[i]) ;
|
||||
}
|
||||
}
|
||||
|
||||
// smusso le curve di offset ( ad eccezione di quelle di primo Offset)
|
||||
@@ -5975,10 +6064,6 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione
|
||||
|
||||
// riordino le curve e creo i collegamenti
|
||||
/*
|
||||
Se richiesto parametro di smusso, tutti gli Offset ( ad eccezione di quelli generati alla
|
||||
prima iterazione vengono tagliati, quindi diventano aperti
|
||||
*/
|
||||
ICURVEPOVECTOR vLinks( vOffs.size()) ;
|
||||
if ( ! CreateSpiralPocketingPath( vOffs, vLinks, PockParams, vOffsFirstCurve))
|
||||
return false ;
|
||||
@@ -5996,9 +6081,8 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
|
||||
// se collegamento da aggiungere
|
||||
if ( ! IsNull( vLinks[i])) {
|
||||
// accodo nel percorso di lavorazione
|
||||
if ( ! pMCrv->AddCurve( Release( vLinks[i]))) {
|
||||
if ( ! pMCrv->AddCurve( Release( vLinks[i])))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
pMCrv->AddCurve( Release( vOffs[i])) ;
|
||||
}
|
||||
@@ -7063,8 +7147,8 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
|
||||
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
|
||||
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
|
||||
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
|
||||
{
|
||||
|
||||
// controllo dei parametri
|
||||
@@ -7073,53 +7157,79 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
|
||||
pCrvLink == nullptr || ! pCrvLink->IsValid())
|
||||
return false ;
|
||||
|
||||
// curva precedente
|
||||
// definisco la lunghezza del segmento iniziale e finale sulle due curve di Offset
|
||||
double dRefLenSeg = 2. * dSmoothPar ;
|
||||
|
||||
// --- Curva precedente ---
|
||||
// recupero la lunghezza e il dominio del primo Offset
|
||||
double dLen ;
|
||||
pCrvOffs0->GetLength( dLen) ;
|
||||
double dUStart, dUEnd ;
|
||||
pCrvOffs0->GetDomain( dUStart, dUEnd) ;
|
||||
// inizializzo la curva
|
||||
PtrOwner<ICurveComposite> pCrvBef( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvBef))
|
||||
return false ;
|
||||
// se primo Offset di bordo o chiuso...
|
||||
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
|
||||
const ICurve* pCrvFirst = pCrvOffs0->GetFirstCurve() ;
|
||||
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
|
||||
double dU = dUEnd ;
|
||||
if ( dLen > dRefLenSeg - EPS_SMALL)
|
||||
pCrvOffs0->GetParamAtLength( dRefLenSeg, dU) ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dUStart, dU)) ;
|
||||
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
|
||||
return false ;
|
||||
pCrvBef->AddCurve( Release( pMyCrv)) ;
|
||||
}
|
||||
// altrimenti...
|
||||
else {
|
||||
const ICurve* pCrvLast = pCrvOffs0->GetLastCurve() ;
|
||||
if ( pCrvLast == nullptr || ! pCrvLast->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvLast->Clone()) ;
|
||||
double dU = dUStart ;
|
||||
if ( dLen > dRefLenSeg)
|
||||
pCrvOffs0->GetParamAtLength( dLen - dRefLenSeg, dU) ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dU, dUEnd)) ;
|
||||
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
|
||||
return false ;
|
||||
pCrvBef->AddCurve( Release( pMyCrv)) ;
|
||||
}
|
||||
// se non valida, errore
|
||||
if ( ! pCrvBef->IsValid())
|
||||
return false ;
|
||||
|
||||
// curva successiva
|
||||
// --- Curva successiva ---
|
||||
// recupero la lunghezza e il dominio del primo Offset
|
||||
pCrvOffs1->GetLength( dLen) ;
|
||||
pCrvOffs1->GetDomain( dUStart, dUEnd) ;
|
||||
// inizializzo la curva
|
||||
PtrOwner<ICurveComposite> pCrvAft( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvAft))
|
||||
return false ;
|
||||
const ICurve* pCrvFirst = pCrvOffs1->GetFirstCurve() ;
|
||||
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
|
||||
// calcolo il parametro di taglio
|
||||
double dU = dUEnd ;
|
||||
if ( dLen > dRefLenSeg - EPS_SMALL)
|
||||
pCrvOffs1->GetParamAtLength( dRefLenSeg, dU) ;
|
||||
PtrOwner<ICurve> pMyCrv( pCrvOffs1->CopyParamRange( dUStart, dU)) ;
|
||||
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
|
||||
return false ;
|
||||
pCrvAft->AddCurve( Release( pMyCrv)) ;
|
||||
// se non valida, errore
|
||||
if ( ! pCrvAft->IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo la validità delle curve precedenti e successive ricavate
|
||||
if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid())
|
||||
return false ;
|
||||
// estendo il Link
|
||||
// estendo il Link ( linea di ingresso, segmento Link, linea d'uscita)
|
||||
pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ;
|
||||
pCrvLink->AddCurve( Release( pCrvAft), true, dTol) ;
|
||||
// smusso
|
||||
|
||||
// miglioro la curva
|
||||
pCrvLink->MergeCurves( 100 * EPS_SMALL, ANG_TOL_STD_DEG) ;
|
||||
|
||||
// smusso la curva
|
||||
ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ;
|
||||
// toglo gli estremi
|
||||
|
||||
// toglo gli estremi, il Link è in tangenza e le linee di ingresso e d'uscita sono più
|
||||
// estese dell'arco di smusso creato
|
||||
delete( pCrvLink->RemoveFirstOrLastCurve( false)) ;
|
||||
delete( pCrvLink->RemoveFirstOrLastCurve( true)) ;
|
||||
// modifico Offset0 per raccordarlo al nuovo Link
|
||||
|
||||
// modifico il primo Offset per raccordarlo al nuovo Link
|
||||
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
|
||||
const ICurve* pCrvFirst = pCrvLink->GetFirstCurve() ;
|
||||
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
|
||||
@@ -7135,7 +7245,8 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
|
||||
double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ;
|
||||
pCrvOffs0->TrimEndAtParam( dUE) ;
|
||||
}
|
||||
// modifico Offset1 per raccordarlo al nuovo Link
|
||||
|
||||
// modifico il secondo Offset per raccordarlo al nuovo Link
|
||||
Point3d ptE ; pCrvLink->GetEndPoint( ptE) ;
|
||||
double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ;
|
||||
if ( bFirstOffs1 && pCrvOffs1->IsClosed())
|
||||
@@ -7195,8 +7306,8 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
|
||||
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
|
||||
CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
|
||||
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
|
||||
{
|
||||
// controllo validità delle due curve di Offset
|
||||
if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() ||
|
||||
@@ -7248,10 +7359,16 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket
|
||||
ICRVCOMPOPOVECTOR vCrvChunk ;
|
||||
for ( int i = 0 ; i < int( vIndOffs0.size()) ; ++ i)
|
||||
vCrvChunk.emplace_back( vCrvClassBorder[vIndOffs0[i]]->Clone()) ;
|
||||
// se la curva successiva è chiusa, aggiorno il suo punto iniziale a quello a minima distanza
|
||||
if ( ! bOpen1) {
|
||||
Point3d ptS ; pCrvOffs0->GetStartPoint( ptS) ;
|
||||
double dPar ;
|
||||
int nFlag ;
|
||||
if ( DistPointCurve( ptS, *pCrvOffs1).GetParamAtMinDistPoint( 0., dPar, nFlag))
|
||||
pCrvOffs1->ChangeStartPoint( dPar) ;
|
||||
}
|
||||
if ( ! CutCurveToConnect( pCrvOffs0, pCrvOffs1, vCrvChunk, PockParams,
|
||||
( ( bOpen0 || bFirstIterOffs0) ? 0. : 10 * EPS_SMALL),
|
||||
( ( bOpen1 || bFirstIterOffs1) ? 0. : 10 * EPS_SMALL),
|
||||
pCrvLink) ||
|
||||
bOpen0 ? 0. : 10 * EPS_SMALL, bOpen1 ? 0. : 10 * EPS_SMALL, pCrvLink) ||
|
||||
! pCrvLink->IsValid()) {
|
||||
// se curva di Link non valida, cerco una strada più semplice
|
||||
pCrvLink->Clear() ;
|
||||
@@ -7778,7 +7895,7 @@ CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion*
|
||||
if ( IsNull( pCrvLink))
|
||||
return false ;
|
||||
// se non calcolabile, allora retroazione, altrimenti lo memorizzo
|
||||
if ( ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
|
||||
if ( ! CalcConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
|
||||
IsNull( pCrvLink) || ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0)
|
||||
vCrvLink.resize( int( vCrvLink.size()) + 1) ;
|
||||
else
|
||||
@@ -8808,7 +8925,7 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
|
||||
double dOpenMinSafe, int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
|
||||
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
|
||||
bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs,
|
||||
double dMaxOptSize, double dLiTang, int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
|
||||
{
|
||||
@@ -8831,6 +8948,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
myParams.dAngle = dAngle ;
|
||||
myParams.dSideStep = dStep ;
|
||||
myParams.dOpenMinSafe = dOpenMinSafe ;
|
||||
myParams.bCalcUnclearedRegs = bCalcUnclReg ;
|
||||
myParams.bInvert = bInvert ;
|
||||
myParams.bAvoidOpt = bAvoidOpt ;
|
||||
myParams.bCalcFeed = bCalcFeed ;
|
||||
|
||||
@@ -2087,6 +2087,51 @@ CalcCurveSingleCurvesOffset( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double d
|
||||
return pVoronoiObj->CalcSingleCurvesOffset( vCrvs, dOffs) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs, int nType)
|
||||
{
|
||||
// creo oggetto Voronoi con le curve passate
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return pVoronoiObj->CalcOffset( vCrvs, dOffs, nType) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, double dOffs,
|
||||
bool bSquareEnds, bool bSquareMids, bool bMergeOnlySameProps)
|
||||
{
|
||||
// controllo validità delle curve
|
||||
for ( auto& pCrv : vpCrvs) {
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
}
|
||||
// se offset nullo restituisco direttamente le curve
|
||||
if ( abs( dOffs) < EPS_SMALL) {
|
||||
for ( auto& pCrv : vpCrvs) {
|
||||
if ( ! vCrvs.emplace_back( pCrv->Clone()))
|
||||
return false ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
// creo oggetto Voronoi con le curve passate
|
||||
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
|
||||
if ( pVoronoiObj == nullptr)
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
|
||||
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return pVoronoiObj->CalcFatCurve( vCrvs, dOffs, bSquareEnds, bSquareMids, bMergeOnlySameProps) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
ResetCurveVoronoi( const ICurve& crvC)
|
||||
|
||||
+10
-4
@@ -224,8 +224,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyStart( ptEnd))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyStart( ptEnd)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptEnd, ptCrvEnd) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
@@ -246,8 +249,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
// eseguo modifica
|
||||
if ( ! pCrv->ModifyEnd( ptStart))
|
||||
return false ;
|
||||
if ( ! pCrv->ModifyEnd( ptStart)) {
|
||||
CurveLine crvLine ;
|
||||
if ( ! crvLine.Set( ptCrvStart, ptStart) || ! pCrv.Set( crvLine.Clone()))
|
||||
return false ;
|
||||
}
|
||||
// verifico che la lunghezza non sia variata troppo
|
||||
double dNewLen ; pCrv->GetLength( dNewLen) ;
|
||||
if ( abs( dNewLen - dOldLen) > 10 * dLinTol)
|
||||
|
||||
Binary file not shown.
@@ -345,6 +345,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
|
||||
@@ -550,7 +550,7 @@
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -1232,6 +1232,9 @@
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+52
-2
@@ -234,12 +234,12 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
|
||||
m_vPart.clear() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
if ( ! vtN.Normalize( EPS_ZERO))
|
||||
return SVT_DEL ;
|
||||
// inserisco il triangolo
|
||||
try { m_vTria.emplace_back( nIdVert, nTFlag) ;}
|
||||
catch(...) { return SVT_NULL ;}
|
||||
// aggiorno la sua normale
|
||||
if ( ! vtN.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
m_vTria.back().vtN = vtN ;
|
||||
// aggiorno massimo TFlag
|
||||
m_nMaxTFlag = max( m_nMaxTFlag, nTFlag) ;
|
||||
@@ -4029,6 +4029,56 @@ SurfTriMesh::CloneShell( int nShell) const
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartLocalBBox( int nP, BBox3d& b3Loc) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Loc.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Loc.Add( m_vVert[m_vTria[i].nIdVert[j]].ptP) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const
|
||||
{
|
||||
// verifico esistenza della parte
|
||||
if ( nP < 0 || nP >= GetPartCount())
|
||||
return false ;
|
||||
|
||||
// assegno il box in locale
|
||||
b3Ref.Reset() ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// recupero il vettore delle Shell della parte corrente
|
||||
const auto& vShell = m_vPart[nP].vShell ;
|
||||
// scorro i triangoli validi contenuti nella Shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL &&
|
||||
find( vShell.begin(), vShell.end(), m_vTria[i].nShell) != vShell.end()) {
|
||||
// ciclo sui tre vertici
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
b3Ref.Add( GetToGlob( m_vVert[m_vTria[i].nIdVert[j]].ptP, frRef)) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetPartCount( void) const
|
||||
|
||||
@@ -337,6 +337,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetShellArea( int nShell, double& dArea) const override ;
|
||||
bool RemoveShell( int nShell) override ;
|
||||
SurfTriMesh* CloneShell( int nShell) const override ;
|
||||
bool GetPartLocalBBox( int nP, BBox3d& b3Loc) const override ;
|
||||
bool GetPartBBox( int nP, const Frame3d& frRef, BBox3d& b3Ref) const override ;
|
||||
int GetPartCount( void) const override ;
|
||||
bool RemovePart( int nPart) override ;
|
||||
bool GetPartArea( int nPart, double& dArea) const override ;
|
||||
|
||||
+53
-12
@@ -1,19 +1,21 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2022
|
||||
// EgalTech 2025
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SurfTriMeshOffset.cpp Data : 10.06.25 Versione : 2.7e4
|
||||
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
|
||||
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.25 RE Creazione modulo.
|
||||
// 10.06.25 RE Offset di superfici chiuse.
|
||||
// 04.07.25 RE Thickening Offset di superfici generiche.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "VolZmap.h"
|
||||
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -44,32 +46,71 @@ SumStm( const CISURFTMPVECTOR& vStm)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione che crea l'Offset di una superficie TriMesh chiusa */
|
||||
// Funzione che crea l'Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dLinTol)
|
||||
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return CreateSurfTriMeshesOffset( { pStm}, dOffs, dLinTol) ;
|
||||
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione che crea l'Offset di un insieme di superfici */
|
||||
// Funzione che crea il Fat Offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLinTol)
|
||||
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione che crea l'Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyLinTol = max( dLinTol, 10 * EPS_SMALL) ;
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
// --- NB. Per la creazione dello Zmap è necessario che le superfici siano chiuse
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyLinTol))
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//* Funzione che crea il Fat Offset di un insieme di superfici
|
||||
//----------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
||||
{
|
||||
// se vettore delle superfici vuoto, non faccio nulla
|
||||
if ( vStm.empty())
|
||||
return nullptr ;
|
||||
// controllo sul valore di tolleranza lineare
|
||||
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
||||
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
||||
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
||||
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return SumStm( vStm) ;
|
||||
|
||||
// creo lo Zmap associato alle superfici TriMesh
|
||||
PtrOwner<IVolZmap> pVolZmap( CreateVolZmap()) ;
|
||||
if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie TriMesh
|
||||
return ( pVolZmap->GetSurfTriMesh()) ;
|
||||
}
|
||||
|
||||
@@ -85,8 +85,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 100 * EPS_SMALL) override ;
|
||||
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0.) override ;
|
||||
bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = STMOFF_FILLET) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
@@ -461,8 +462,13 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
// Funzioni per Offset di superfici
|
||||
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) ;
|
||||
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid) ;
|
||||
bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ;
|
||||
bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ;
|
||||
bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
|
||||
+3
-2
@@ -802,7 +802,8 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
|
||||
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
|
||||
// quindi espandiamo il bounding box per ovviare al problema.
|
||||
SurfBBox.Expand( dExtraBox) ;
|
||||
if ( dExtraBox > EPS_ZERO)
|
||||
SurfBBox.Expand( dExtraBox) ;
|
||||
|
||||
// Determino i punti estremi del bounding box
|
||||
Point3d ptMapOrig, ptMapEnd ;
|
||||
@@ -920,7 +921,7 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
m_dMaxZ[2] = ( bTriDex ? vtLen.y : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = ( IsBox() ? BOX : GENERIC) ;
|
||||
m_nShape = ( dExtraBox > EPS_ZERO && IsBox() ? BOX : GENERIC) ;
|
||||
|
||||
// Aggiornamento dello stato
|
||||
m_nStatus = OK ;
|
||||
|
||||
+408
-140
@@ -23,36 +23,36 @@
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh */
|
||||
// Funzione per sottrarre intervalli lungo un Dexel per l'offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap)
|
||||
{
|
||||
// per ora la funzione è la stessa della differenza in generale
|
||||
// TODO -- Aggiustare eventuali tolleranze
|
||||
return SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh */
|
||||
// Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap)
|
||||
{
|
||||
// per ora la funzione è la stessa della somma generale
|
||||
// TODO -- Aggiustare eventuali tolleranze
|
||||
return AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, bSkipSwap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
|
||||
aggiungere o sottrarre intervalli lungo i Dexel coinvolti */
|
||||
// Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui
|
||||
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
|
||||
VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nTool)
|
||||
{
|
||||
// determino il Box della sfera posizionata su tale vertice
|
||||
BBox3d BBoxSphere( ptV - dOffs * Vector3d( 1., 1., 1.),
|
||||
@@ -78,9 +78,9 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
|
||||
Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ;
|
||||
vtNmax.Normalize() ;
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, 0) ;
|
||||
AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, 0) ;
|
||||
SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,10 +89,12 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
|
||||
aggiungere o sottrarre intervalli lungo i Dexel coinvolti */
|
||||
// Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui
|
||||
// aggiungere o sottrarre intervalli lungo i Dexel coinvolti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid)
|
||||
VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid,
|
||||
int nTool)
|
||||
{
|
||||
// determino la lunghezza dello spigolo corrente
|
||||
double dH = Dist( ptP1, ptP2) ;
|
||||
@@ -131,9 +133,9 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, 0) ;
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, 0) ;
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,10 +144,351 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/* Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da una
|
||||
superficie TriMesh */
|
||||
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
|
||||
// L'idea è quella di creare uno ZMap a partire dal Box complessivo delle superfici TriMesh :
|
||||
// - le superfici chiuse possono già inserire i rispettivi spilloni
|
||||
// - le superfici aperte non danno contributo
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
|
||||
VolZmap::InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
|
||||
{
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
|
||||
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
|
||||
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
|
||||
|
||||
// --- se una sola superficie
|
||||
if ( int( vSurf.size()) == 1) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
// --- se superficie chiusa posso direttamente creare lo Zmap iniziale
|
||||
if ( vSurf[0]->IsClosed()) {
|
||||
// definisco lo Zamp a partire dall'espansione del Box della superficie
|
||||
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
|
||||
return false ;
|
||||
}
|
||||
// --- se superficie aperta, lo creo inizialmente vuoto a partire dal suo Box
|
||||
BBox3d BBoxSurf ;
|
||||
vSurf[0]->GetLocalBBox( BBoxSurf) ;
|
||||
BBoxSurf.Expand( dBoxExpansion) ;
|
||||
if ( ! CreateEmpty( BBoxSurf.GetMin(), BBoxSurf.GetDimX(), BBoxSurf.GetDimY(), BBoxSurf.GetDimZ(), dTol, true))
|
||||
return false ;
|
||||
}
|
||||
// --- se più superfici
|
||||
else {
|
||||
// calcolo il Box complessivo
|
||||
BBox3d BBoxGlob ;
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// calcolo il Box della superficie
|
||||
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
|
||||
// aggiungo il Box a quello complessivo
|
||||
BBoxGlob.Add( BBoxSurf) ;
|
||||
}
|
||||
// definisco uno Zmap vuoto a partire dal Box
|
||||
BBoxGlob.Expand( dBoxExpansion) ;
|
||||
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
|
||||
return false ;
|
||||
// aggiungo tutte le superfici chiuse
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0 || ! Surf->IsClosed())
|
||||
continue ;
|
||||
if ( ! AddSurfTm( Surf))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh
|
||||
// L'idea è quella di creare uno ZMap vuoto a partire dal Box complessivo delle superfici TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol)
|
||||
{
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
|
||||
// definisco la tolleranza di espansione del Box per la creazione dellop ZMap
|
||||
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
|
||||
|
||||
// calcolo il Box complessivo
|
||||
BBox3d BBoxGlob ;
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// calcolo il Box della superficie
|
||||
BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ;
|
||||
// aggiungo il Box a quello complessivo
|
||||
BBoxGlob.Add( BBoxSurf) ;
|
||||
}
|
||||
// definisco uno Zmap vuoto a partire dal Box
|
||||
BBoxGlob.Expand( dBoxExpansion) ;
|
||||
return ( CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie aperta
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// da studiare...
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie chiusa
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// controlli sulla superficie
|
||||
if ( Surf == nullptr || ! Surf->IsClosed())
|
||||
return false ;
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
|
||||
// Assunzioni :
|
||||
// - Idea Generale di Offset
|
||||
// - Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
|
||||
// centro il vertice corrente)
|
||||
// - Su ogni lato viene definito un cilindro ( con raggio di base pari al valore di Offset
|
||||
// e asse definito dall'edge stesso)
|
||||
// - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
|
||||
// definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
|
||||
//
|
||||
// - Segno dell'Offset :
|
||||
// - Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
|
||||
// - Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
|
||||
//
|
||||
// - Semplificazione entità :
|
||||
// La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
|
||||
// "spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
|
||||
// calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
|
||||
// troppo i conti introducendo variabili angolari che non sommando tutte le parti.
|
||||
//
|
||||
|
||||
// definisco vettore di frame Locali alle 3 griglie
|
||||
FRAME3DVECTOR vFrGrid( 4) ;
|
||||
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
|
||||
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
|
||||
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
|
||||
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
|
||||
|
||||
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
|
||||
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
|
||||
// ----------------------- Cilindri e Sfere -----------------------
|
||||
// scorro gli Edge della superficie
|
||||
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
|
||||
// recupero lo spigolo
|
||||
int nV1, nV2, nF1, nF2 ; double dAng ;
|
||||
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
|
||||
// controllo se il cilindro serve
|
||||
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
|
||||
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
|
||||
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
|
||||
if ( dAng * dOffs < 0)
|
||||
continue ;
|
||||
// recupero le coordinate dei vertici
|
||||
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
|
||||
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
|
||||
// esprimo gli estremi nel riferimento della griglia
|
||||
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dal cilindro
|
||||
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
|
||||
return false ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dalla sfera
|
||||
if ( ! vbVert[nV1]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
if ( ! vbVert[nV2]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
vbVert[nV1] = true ;
|
||||
vbVert[nV2] = true ;
|
||||
}
|
||||
// ----------------------- Facce -----------------------
|
||||
// scorro tutte le facce definendo una superficie di estrusione
|
||||
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
|
||||
// recupero lo faccia
|
||||
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
|
||||
// recupero la normale della faccia
|
||||
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
|
||||
// definisco la superficie di estrusione
|
||||
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vPL[i].Translate( - abs( dOffs) * vtN) ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
vpCrvs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
// recupero la TriMesh di estrusione
|
||||
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
|
||||
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
// aggiorno gli spilloni
|
||||
if ( dOffs > 0.)
|
||||
AddSurfTm( pStmExtr) ;
|
||||
else
|
||||
SubtractSurfTm( pStmExtr) ;
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// [Fillet Thickening] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente
|
||||
// mediante una superficie generica (aperta o chiusa)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol)
|
||||
{
|
||||
// controlli sulla superficie
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
|
||||
// non inizializzo lo Zmap, semplicemente lavoro con facce, spigoli e vertici
|
||||
|
||||
// definisco vettore di frame Locali alle 3 griglie
|
||||
FRAME3DVECTOR vFrGrid( 4) ;
|
||||
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
|
||||
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
|
||||
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
|
||||
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
|
||||
|
||||
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
|
||||
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
|
||||
// ----------------------- Cilindri e Sfere -----------------------
|
||||
// scorro gli Edge della superficie
|
||||
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
|
||||
// recupero lo spigolo
|
||||
int nV1, nV2, nF1, nF2 ; double dAng ;
|
||||
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
|
||||
// recupero le coordinate dei vertici
|
||||
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
|
||||
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
|
||||
// esprimo gli estremi nel riferimento della griglia
|
||||
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dal cilindro
|
||||
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dalla sfera
|
||||
if ( ! vbVert[nV1]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP1, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
}
|
||||
if ( ! vbVert[nV2]) {
|
||||
if ( ! CreateOffsSphereOnVertex( ptP2, abs( dOffs), nGrid))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
vbVert[nV1] = true ;
|
||||
vbVert[nV2] = true ;
|
||||
}
|
||||
// ----------------------- Facce -----------------------
|
||||
// scorro tutte le facce definendo una superficie di estrusione
|
||||
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
|
||||
// recupero lo faccia
|
||||
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
|
||||
// recupero la normale della faccia
|
||||
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
|
||||
// definisco la superficie di estrusione
|
||||
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vPL[i].Translate( - abs( dOffs) * vtN) ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
vpCrvs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
// recupero la TriMesh di estrusione
|
||||
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
|
||||
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) {
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
// aggiorno gli spilloni
|
||||
AddSurfTm( pStmExtr) ;
|
||||
// dealloco le curve
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
delete ( vpCrvs[i]) ;
|
||||
vpCrvs[i] = nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da un
|
||||
// vettore di superfici TriMesh (aperte o chiuse).
|
||||
// Definizione :
|
||||
// - Lo Zmap di Offset ( positivo o negativo) di una superficie chiusa è automaticamente l'Offset stesso
|
||||
// - Lo Zmap di Offset ( positivo o negativo) di una superficie aperta è ????? ( da capire...)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
|
||||
{
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
@@ -159,142 +502,67 @@ VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, do
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
|
||||
// definisco lo Zmap di partenza a partire dalle superfici
|
||||
// se una sola superficie
|
||||
double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ;
|
||||
if ( int( vSurf.size()) == 1) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0)
|
||||
return true ;
|
||||
// definisco lo Zamp a partire dall'espansione del Box della superficie
|
||||
if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion))
|
||||
return false ;
|
||||
}
|
||||
// se più superfici
|
||||
else {
|
||||
// calcolo il Box complessivo delle superfici TriMesh
|
||||
BBox3d BBoxGlob ;
|
||||
for ( int i = 0 ; i < int( vSurf.size()) ; ++ i) {
|
||||
// controllo la validità della superficie
|
||||
if ( ! vSurf[i]->IsValid() || vSurf[i]->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// calcolo il Box della superficie
|
||||
BBox3d BBoxSurf ; vSurf[i]->GetLocalBBox( BBoxSurf) ;
|
||||
// aggiungo il Box a quello complessivo
|
||||
BBoxGlob.Add( BBoxSurf) ;
|
||||
}
|
||||
// definisco uno Zmap vuoto a partire dal Box
|
||||
BBoxGlob.Expand( dBoxExpansion) ;
|
||||
if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true))
|
||||
return false ;
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( ! AddSurfTm( Surf))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assunzioni :
|
||||
- Idea Generale di Offset
|
||||
- Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e
|
||||
centro il vertice corrente)
|
||||
- Su ogni lato viene definito un cilindro ( con raggio di pase pari al valore di Offset
|
||||
e asse definito dall'edge stesso)
|
||||
- Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono
|
||||
definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale)
|
||||
|
||||
- Segno dell'Offset :
|
||||
- Positivo ( si sommano gli intervalli corrisipondenti alle entità create)
|
||||
- Negativo ( si sottraggono gli intervalli corrispondenti alle enetità create)
|
||||
|
||||
- Semplificazione entità :
|
||||
La creazione di Sfere e Cilindri potrebbe essere resa più "corretta" definitendo solo
|
||||
"spicchi 3d" di sfera e "spicchi 3d" di cilindri. Dato che le operazioni di somma, sottrazioni e
|
||||
calcolo delle normali per gli spilloni sono elementari su queste figure, si rischia di appesantire
|
||||
troppo i conti introducendo variabili angolari che non sommando tutte le parti.
|
||||
*/
|
||||
|
||||
// definisco vettore di frame Locali alle 3 griglie
|
||||
FRAME3DVECTOR vFrGrid( 4) ;
|
||||
vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ;
|
||||
vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ;
|
||||
vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ;
|
||||
vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ;
|
||||
|
||||
// inizializzo lo Zmap di Offset a partire dalle superfici
|
||||
if ( ! InitVolZMapOffs( vSurf, dOffs, dTol))
|
||||
return false ;
|
||||
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// se superficie non valida, passo alla successiva
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
// definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere
|
||||
BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ;
|
||||
// ----------------------- Cilindri e Sfere -----------------------
|
||||
// scorro gli Edge della superficie
|
||||
for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) {
|
||||
// recupero lo spigolo
|
||||
int nV1, nV2, nF1, nF2 ; double dAng ;
|
||||
Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ;
|
||||
// controllo se il cilindro serve
|
||||
// NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici
|
||||
// durante questa iterazione; non significa che questa sfera non verrà mai creata...
|
||||
// Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti
|
||||
if ( dAng * dOffs < 0)
|
||||
continue ;
|
||||
// recupero le coordinate dei vertici
|
||||
Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ;
|
||||
Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ;
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) {
|
||||
// esprimo gli estremi nel riferimento della griglia
|
||||
ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dal cilindro
|
||||
if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid))
|
||||
// aggiorno lo ZMap
|
||||
if ( Surf->IsClosed()) {
|
||||
if ( nType == STMOFF_FILLET) {
|
||||
if ( ! UpdateVolZMapByClosedSurfFilletOffset( Surf, dOffs, dTol))
|
||||
return false ;
|
||||
// aggiungo/sottraggo gli intervalli definiti dalla sfera
|
||||
if ( ! vbVert[nV1]) {
|
||||
vbVert[nV1] = ( nGrid == 2) ;
|
||||
if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
if ( ! vbVert[nV2]) {
|
||||
vbVert[nV2] = ( nGrid == 2) ;
|
||||
if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ----------------------- Facce -----------------------
|
||||
// scorro tutte le facce definendo una superficie di estrusione
|
||||
for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) {
|
||||
// recupero lo faccia
|
||||
POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ;
|
||||
// recupero la normale della faccia
|
||||
Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ;
|
||||
// definisco la superficie di estrusione
|
||||
CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vPL[i].Translate( - abs( dOffs) * vtN) ;
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i]))
|
||||
return false ;
|
||||
vpCrvs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
// recupero la TriMesh di estrusione
|
||||
PtrOwner<ISurfTriMesh> pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ;
|
||||
if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0)
|
||||
return false ;
|
||||
// aggiorno gli spilloni
|
||||
if ( dOffs > 0.)
|
||||
AddSurfTm( pStmExtr) ;
|
||||
else
|
||||
SubtractSurfTm( pStmExtr) ;
|
||||
else {
|
||||
// --- LE SUPERFICI APERTE SONO PER ORA DISABILITATE ---
|
||||
}
|
||||
}
|
||||
m_nShape = OFFSET ; // OFFSET (?) ... per ora va bene così
|
||||
|
||||
m_nShape = OFFSET ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Funzione per la creazine di uno Zmap di Fat Offset a partire da un
|
||||
// vettore di superfici TriMesh (aperte o chiuse).
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType)
|
||||
{
|
||||
// controllo delle superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
if ( Surf == nullptr)
|
||||
return false ;
|
||||
}
|
||||
// verifica sul parametro di Offset ( coerente con Curve e FlatRegion)
|
||||
if ( abs( dOffs) < 10 * EPS_SMALL)
|
||||
return true ;
|
||||
// se non ho superfici, non faccio nulla
|
||||
if ( vSurf.empty())
|
||||
return true ;
|
||||
|
||||
// inizializzo lo Zmap di Offset a partire dalle superfici
|
||||
if ( ! InitVolZMapThickeningOffs( vSurf, dOffs, dTol))
|
||||
return false ;
|
||||
|
||||
// scorro le superfici
|
||||
for ( const ISurfTriMesh* Surf : vSurf) {
|
||||
// se superficie non valida, passo alla successiva
|
||||
if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0)
|
||||
continue ;
|
||||
|
||||
// aggiorno lo Zmap
|
||||
if ( nType == STMOFF_FILLET) {
|
||||
if ( ! UpdateVolZMapBySurfThickeningFilletOffset( Surf, dOffs, dTol))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
m_nShape = OFFSET ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+153
-153
@@ -25,7 +25,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
|
||||
Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
|
||||
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
|
||||
{
|
||||
// tento di aggiungere la curva
|
||||
@@ -35,7 +35,7 @@ Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
|
||||
Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
|
||||
: m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true)
|
||||
{
|
||||
// tento di aggiungere la superficie
|
||||
@@ -45,16 +45,16 @@ Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
Voronoi::~Voronoi( void)
|
||||
Voronoi::~Voronoi( void)
|
||||
{
|
||||
Clear() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::Clear( void)
|
||||
Voronoi::Clear( void)
|
||||
{
|
||||
// pulizia oggetto vroni
|
||||
// pulizia oggetto vroni
|
||||
if ( m_vroni != nullptr)
|
||||
delete m_vroni ;
|
||||
m_vroni = nullptr ;
|
||||
@@ -72,7 +72,7 @@ Voronoi::Clear( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddCurve( const ICurve* pCrv)
|
||||
Voronoi::AddCurve( const ICurve* pCrv)
|
||||
{
|
||||
if ( ! m_bAllowAdd)
|
||||
return false ;
|
||||
@@ -99,21 +99,21 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
if ( ! vtExtr.IsSmall())
|
||||
plPlane.Set( ptS, vtExtr) ;
|
||||
else
|
||||
plPlane.Set( ptS, Z_AX) ;
|
||||
plPlane.Set( ptS, Z_AX) ;
|
||||
}
|
||||
else {
|
||||
if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
if ( m_vpCrvs.empty()) {
|
||||
// se prima curva considerata assegno il frame al Voronoi
|
||||
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
||||
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
||||
}
|
||||
else {
|
||||
// altrimenti verifico sia complanare ad eventuali curve già presenti
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// creo una copia della curva e la porto in locale
|
||||
@@ -128,8 +128,8 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
return false ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
// aggiungo la curva in locale all'oggetto vroni
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
@@ -144,61 +144,61 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
BBox3d bBox ;
|
||||
pCrvLoc->GetLocalBBox( bBox) ;
|
||||
m_bBox.Add( bBox) ;
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
{
|
||||
if ( ! m_bAllowAdd)
|
||||
return false ;
|
||||
|
||||
if ( pSfr == nullptr)
|
||||
return false ;
|
||||
|
||||
|
||||
// recupero il piano
|
||||
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
|
||||
Vector3d vtN = pSfr->GetNormVersor() ;
|
||||
Vector3d vtN = pSfr->GetNormVersor() ;
|
||||
if ( m_vpCrvs.empty()) {
|
||||
// assegno il frame al Voronoi
|
||||
m_Frame.Set( ptCen, vtN) ;
|
||||
m_Frame.Set( ptCen, vtN) ;
|
||||
}
|
||||
else {
|
||||
// verifico sia complanare ad eventuali curve già presenti
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
return false ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
|
||||
// aggiungo le curve di loop
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
|
||||
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
|
||||
if ( IsNull( pCrvLoc))
|
||||
return false ;
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage())
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
// aggiorno il box complessivo
|
||||
BBox3d bBox ;
|
||||
Frame3d frSrf = m_Frame ;
|
||||
@@ -211,16 +211,16 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddCurveToVroni( const ICurve* pCrv)
|
||||
Voronoi::AddCurveToVroni( const ICurve* pCrv)
|
||||
{
|
||||
int nLoopId = m_vpCrvs.size() ;
|
||||
|
||||
// aggiungo il punto iniziale
|
||||
Point3d ptStart ;
|
||||
Point3d ptStart ;
|
||||
if ( ! pCrv->GetStartPoint( ptStart))
|
||||
return false ;
|
||||
int nCrv = m_vroni->HandlePnt( ptStart.x, ptStart.y, {nLoopId, 0}) ;
|
||||
|
||||
|
||||
// aggiungo la parte rimanente della curva
|
||||
switch ( pCrv->GetType()) {
|
||||
case CRV_LINE :
|
||||
@@ -229,7 +229,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
|
||||
case CRV_ARC :
|
||||
m_vpCrvs.emplace_back( pCrv->Clone()) ;
|
||||
return AddArcToVroni( GetCurveArc( pCrv), nCrv, nLoopId) ;
|
||||
case CRV_COMPO :
|
||||
case CRV_COMPO :
|
||||
return AddCompoToVroni( GetCurveComposite( pCrv), nCrv, nLoopId) ;
|
||||
case CRV_BEZIER :
|
||||
return AddBezierToVroni( GetCurveBezier( pCrv), nCrv, nLoopId) ;
|
||||
@@ -242,7 +242,7 @@ Voronoi::AddCurveToVroni( const ICurve* pCrv)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
|
||||
Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
|
||||
{
|
||||
if ( pLine == nullptr)
|
||||
return false ;
|
||||
@@ -250,7 +250,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
|
||||
// verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine
|
||||
if ( ! ptEnd.IsValid()) {
|
||||
if ( ! pLine->GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
m_vroni->AddSeg( &nVroniCrv, ptEnd.x, ptEnd.y, {nLoopId, nCrvId}) ;
|
||||
@@ -259,7 +259,7 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
|
||||
Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd)
|
||||
{
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
@@ -285,7 +285,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
|
||||
// verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc
|
||||
if ( ! ptEnd.IsValid()) {
|
||||
if ( ! pArc->GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ;
|
||||
}
|
||||
@@ -295,7 +295,7 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId)
|
||||
Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId)
|
||||
{
|
||||
if ( pCompo == nullptr)
|
||||
return false ;
|
||||
@@ -315,18 +315,18 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
|
||||
bool bClosed = pCopy->IsClosed() ;
|
||||
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
|
||||
Point3d ptForcedEnd = P_INVALID ;
|
||||
|
||||
|
||||
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
|
||||
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
|
||||
pCompo->GetStartPoint( ptForcedEnd) ;
|
||||
|
||||
|
||||
// aggiungo
|
||||
const ICurve* pCrv = pCopy->GetCurve( i) ;
|
||||
int nType = pCrv->GetType() ;
|
||||
if ( nType == CRV_LINE)
|
||||
AddLineToVroni( GetCurveLine( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
|
||||
else if ( nType == CRV_ARC)
|
||||
AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
|
||||
AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ;
|
||||
}
|
||||
|
||||
// aggiungo al vettore di curve
|
||||
@@ -341,7 +341,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
|
||||
{
|
||||
if ( pBezier == nullptr)
|
||||
return false ;
|
||||
|
||||
|
||||
// riconduco al caso di curva composita
|
||||
PtrOwner<CurveComposite> pCompo( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCompo))
|
||||
@@ -352,28 +352,28 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
|
||||
|
||||
Vector3d vtExtr ; pBezier->GetExtrusion( vtExtr) ;
|
||||
pCompo->SetExtrusion( vtExtr) ;
|
||||
|
||||
|
||||
return AddCompoToVroni( pCompo, nVroniCrv, nLoopId) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ICurve*
|
||||
Voronoi::GetCurve( int nId) const
|
||||
{
|
||||
// verifico validità indice
|
||||
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
|
||||
return nullptr ;
|
||||
return nullptr ;
|
||||
// ne faccio una copia
|
||||
ICurve* pCrv = m_vpCrvs[nId]->Clone() ;
|
||||
if ( pCrv == nullptr)
|
||||
return nullptr ;
|
||||
return nullptr ;
|
||||
// la porto nel riferimento globale
|
||||
pCrv->ToGlob( m_Frame) ;
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::GetVroniPlane( Plane3d& plPlane) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -383,13 +383,13 @@ Voronoi::GetVroniPlane( Plane3d& plPlane) const
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcVoronoi( int nBound)
|
||||
{
|
||||
{
|
||||
// se già stato calcolato con lo stesso bound non devo fare nulla
|
||||
if ( m_bVDComputed && nBound == m_nBound)
|
||||
return true ;
|
||||
|
||||
|
||||
// se già stato calcolato reset dei dati
|
||||
if ( m_bVDComputed)
|
||||
m_vroni->ResetVoronoiDiagram() ;
|
||||
@@ -398,9 +398,9 @@ Voronoi::CalcVoronoi( int nBound)
|
||||
m_nBound = max( nBound, VORONOI_STD_BOUND) ;
|
||||
|
||||
// calcolo
|
||||
m_bVDComputed = true ;
|
||||
m_bVDComputed = true ;
|
||||
string sTmp = "" ;
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -416,7 +416,7 @@ Voronoi::GetBisectorCurve( int i)
|
||||
int nType = m_vroni->GetBisectorType( i) ;
|
||||
|
||||
// linea
|
||||
if ( nType == BisectorType::LINE) {
|
||||
if ( nType == BisectorType::LINE) {
|
||||
// recupero i dati del bisettore da vroni
|
||||
Point3d ptS, ptE ;
|
||||
double dParS, dParE ;
|
||||
@@ -434,7 +434,7 @@ Voronoi::GetBisectorCurve( int i)
|
||||
pLine->SetTempParam( dParS, 0) ;
|
||||
pLine->SetTempParam( dParE, 1) ;
|
||||
pLine->ToGlob( m_Frame) ;
|
||||
return pLine ;
|
||||
return pLine ;
|
||||
}
|
||||
|
||||
// degenerate hyperellipse ( arco)
|
||||
@@ -454,20 +454,20 @@ Voronoi::GetBisectorCurve( int i)
|
||||
pArc->SetTempParam( dParS, 0) ;
|
||||
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
|
||||
pArc->ToGlob( m_Frame) ;
|
||||
return pArc ;
|
||||
return pArc ;
|
||||
}
|
||||
|
||||
|
||||
// bisettore generico
|
||||
else if ( nType != BisectorType::NONE) {
|
||||
// approssimo linearmente il bisettore
|
||||
int nPoints = m_vroni->GetApproxedBisectorPointsNbr( i) ;
|
||||
if ( nPoints < 2)
|
||||
return nullptr ;
|
||||
|
||||
|
||||
CurveComposite* pCompo = CreateBasicCurveComposite() ;
|
||||
if ( pCompo == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
|
||||
// verifico se devo leggere i punti del bisettore al contrario per averlo orientato dal parametro minore al maggiore
|
||||
bool bInvert = false ;
|
||||
double dPar1, dPar2 ;
|
||||
@@ -481,13 +481,13 @@ Voronoi::GetBisectorCurve( int i)
|
||||
m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ;
|
||||
pCompo->AddPoint( pt) ;
|
||||
int nCrvCount = 0 ;
|
||||
|
||||
|
||||
double dParPrev = dParS ;
|
||||
int j = bInvert ? nPoints - 2 : 1 ;
|
||||
while ( ( bInvert && j >= 0) || ( ! bInvert && j < nPoints)) {
|
||||
double dPar ;
|
||||
m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ;
|
||||
if ( pCompo->AddLine( pt)) {
|
||||
if ( pCompo->AddLine( pt)) {
|
||||
// setto i parametri sulla sottocurva
|
||||
pCompo->SetCurveTempParam( nCrvCount, dParPrev, 0) ;
|
||||
pCompo->SetCurveTempParam( nCrvCount, dPar, 1) ;
|
||||
@@ -501,7 +501,7 @@ Voronoi::GetBisectorCurve( int i)
|
||||
else
|
||||
j ++ ;
|
||||
}
|
||||
|
||||
|
||||
// setto parametri sulla curva
|
||||
pCompo->SetTempParam( dParS, 0) ;
|
||||
pCompo->SetTempParam( dParPrev, 1) ;
|
||||
@@ -521,12 +521,12 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
|
||||
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
|
||||
try {
|
||||
// verifico se necessario calcolo Voronoi
|
||||
if ( ! m_bVDComputed || nBound != m_nBound)
|
||||
CalcVoronoi( nBound) ;
|
||||
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// recupero la curva del bisettore
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
@@ -546,7 +546,7 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
{
|
||||
vCrvs.clear() ;
|
||||
@@ -561,21 +561,21 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
bRight = false ;
|
||||
else if ( nSide == WMAT_RIGHT)
|
||||
bLeft = false ;
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
if ( ! m_bVDComputed)
|
||||
CalcVoronoi() ;
|
||||
|
||||
// calcolo medial axis
|
||||
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// verifico se il lato appartiene al medial axis
|
||||
if ( m_vroni->IsWMATEdge( i)) {
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
@@ -590,7 +590,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
{
|
||||
vOffs.clear() ;
|
||||
@@ -603,29 +603,29 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
for ( auto pCrv : m_vpCrvs)
|
||||
vOffs.emplace_back( pCrv->Clone()) ;
|
||||
}
|
||||
|
||||
|
||||
// calcolo offset
|
||||
ICRVCOMPOPLIST OffsList ;
|
||||
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
|
||||
return false ;
|
||||
|
||||
return false ;
|
||||
|
||||
// sistemo le curve di offset calcolate con vroni
|
||||
for ( auto pCrv : OffsList) {
|
||||
|
||||
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
|
||||
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
|
||||
|
||||
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
|
||||
|
||||
|
||||
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
|
||||
|
||||
// eventuale inversione
|
||||
if ( dOffs > EPS_SMALL)
|
||||
vResult[i]->Invert() ;
|
||||
|
||||
|
||||
// sistemo il punto di inizio
|
||||
if ( vResult[i]->IsClosed())
|
||||
if ( vResult[i]->IsClosed())
|
||||
AdjustOffsetStart( vResult[i]) ;
|
||||
|
||||
// identifico i raccordi
|
||||
|
||||
// identifico i raccordi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0)
|
||||
IdentifyFillets( vResult[i], dOffs) ;
|
||||
|
||||
@@ -643,17 +643,17 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
if ( ! AdjustCurveFillets( vOffs, dOffs, nType)) {
|
||||
vOffs.clear() ;
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// porto nel frame globale
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; i++)
|
||||
vOffs[i]->ToGlob( m_Frame) ;
|
||||
vOffs[i]->ToGlob( m_Frame) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
{
|
||||
// calcola, se possibile, le curve di offset del valore richiesto come curve singole, andando a recuperare i tratti del
|
||||
@@ -667,22 +667,22 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
try {
|
||||
try {
|
||||
if ( ! m_bVDComputed)
|
||||
CalcVoronoi() ;
|
||||
|
||||
// individuo il lato richiesto
|
||||
// individuo il lato richiesto
|
||||
bool bLeft = ( dOffs < 0) ;
|
||||
bool bRight = ! bLeft ;
|
||||
bool bRight = ! bLeft ;
|
||||
for ( int i = 0 ; i < int( m_vpCrvs.size()) ; i++) {
|
||||
if ( ! m_vpCrvs[i]->IsClosed()) {
|
||||
// se è presente una curva aperta il medial axis deve essere fatto sia a destra sia a sinistra
|
||||
bLeft = true ;
|
||||
bRight = true ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
|
||||
int nSideRef = ( dOffs < 0 ? MDS_LEFT : MDS_RIGHT) ;
|
||||
|
||||
// seleziono le curve del medial axis aventi parametro costante pari all'offset richiesto
|
||||
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||
@@ -695,7 +695,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
m_vroni->GetBisectorParams( i, dParS, dParE) ;
|
||||
if ( abs( dParS - abs( dOffs)) < EPS_SMALL && abs( dParE - abs( dOffs)) < EPS_SMALL) {
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid()) {
|
||||
// se necessario verifico se dal lato corretto rispetto ai siti di riferimento
|
||||
if ( bLeft && bRight) {
|
||||
// recupero i siti di riferimento
|
||||
@@ -707,7 +707,7 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
pCrv->SetTempProp( nOrigCrv1, 1) ;
|
||||
int nSide = GetOffsetCurveSide( pCrv) ;
|
||||
if ( nSide != nSideRef)
|
||||
continue ;
|
||||
continue ;
|
||||
}
|
||||
if ( nOrigCrv2 != -1) {
|
||||
// verifico il lato rispetto al secondo sito
|
||||
@@ -716,18 +716,18 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
int nSide = GetOffsetCurveSide( pCrv) ;
|
||||
if ( nSide != nSideRef)
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
}
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// concateno le curve ottenute
|
||||
if ( vCrvs.size() == 1)
|
||||
vOffs.emplace_back( Release( vCrvs[0])) ;
|
||||
else if ( ! vCrvs.empty()) {
|
||||
else if ( ! vCrvs.empty()) {
|
||||
ChainCurves chainC ;
|
||||
chainC.Init( true, 10 * EPS_SMALL, int( vCrvs.size())) ;
|
||||
for ( int i = 0 ; i < int( vCrvs.size()) ; ++ i) {
|
||||
@@ -754,14 +754,14 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
vCrvs[nInd]->Invert() ;
|
||||
// aggiungo alla composita
|
||||
if ( ! pCrvCompo->AddCurve( Release( vCrvs[nInd])))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
if ( pCrvCompo->IsValid()) {
|
||||
pCrvCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
vOffs.emplace_back( Release( pCrvCompo)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
m_vroni->apiFreeBisectorBuffer() ;
|
||||
@@ -775,11 +775,11 @@ Voronoi::CalcSingleCurvesOffset( ICURVEPOVECTOR& vOffs, double dOffs)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
{
|
||||
// calcola i punti e le tangenti sui bisettori del medial axis in corrispondenza del valore di offset richiesto
|
||||
|
||||
|
||||
vResult.clear() ;
|
||||
|
||||
if ( abs( dOffs) < EPS_SMALL)
|
||||
@@ -792,12 +792,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
// verifico se necessario ricalcolo Voronoi
|
||||
UpdateVoronoi( dOffs) ;
|
||||
|
||||
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
|
||||
// indivudio lato medial axis per curve chiuse ( suppongo di chiamare la funzione dalla singola curva, quindi vale controllare
|
||||
// la chiusura solo sulla prima curva. Eventualmente da estendere)
|
||||
bool bLeft = true, bRight = true ;
|
||||
if ( m_vpCrvs[0]->IsClosed()) {
|
||||
bLeft = dOffs < 0 ;
|
||||
bRight = ! bLeft ;
|
||||
bRight = ! bLeft ;
|
||||
}
|
||||
|
||||
// calcolo medial axis
|
||||
@@ -826,12 +826,12 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
double dPar ;
|
||||
Point3d ptTemp ;
|
||||
Vector3d vtDir ;
|
||||
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||
return false ;
|
||||
vtDir.Normalize() ;
|
||||
|
||||
vResult.emplace_back( pt, vtDir) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettori
|
||||
@@ -846,23 +846,23 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids,
|
||||
bool bMergeOnlySameProps)
|
||||
{
|
||||
vCrvs.clear() ;
|
||||
|
||||
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
|
||||
// se offset nullo errore
|
||||
if ( abs( dOffs) < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
|
||||
ICRVCOMPOPLIST OffsList ;
|
||||
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
|
||||
return false ;
|
||||
|
||||
|
||||
// sistemo le curve di offset calcolate con vroni
|
||||
bool bClosed = m_vpCrvs[0]->IsClosed() ;
|
||||
for ( auto pCrvOffs : OffsList) {
|
||||
@@ -910,7 +910,7 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
{
|
||||
OffsList.clear() ;
|
||||
@@ -931,21 +931,21 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, true, true) ;
|
||||
|
||||
// recupero le curve di offset da vroni
|
||||
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
for ( int i = 0 ; i < nOffsCnt ; i++) {
|
||||
Point3d ptSChain = P_INVALID ;
|
||||
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
|
||||
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
|
||||
|
||||
for ( int j = 0 ; j < nCrvCnt ; j ++) {
|
||||
// recupero la sottocurva da vroni
|
||||
// recupero la sottocurva da vroni
|
||||
Point3d ptS, ptE, ptC ;
|
||||
int nType ;
|
||||
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
|
||||
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
|
||||
|
||||
if ( j == 0)
|
||||
pCrvOffs->AddPoint( ptS) ;
|
||||
pCrvOffs->AddPoint( ptS) ;
|
||||
|
||||
// se estremi coincidenti la curva va ignorata ( da vroni non possono arrivare circonferenze)
|
||||
// ma controllo se appartiene ad una catena di tratti infinitesimi
|
||||
@@ -954,7 +954,7 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
if ( ! AreSamePointApprox( ptSChain, ptE)) {
|
||||
if ( ! pCrvOffs->AddLine( ptE))
|
||||
return false ;
|
||||
ptSChain = P_INVALID ;
|
||||
ptSChain = P_INVALID ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -970,16 +970,16 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
if ( ! pCrvOffs->AddLine( ptE))
|
||||
return false ;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
|
||||
if ( ! pArc->SetC2P( ptC, ptS, ptE)) {
|
||||
// se raggio minore di EPS_SMALL approssimo con linea
|
||||
if ( AreSamePointApprox( ptC, ptS)) {
|
||||
if ( ! pCrvOffs->AddLine( ptE))
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
else {
|
||||
// verifico orientamento
|
||||
@@ -988,25 +988,25 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
pArc->ToExplementary() ;
|
||||
// aggiungo alla composita
|
||||
if ( ! pCrvOffs->AddCurve( Release( pArc)))
|
||||
return false ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// setto come info la sottocurva da cui si è generata
|
||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
|
||||
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
|
||||
// aperta e chiusa)
|
||||
if ( nOrigCrv == -1) {
|
||||
int nOrigCrvCnt = 1 ;
|
||||
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
|
||||
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
|
||||
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
|
||||
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
|
||||
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
|
||||
@@ -1014,8 +1014,8 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
|
||||
// aggiungo la curva alla lista degli offset
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
|
||||
// libero la memoria di vroni dedicata agli offset
|
||||
m_vroni->apiFreeOffsetData() ;
|
||||
@@ -1029,11 +1029,11 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::UpdateVoronoi( double dOffs)
|
||||
{
|
||||
// calcolo il bound necessario per l'offset desiderato
|
||||
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
|
||||
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
|
||||
if ( ! m_bVDComputed || dNeededBound > m_nBound) {
|
||||
// aggiorno il valore del bound
|
||||
int nBound = ( int)( ceil( dNeededBound) + 0.5) ;
|
||||
@@ -1045,9 +1045,9 @@ Voronoi::UpdateVoronoi( double dOffs)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICRVCOMPOPOVECTOR
|
||||
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
{
|
||||
ICRVCOMPOPOVECTOR
|
||||
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
{
|
||||
ICRVCOMPOPOVECTOR vResult ;
|
||||
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
|
||||
|
||||
@@ -1065,13 +1065,13 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
// controllo la curva complessiva
|
||||
int nSide = GetOffsetCurveSide( pCompo->GetCurve( 0)) ;
|
||||
if ( nSide == nSideRef)
|
||||
vResult.emplace_back( pCompo->Clone()) ;
|
||||
vResult.emplace_back( pCompo->Clone()) ;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
// scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato
|
||||
PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ;
|
||||
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
|
||||
bool bKeep = true ;
|
||||
bool bKeep = true ;
|
||||
double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ;
|
||||
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
|
||||
bKeep = false ;
|
||||
@@ -1087,8 +1087,8 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
if ( pCompoCurr->IsValid()) {
|
||||
vResult.emplace_back( Release( pCompoCurr)) ;
|
||||
pCompoCurr.Set( CreateBasicCurveComposite()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// salvo eventuale ultima curva
|
||||
if ( pCompoCurr->IsValid())
|
||||
@@ -1102,17 +1102,17 @@ Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
vResult.pop_back() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return vResult ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int
|
||||
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
|
||||
{
|
||||
int
|
||||
Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
|
||||
{
|
||||
if ( pCrv == nullptr)
|
||||
return -1 ;
|
||||
|
||||
|
||||
Point3d ptM ; pCrv->GetMidPoint( ptM) ;
|
||||
|
||||
// recupero curva e sottocurva di riferimento dalle temp prop
|
||||
@@ -1121,8 +1121,8 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
|
||||
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
|
||||
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
|
||||
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
|
||||
if ( pCompoOrig != nullptr)
|
||||
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
|
||||
if ( pCompoOrig != nullptr)
|
||||
pCrvRef = pCompoOrig->GetCurve( nOrigSubCrv - 1) ;
|
||||
}
|
||||
|
||||
DistPointCurve distPC( ptM, *pCrvRef) ;
|
||||
@@ -1132,9 +1132,9 @@ Voronoi::GetOffsetCurveSide( const ICurve* pCrv) const
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
{
|
||||
bool
|
||||
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
{
|
||||
for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) {
|
||||
// cerco il tratto associato alla prima sottocurva originale
|
||||
int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ;
|
||||
@@ -1154,15 +1154,15 @@ Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::Translate( const Vector3d & vtMove)
|
||||
{
|
||||
Voronoi::Translate( const Vector3d & vtMove)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.Translate( vtMove) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -1171,7 +1171,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -1180,7 +1180,7 @@ Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::ToGlob( const Frame3d& frRef)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -1189,7 +1189,7 @@ Voronoi::ToGlob( const Frame3d& frRef)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::ToLoc( const Frame3d& frRef)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -1198,7 +1198,7 @@ Voronoi::ToLoc( const Frame3d& frRef)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
@@ -1207,7 +1207,7 @@ Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
bool
|
||||
Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
|
||||
{
|
||||
if ( nCrv < 0 || nCrv > int( m_vpCrvs.size()) - 1)
|
||||
@@ -1221,14 +1221,14 @@ Voronoi::CalcLimitOffset( int nCrv, bool bLeft, double& dOffs)
|
||||
// verifico se necessario calcolo Voronoi
|
||||
if ( ! m_bVDComputed)
|
||||
CalcVoronoi() ;
|
||||
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// verifico se è un bisettore relativo alla curva richiesta e dal lato opportuno
|
||||
if ( m_vroni->IsRelatedEdge( i, nCrv, bLeft)) {
|
||||
// calcolo i parametri del bisettore
|
||||
double dParS, dParE ;
|
||||
m_vroni->GetBisectorParams( i, dParS, dParE) ;
|
||||
dOffs = max( { dParS, dParE, dOffs}) ;
|
||||
dOffs = max( { dParS, dParE, dOffs}) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user