Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f79def16c | |||
| a4f0a43273 | |||
| 6646aee01c | |||
| 7f8382f1b8 | |||
| 4bcdb03598 | |||
| 68e9be7901 | |||
| 9e3bac4a68 | |||
| 1fee7b8e49 | |||
| f668d7ac11 | |||
| 4a1c13154f | |||
| 68a9848748 | |||
| f5059166ed | |||
| ad7f209fc9 | |||
| 8b5bfb6e19 | |||
| 1efd17f6ee | |||
| b8caeb49e0 | |||
| a9fc259745 | |||
| bbc98fe282 | |||
| a445ddd89b | |||
| e874b2eb36 | |||
| a45faa4793 | |||
| 344f0da7ff | |||
| cea869c6ee | |||
| 8ad2887c38 | |||
| 2b1d2a512d | |||
| a55770d702 | |||
| 2e4b1cdd40 | |||
| 3ffc0b40d8 | |||
| cd2cde40da | |||
| efc656a72c | |||
| e1eb139aee | |||
| e7d25b2d0e | |||
| ce05ce577c | |||
| ae2cac48d1 | |||
| 37e9a05347 | |||
| 02cb8a0d3c | |||
| 6942f5fc23 | |||
| 6c4bf3f05a | |||
| 4bc8590ce9 | |||
| 5b68e33d1f | |||
| a70f7ee9c9 | |||
| 95a070413a | |||
| 223489e80d | |||
| f6a535d94c | |||
| dbc3e7d2bf | |||
| b3ebb35d01 |
+2
-4
@@ -2440,12 +2440,10 @@ CAvDiskTriangle( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDis
|
||||
// Allontanamento dall'interno
|
||||
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
|
||||
// Allontanamento dalla frontiera
|
||||
Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ;
|
||||
Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ;
|
||||
vtMoveOrt.Normalize() ;
|
||||
Frame3d DiskFrame ;
|
||||
Vector3d vtJ = vtDiskAx ^ vtMoveOrt ;
|
||||
vtJ.Normalize() ;
|
||||
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
|
||||
DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ;
|
||||
Triangle3d trTriaLoc = trTria ;
|
||||
Vector3d vtMoveLoc = vtMove ;
|
||||
trTriaLoc.ToLoc( DiskFrame) ;
|
||||
|
||||
+238
-119
@@ -146,7 +146,7 @@ GetMaxFeed( const PocketParams& PockParams)
|
||||
static double
|
||||
GetMinFeed( const PocketParams& PockParams)
|
||||
{
|
||||
return PockParams.dFeed * PockParams.dSideStep / ( 2 * PockParams.dRad) ;
|
||||
return PockParams.dFeed * PockParams.dSideStep / ( 2. * PockParams.dRad) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -180,8 +180,8 @@ AssignMinFeed( ICurveComposite* pCrv, const PocketParams& PockParams)
|
||||
return false ;
|
||||
|
||||
// assegno la Feed minima ad ogni sottocurva di pCrv
|
||||
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
|
||||
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
|
||||
for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU)
|
||||
pCrv->SetCurveTempParam( nU, GetMinFeed( PockParams), 0) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -223,18 +223,19 @@ GetFeedForParam( double dPar, const PocketParams& PockParams, double& dFeed)
|
||||
GetSideStep() Diam
|
||||
*/
|
||||
|
||||
if ( dPar > PockParams.dRad * 2 || dPar < 0 ) // dominio...
|
||||
return false ;
|
||||
// dominio
|
||||
dPar = Clamp( dPar, 0., 2. * PockParams.dRad) ;
|
||||
|
||||
if ( PockParams.dRad * 2 - PockParams.dSideStep < 50 * EPS_SMALL) { // se la funzione è costante...
|
||||
dFeed = GetMaxFeed( PockParams) ; // non ho scelta ...
|
||||
// se la funzione si riduce ad un unico tratto costante
|
||||
if ( 2. * PockParams.dRad - PockParams.dSideStep < 50. * EPS_SMALL) {
|
||||
dFeed = GetMaxFeed( PockParams) ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti controllo in quale tratto lineare cade il parametro
|
||||
else {
|
||||
if ( PockParams.dSideStep < dPar + 50 * EPS_SMALL) { // se sono nel tratto lineare discendente ...
|
||||
// d/2 su parte discendente
|
||||
dFeed = GetFeed( PockParams) + ( GetFeed( PockParams) * ( 1 - ( PockParams.dSideStep / ( PockParams.dRad * 2)))) *
|
||||
( dPar - PockParams.dSideStep) / ( PockParams.dSideStep - ( PockParams.dRad * 2)) ;
|
||||
if ( PockParams.dSideStep < dPar + 50. * EPS_SMALL) {
|
||||
dFeed = GetFeed( PockParams) + ( GetFeed( PockParams) * ( 1. - ( PockParams.dSideStep / ( 2. * PockParams.dRad)))) *
|
||||
( dPar - PockParams.dSideStep) / ( PockParams.dSideStep - ( 2. * PockParams.dRad)) ;
|
||||
}
|
||||
else
|
||||
dFeed = GetMaxFeed( PockParams) ; // se sono nel tratto costante ...
|
||||
@@ -442,10 +443,9 @@ CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nSt
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdges,
|
||||
const PocketParams& PockParams)
|
||||
AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdges, const PocketParams& PockParams)
|
||||
{
|
||||
// NB. *pSfrOpenEdges deve essere una regione che all'esterno contiene i lati considerati aperti
|
||||
// NB. pSfrOpenEdges deve essere una regione che all'esterno contiene i lati considerati aperti
|
||||
// Solo ai tratti esterni vengono assegnate le Feed
|
||||
|
||||
// se non rischiesto il calcolo della Feed, lascio quella standard
|
||||
@@ -591,29 +591,28 @@ SimplifyCurveByFeeds( ICurveComposite* pCrvCompo, const PocketParams& PockParam,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, bool bIsLink,
|
||||
bool bFirstOffs, const ISurfFlatRegion* pSfrOpenEdges, const PocketParams& PockParams,
|
||||
double dToll)
|
||||
AssignFeedSpiral( ICurveComposite* pCompo, const ISurfFlatRegion* pSrfRemoved, bool bIsLink, bool bFirstOffs,
|
||||
const ISurfFlatRegion* pSfrOpenEdges, const PocketParams& PockParams, double dTol)
|
||||
{
|
||||
// controllo la validità della curva
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0)
|
||||
if ( pCompo == nullptr || ! pCompo->IsValid() || pCompo->GetCurveCount() == 0)
|
||||
return false ;
|
||||
|
||||
// controllo se il Flag per assegnare la Feed è attivo
|
||||
if ( ! PockParams.bCalcFeed)
|
||||
return AssignMaxFeed( pCrv, PockParams) ;
|
||||
return AssignMaxFeed( pCompo, PockParams) ;
|
||||
|
||||
// Se link di conformal ZigZag
|
||||
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG && bIsLink)
|
||||
return AssignMaxFeed( pCrv, PockParams) ;
|
||||
return AssignMaxFeed( pCompo, PockParams) ;
|
||||
|
||||
// imposto di Default la Feed minima per ogni sottocurva
|
||||
AssignMinFeed( pCrv, PockParams) ;
|
||||
AssignMinFeed( pCompo, PockParams) ;
|
||||
|
||||
// se non ho una superificie svuotata, allora esco ( con Feed Minima)
|
||||
if ( pSrfRemoved == nullptr || ! pSrfRemoved->IsValid() || pSrfRemoved->GetChunkCount() == 0) {
|
||||
// controllo eventuali sovrapposizioni con lati aperti
|
||||
return AssignFeedForOpenEdge( pCrv, pSfrOpenEdges, PockParams) ;
|
||||
return AssignFeedForOpenEdge( pCompo, pSfrOpenEdges, PockParams) ;
|
||||
}
|
||||
|
||||
// parametro di Offset per regione svuotata ( restringo la superficie in maniera appropriata)
|
||||
@@ -630,39 +629,39 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo
|
||||
|
||||
// classifico le parti interne alla superificie creata solo dagli Offset
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! pSrfRemovedOffs->GetCurveClassification( *pCrv, EPS_SMALL, ccClass))
|
||||
if ( ! pSrfRemovedOffs->GetCurveClassification( *pCompo, EPS_SMALL, ccClass))
|
||||
return true ; // esco ( sempre con Feed Minima)
|
||||
|
||||
// creo la nuova curva con le Feed regolate
|
||||
PtrOwner<ICurveComposite> pCrv_new( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrv_new))
|
||||
PtrOwner<ICurveComposite> pCompoNew( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCompoNew))
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) {
|
||||
// recupero il tratto di curva ricavato dalla classificazione
|
||||
PtrOwner<ICurveComposite> pCrv_sez( ConvertCurveToComposite( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ;
|
||||
if ( IsNull( pCrv_sez))
|
||||
PtrOwner<ICurveComposite> pSubCompo( ConvertCurveToComposite( pCompo->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ;
|
||||
if ( IsNull( pSubCompo))
|
||||
continue ; // curva troppo piccola, passo alla successiva
|
||||
// controllo se interno o fuori alla regione ( regolando quindi la Feed)
|
||||
double dCurrFeed = ( ccClass[i].nClass == CRVC_IN ? GetMaxFeed( PockParams) :
|
||||
GetMinFeed( PockParams)) ;
|
||||
// assegno tale Feed ad ogni sottocurva ricavata dal tratto di classificazione
|
||||
for ( int u = 0 ; u < pCrv_sez->GetCurveCount() ; ++ u)
|
||||
pCrv_sez->SetCurveTempParam( u, dCurrFeed, 0) ;
|
||||
for ( int nU = 0 ; nU < pSubCompo->GetCurveCount() ; ++ nU)
|
||||
pSubCompo->SetCurveTempParam( nU, dCurrFeed, 0) ;
|
||||
// aggiungo la nuova curva con la Feed regolata a quella finale
|
||||
pCrv_new->AddCurve( Release( pCrv_sez)) ;
|
||||
pCompoNew->AddCurve( Release( pSubCompo)) ;
|
||||
}
|
||||
|
||||
// sotituisco con quanto calcolato
|
||||
pCrv->Clear() ;
|
||||
pCrv->AddCurve( Release( pCrv_new)) ;
|
||||
pCompo->Clear() ;
|
||||
pCompo->AddCurve( Release( pCompoNew)) ;
|
||||
|
||||
// cerco di uniformare i tratti ricavati
|
||||
if ( ! bIsLink) { // ---------------- NEL CASO DI OFFSET ----------------
|
||||
// creo un intervallo con tutte le Feed Minime
|
||||
Intervals IntMinFeed ;
|
||||
for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) {
|
||||
double dFeed ; pCrv->GetCurveTempParam( nU, dFeed, 0) ;
|
||||
if ( abs( dFeed - GetMinFeed( PockParams)) < 5 * EPS_SMALL)
|
||||
for ( int nU = 0 ; nU < pCompo->GetCurveCount() ; ++ nU) {
|
||||
double dFeed ; pCompo->GetCurveTempParam( nU, dFeed, 0) ;
|
||||
if ( abs( dFeed - GetMinFeed( PockParams)) < 5. * EPS_SMALL)
|
||||
IntMinFeed.Add( nU, nU + 1) ;
|
||||
}
|
||||
double dParS = EPS_SMALL ; double dParE = EPS_SMALL ;
|
||||
@@ -670,59 +669,59 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo
|
||||
Intervals IntMinFeed_noSmall ;
|
||||
bool bFound = IntMinFeed.GetFirst( dParS, dParE) ;
|
||||
while ( bFound) {
|
||||
PtrOwner<ICurve> pCrv_Crv( pCrv->CopyParamRange( dParS, dParE)) ;
|
||||
double dLen = EPS_SMALL ; pCrv_Crv->GetLength( dLen) ;
|
||||
if ( dLen > dToll + 5 * EPS_SMALL)
|
||||
PtrOwner<ICurve> pCrv( pCompo->CopyParamRange( dParS, dParE)) ;
|
||||
double dLen = EPS_SMALL ; pCrv->GetLength( dLen) ;
|
||||
if ( dLen > dTol + 5. * EPS_SMALL)
|
||||
IntMinFeed_noSmall.Add( dParS, dParE) ;
|
||||
bFound = IntMinFeed.GetNext( dParS, dParE) ;
|
||||
}
|
||||
for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) {
|
||||
for ( int nU = 0 ; nU < pCompo->GetCurveCount() ; ++ nU) {
|
||||
if ( ! IntMinFeed_noSmall.IsInside( nU + 0.5))
|
||||
pCrv->SetCurveTempParam( nU, GetMaxFeed( PockParams), 0) ;
|
||||
pCompo->SetCurveTempParam( nU, GetMaxFeed( PockParams), 0) ;
|
||||
}
|
||||
}
|
||||
else { // ---------------- NEL CASO DI LINK ----------------
|
||||
// le curve con lunghezza inferiore alla tolleranza vanno modificate
|
||||
for ( int j = 0 ; j < pCrv->GetCurveCount() ; ++ j) {
|
||||
for ( int j = 0 ; j < pCompo->GetCurveCount() ; ++ j) {
|
||||
double dLen = EPS_SMALL ;
|
||||
pCrv->GetCurve( j)->GetLength( dLen) ;
|
||||
if ( dLen < dToll + 5 * EPS_SMALL) {
|
||||
pCompo->GetCurve( j)->GetLength( dLen) ;
|
||||
if ( dLen < dTol + 5. * EPS_SMALL) {
|
||||
// se curva piccola, ricavo il tratto successivo lungo quanto il diametro
|
||||
double dLenStart ;
|
||||
pCrv->GetLengthAtParam( j, dLenStart) ;
|
||||
pCompo->GetLengthAtParam( j, dLenStart) ;
|
||||
double dLenEnd = dLenStart + dLen + 2 * PockParams.dRad ;
|
||||
double dUE = pCrv->GetCurveCount() ;
|
||||
pCrv->GetParamAtLength( dLenEnd, dUE) ;
|
||||
double dUE = pCompo->GetCurveCount() ;
|
||||
pCompo->GetParamAtLength( dLenEnd, dUE) ;
|
||||
bool bFound = false ;
|
||||
for ( int k = j + 1 ; k < int( ceil( dUE)) ; ++ k) {
|
||||
double dLenH = EPS_SMALL ;
|
||||
pCrv->GetCurve( k)->GetLength( dLenH) ;
|
||||
if ( dLenH < dToll + 5 * EPS_SMALL)
|
||||
pCompo->GetCurve( k)->GetLength( dLenH) ;
|
||||
if ( dLenH < dTol + 5 * EPS_SMALL)
|
||||
continue ;
|
||||
// cerco tra le curve successive vicine se ne trovo una con Feed Minima
|
||||
double dParam ;
|
||||
pCrv->GetCurveTempParam( k, dParam, 0) ;
|
||||
if ( abs( dParam - GetMinFeed( PockParams)) < 5 * EPS_SMALL) {
|
||||
pCrv->SetCurveTempParam( k, dParam, 0) ;
|
||||
pCompo->GetCurveTempParam( k, dParam, 0) ;
|
||||
if ( abs( dParam - GetMinFeed( PockParams)) < 5. * EPS_SMALL) {
|
||||
pCompo->SetCurveTempParam( k, dParam, 0) ;
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( ! bFound && j != 0) {
|
||||
// arrivato qui, so che successivamente non ho curve con Feed Minima vicine
|
||||
double dParam ; pCrv->GetCurveTempParam( j - 1, dParam, 0) ;
|
||||
if ( abs( dParam - GetMaxFeed( PockParams)) < 5 * EPS_SMALL)
|
||||
double dParam ; pCompo->GetCurveTempParam( j - 1, dParam, 0) ;
|
||||
if ( abs( dParam - GetMaxFeed( PockParams)) < 5. * EPS_SMALL)
|
||||
// se anche la precedente ha Feed Massima -> la curva u-esima è piccola ed Isolata
|
||||
pCrv->SetCurveTempParam( j, dParam, 0) ;
|
||||
pCompo->SetCurveTempParam( j, dParam, 0) ;
|
||||
}
|
||||
else
|
||||
pCrv->SetCurveTempParam( j, GetMinFeed( PockParams), 0) ;
|
||||
pCompo->SetCurveTempParam( j, GetMinFeed( PockParams), 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bFirstOffs)
|
||||
AssignFeedForOpenEdge( pCrv, pSfrOpenEdges, PockParams) ;
|
||||
AssignFeedForOpenEdge( pCompo, pSfrOpenEdges, PockParams) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -1017,6 +1016,13 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite*
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static double
|
||||
GetExtendPathLen( const PocketParams& PockParam)
|
||||
{
|
||||
return ( Clamp( 2. * PockParam.dRad - PockParam.dOpenEdgeRad, 0., PockParam.dRad) + PockParam.dOpenMinSafe) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams,
|
||||
@@ -1831,14 +1837,14 @@ AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr,
|
||||
Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ;
|
||||
vtStart.Invert() ;
|
||||
bool bIsStartExtended = false ;
|
||||
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsStartExtended))
|
||||
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, GetExtendPathLen( PockParams), bIsStartExtended))
|
||||
return false ;
|
||||
// se aperta, controllo la fine
|
||||
if ( ! bIsClosed) {
|
||||
// ricavo vettore tangente finale e provo ad estendere
|
||||
Vector3d vtEnd ; vCrvCompo[i]->GetEndDir( vtEnd) ;
|
||||
bool bIsEndExtended = false ;
|
||||
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsEndExtended))
|
||||
if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, GetExtendPathLen( PockParams), bIsEndExtended))
|
||||
return false ;
|
||||
if ( bIsEndExtended)
|
||||
break ;
|
||||
@@ -2411,7 +2417,7 @@ CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, dou
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
||||
if ( IsNull( pArc) || ! pArc->Set( ptCen, vtN, dOutRad))
|
||||
return false ;
|
||||
// cambio il punto inizile se necessario
|
||||
// cambio il punto iniziale se necessario
|
||||
if ( PockParams.ptStart.IsValid()) {
|
||||
double dUStart = 0. ;
|
||||
int nFlag = 0 ;
|
||||
@@ -2690,15 +2696,30 @@ IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& Pock
|
||||
bForced = true ;
|
||||
// se entrambe le basi sono aperte
|
||||
else if ( vnProps[nBase] == TEMP_PROP_OPEN_EDGE && vnProps[nSecondBase] == TEMP_PROP_OPEN_EDGE) {
|
||||
const ICurve* pCrvOpenBase = pCrvTrap->GetCurve( nBase) ;
|
||||
const ICurve* pCrvOpenSecondBase = pCrvTrap->GetCurve( nSecondBase) ;
|
||||
if ( pCrvOpenBase == nullptr || ! pCrvOpenBase->IsValid() ||
|
||||
pCrvOpenSecondBase == nullptr || ! pCrvOpenSecondBase->IsValid())
|
||||
return false ;
|
||||
double dLenOpenBase ; pCrvOpenBase->GetLength( dLenOpenBase) ;
|
||||
double dLenSecondOpenBase ; pCrvOpenSecondBase->GetLength( dLenSecondOpenBase) ;
|
||||
bForced = ( dLenOpenBase < dDiam + 10. * EPS_SMALL &&
|
||||
dLenSecondOpenBase < dDiam + 10. * EPS_SMALL) ;
|
||||
double dLenOpen = 0. ;
|
||||
for ( int i = 0 ; i < 4 ; ++ i) {
|
||||
if ( i == nBase || i == nSecondBase) {
|
||||
const ICurve* pCrvOpen = pCrvTrap->GetCurve( i) ;
|
||||
if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid())
|
||||
return false ;
|
||||
// essendo nei casi a trapezio, ho solo segmenti
|
||||
pCrvOpen->GetLength( dLenOpen) ;
|
||||
Vector3d vtDir ; pCrvOpen->GetStartDir( vtDir) ;
|
||||
vtDir *= dLenOpen ;
|
||||
const ICurve* pCrvClosePrev = pCrvTrap->GetCurve( ( i == 0 ? 3 : i - 1)) ;
|
||||
if ( pCrvClosePrev == nullptr || ! pCrvClosePrev->IsValid())
|
||||
return false ;
|
||||
const ICurve* pCrvCloseAft = pCrvTrap->GetCurve( ( i == 3 ? 0 : i + 1)) ;
|
||||
if ( pCrvCloseAft == nullptr || ! pCrvCloseAft->IsValid())
|
||||
return false ;
|
||||
// essendo un trapezio queste due direzioni me le aspetto parallele tra loro
|
||||
Vector3d vtDirPrev ; pCrvClosePrev->GetEndDir( vtDirPrev) ;
|
||||
Vector3d vtDirAft ; pCrvCloseAft->GetStartDir( vtDirAft) ;
|
||||
dLenOpen = min( { OrthoCompo( vtDir, vtDirPrev).Len(), OrthoCompo( vtDir, vtDirAft).Len(), dLenOpen}) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
bForced = ( dLenOpen < dDiam + TOL_TRAPEZOID) ;
|
||||
}
|
||||
// se alternate, non forzo
|
||||
else
|
||||
@@ -2724,14 +2745,14 @@ IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& Pock
|
||||
const ICurve* pCrvCloseAft = pCrvTrap->GetCurve( ( i == 3 ? 0 : i + 1)) ;
|
||||
if ( pCrvCloseAft == nullptr || ! pCrvCloseAft->IsValid())
|
||||
return false ;
|
||||
// essendo un trapezio queste due direzioni me le apsetto parallele tra loro
|
||||
// essendo un trapezio queste due direzioni me le aspetto parallele tra loro
|
||||
Vector3d vtDirPrev ; pCrvClosePrev->GetEndDir( vtDirPrev) ;
|
||||
Vector3d vtDirAft ; pCrvCloseAft->GetStartDir( vtDirAft) ;
|
||||
dLenOpen = min( { OrthoCompo( vtDir, vtDirPrev).Len(), OrthoCompo( vtDir, vtDirAft).Len(), dLenOpen}) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
bForced = ( dLenOpen < dDiam + 10. * EPS_SMALL) ;
|
||||
bForced = ( dLenOpen < dDiam + TOL_TRAPEZOID) ;
|
||||
}
|
||||
break ;
|
||||
// se tutto chiuso, è forzato
|
||||
@@ -2795,8 +2816,8 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr
|
||||
bool bBaseOpen = ( pCrvTrap->GetCurve( 0)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE ||
|
||||
pCrvTrap->GetCurve( 2)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) ;
|
||||
// controllo dimensioni della svuotatura
|
||||
if ( ! ( bBaseOpen && dPocketSize < dDiam + EPS_SMALL) &&
|
||||
abs( dPocketSize - dDiam) > EPS_SMALL) {
|
||||
if ( ! ( bBaseOpen && dPocketSize < dDiam + TOL_TRAPEZOID) &&
|
||||
abs( dPocketSize - dDiam) > EPS_SMALL + TOL_TRAPEZOID) {
|
||||
pCrvTrap->Clear() ;
|
||||
return true ;
|
||||
}
|
||||
@@ -3560,13 +3581,13 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
|
||||
|
||||
// calcolo percorso di svuotatura
|
||||
// se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale
|
||||
if ( ( bRealTrap && dMaxLarg > dDiam + 10. * EPS_SMALL) &&
|
||||
if ( ( bRealTrap && dMaxLarg > dDiam + TOL_TRAPEZOID) &&
|
||||
( ( ( vnProp[0] != TEMP_PROP_CLOSE_EDGE && vnProp[2] != TEMP_PROP_CLOSE_EDGE) &&
|
||||
( vnProp[3] == TEMP_PROP_CLOSE_EDGE && vnProp[1] == TEMP_PROP_CLOSE_EDGE) &&
|
||||
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)) ||
|
||||
( max( dLen0, dLen2) < 2. * dDiam + TOL_TRAPEZOID)) ||
|
||||
( ( vnProp[1] != TEMP_PROP_CLOSE_EDGE && vnProp[3] != TEMP_PROP_CLOSE_EDGE) &&
|
||||
( vnProp[0] == TEMP_PROP_CLOSE_EDGE && vnProp[2] == TEMP_PROP_CLOSE_EDGE) &&
|
||||
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)))) {
|
||||
( max( dLen0, dLen2) < 2. * dDiam + TOL_TRAPEZOID)))) {
|
||||
if ( ! SpecialAdjustTrapezoidSpiralForAngles( pMCrv, ( vnProp[0] == TEMP_PROP_CLOSE_EDGE), pCrvPocket, PockParams, ptRef)) {
|
||||
pMCrv->Clear() ;
|
||||
return false ;
|
||||
@@ -3767,7 +3788,7 @@ AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam,
|
||||
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsStartExtended = false ;
|
||||
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
|
||||
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, GetExtendPathLen( PockParam), bIsStartExtended))
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -3904,7 +3925,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
|
||||
pCrvRes->GetStartDir( vtMidOut) ;
|
||||
vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ;
|
||||
bool bIsExtended ;
|
||||
ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsExtended) ;
|
||||
ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, GetExtendPathLen( PockParam), bIsExtended) ;
|
||||
}
|
||||
// se invece lavorazione in SpiralOut, inverto il percorso
|
||||
else if ( PockParam.nType == POCKET_SPIRALOUT)
|
||||
@@ -4031,7 +4052,7 @@ GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockPara
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockParams, bool& bOutStart,
|
||||
GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockParams, const Point3d& ptEndPrec, bool& bOutStart,
|
||||
Point3d& ptStart, Vector3d& vtOut)
|
||||
{
|
||||
// controllo dei parametri
|
||||
@@ -4049,22 +4070,34 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
|
||||
pMyCrv = pCompo->GetNextCurve() ;
|
||||
}
|
||||
|
||||
// se ho un punto di riferimento, cambio il punto iniziale della curva, partendo da questa
|
||||
PtrOwner<ICurveComposite> pMyCompo( CloneCurveComposite( pCompo)) ;
|
||||
if ( IsNull( pMyCompo) || ! pMyCompo->IsValid())
|
||||
return false ;
|
||||
if ( ptEndPrec.IsValid()) {
|
||||
double dMinDistPar = 0. ;
|
||||
int nFlag = 0 ;
|
||||
DistPointCurve( ptEndPrec, *pMyCompo).GetParamAtMinDistPoint( 0., dMinDistPar, nFlag) ;
|
||||
if ( dMinDistPar > EPS_PARAM)
|
||||
pMyCompo->ChangeStartPoint( floor( dMinDistPar)) ;
|
||||
}
|
||||
|
||||
// richiedo lunghezza superiore a diametro utensile più doppio offset radiale
|
||||
double dRefLen = ( bAllOpen ? 0. : ( 2 * PockParams.dRad) + 2 * PockParams.dRadialOffset - EPS_SMALL) ;
|
||||
double dMaxLen = dRefLen ;
|
||||
// ciclo sulle singole curve
|
||||
bool bFound = false ;
|
||||
const ICurve* pPrevCrv = pCompo->GetLastCurve() ;
|
||||
bool bFound = false, bFirst = true ;
|
||||
const ICurve* pPrevCrv = pMyCompo->GetLastCurve() ;
|
||||
double dLenPrev = 0. ;
|
||||
if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE)
|
||||
pPrevCrv->GetLength( dLenPrev) ;
|
||||
const ICurve* pCrv = pCompo->GetFirstCurve() ;
|
||||
const ICurve* pCrv = pMyCompo->GetFirstCurve() ;
|
||||
while ( pCrv != nullptr) {
|
||||
// analizzo la curva successiva
|
||||
const ICurve* pNextCrv = pCompo->GetNextCurve() ;
|
||||
const ICurve* pNextCrv = pMyCompo->GetNextCurve() ;
|
||||
bool bNextOk = ( pNextCrv != nullptr) ;
|
||||
if ( ! bNextOk)
|
||||
pNextCrv = pCompo->GetFirstCurve() ;
|
||||
pNextCrv = pMyCompo->GetFirstCurve() ;
|
||||
double dLenNext = 0. ;
|
||||
if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE)
|
||||
pNextCrv->GetLength( dLenNext) ;
|
||||
@@ -4084,6 +4117,8 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
|
||||
dLenAgg += max( 0.4, vtEnd * vtNextStart) * dLenNext ;
|
||||
}
|
||||
}
|
||||
if ( ptEndPrec.IsValid() && bFirst)
|
||||
dLenAgg += 2. * ( dLenPrev + dLenNext) ;
|
||||
// entità corrente
|
||||
double dLen = 0 ;
|
||||
if ( pCrv->GetLength( dLen)) {
|
||||
@@ -4097,6 +4132,7 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
|
||||
( abs( ptTest.z - ptStart.z) < 100 * EPS_SMALL && ptTest.y < ptStart.y - 100 * EPS_SMALL)) {
|
||||
dMaxLen = max( dMaxLen, dLen + dLenAgg) ;
|
||||
ptStart = ptTest ;
|
||||
bOutStart = true ;
|
||||
// versore ortogonale verso l'esterno
|
||||
pCrv->GetMidDir( vtOut) ;
|
||||
vtOut.Rotate( Z_AX, 0, -1) ;
|
||||
@@ -4109,6 +4145,7 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
|
||||
// versore ortogonale verso l'esterno
|
||||
vtOut.Normalize() ;
|
||||
vtOut.Rotate( Z_AX, 0, -1) ;
|
||||
bOutStart = true ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
@@ -4120,6 +4157,7 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
|
||||
// vado alla successiva
|
||||
pPrevCrv = pCrv ;
|
||||
pCrv = ( bNextOk ? pNextCrv : nullptr) ;
|
||||
bFirst = false ;
|
||||
}
|
||||
|
||||
return bFound ;
|
||||
@@ -4585,7 +4623,7 @@ SetPtStartForPath( ICurveComposite* pCrvOffs, const PocketParams& PockParams, co
|
||||
}
|
||||
// se punto non trovato precedentemente, tento con una sottocurva OPEN generica
|
||||
if ( ! bMidOut) {
|
||||
if ( ! GetParamOnOpenCurve( pCrvOffs, PockParams, bMidOut, ptStart, vtMidOut))
|
||||
if ( ! GetParamOnOpenCurve( pCrvOffs, PockParams, ptEndPrec, bMidOut, ptStart, vtMidOut))
|
||||
return false ;
|
||||
}
|
||||
// se queste curve sono troppo corte, analizzo le parti uniformi
|
||||
@@ -5384,40 +5422,38 @@ GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVE
|
||||
return true ;
|
||||
|
||||
// controllo dei parametri
|
||||
if ( vFirstOffs.empty() || int( vOffs.size()) < int( vFirstOffs.size()))
|
||||
if ( vFirstOffs.empty() || ssize( vOffs) < ssize( vFirstOffs))
|
||||
return false ;
|
||||
pSfrUncleared->Clear() ;
|
||||
|
||||
// creo la regione esterna ( definita dalle curve di primo Offset)
|
||||
// NB. Questa regione è diversa dalla pSfrOrig :
|
||||
// - i tratti chiusi sono Offsettati di R + OffsR()
|
||||
// - i tratti aperti sono stati estesi all'esterno
|
||||
// - i tratti aperti sono stati estesi all'esterno di PockParams.dMaxOpenEdgeRad
|
||||
PtrOwner<ISurfFlatRegion> pSrfExtern( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSrfExtern))
|
||||
return false ;
|
||||
for ( int i = 0 ; i < int( vFirstOffs.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vFirstOffs) ; ++ i) {
|
||||
if ( i == 0)
|
||||
pSrfExtern->AddExtLoop( vFirstOffs[i]->Clone()) ;
|
||||
else {
|
||||
PtrOwner<ICurve> pCrvIntLoop( vFirstOffs[i]->Clone()) ;
|
||||
if ( IsNull( pCrvIntLoop) ||
|
||||
! pCrvIntLoop->Invert() ||
|
||||
! pSrfExtern->AddIntLoop( Release( pCrvIntLoop)))
|
||||
if ( IsNull( pCrvIntLoop) || ! pCrvIntLoop->Invert() || ! pSrfExtern->AddIntLoop( Release( pCrvIntLoop)))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// Offset di una piccola quantità, tutte le curve esterne a tale regione sono associate a lati aperti
|
||||
const double OPEN_OFFS_TOL = 1000. * EPS_SMALL ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrForOpenEdges( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfrForOpenEdges))
|
||||
return false ;
|
||||
if ( pSfrOrig != nullptr && pSfrOrig->IsValid()) {
|
||||
if ( ! pSfrForOpenEdges.Set( CloneSurfFlatRegion( pSfrOrig)) ||
|
||||
! pSfrForOpenEdges->Offset( 1000 * EPS_SMALL, ICurve::OFF_FILLET))
|
||||
return false ;
|
||||
! pSfrForOpenEdges->Offset( OPEN_OFFS_TOL, ICurve::OFF_FILLET))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// definisco la regione rimossa dall'utensile
|
||||
@@ -5425,11 +5461,10 @@ GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVE
|
||||
if ( IsNull( pSfrTool))
|
||||
return false ;
|
||||
|
||||
// creo un vettore che conterrà solamente i Link percorsi fino ad Ora
|
||||
// creo un vettore che conterrà solamente i Link percorsi fino ad ora
|
||||
// NB. Per SpiralOut devo scorrere le curva di Offset in maniera inversa
|
||||
bool bFollowOrder = ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_CONFORMAL_ZIGZAG) ;
|
||||
for ( int i = ( bFollowOrder ? 0 : int( vOffs.size()) - 1) ;
|
||||
( bFollowOrder ? i < int( vOffs.size()) : i >= 0 ) ;
|
||||
( bFollowOrder ? ++ i : -- i)) {
|
||||
for ( int i = ( bFollowOrder ? 0 : ssize( vOffs) - 1) ; ( bFollowOrder ? i < ssize( vOffs) : i >= 0) ; ( bFollowOrder ? ++ i : -- i)) {
|
||||
|
||||
// ================== OFFSET =============================
|
||||
// recupero le proprietà temporanee
|
||||
@@ -5445,14 +5480,15 @@ GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVE
|
||||
bFirstOffs = true ;
|
||||
else {
|
||||
Point3d ptStart ; vOffs[i]->GetStartPoint( ptStart) ;
|
||||
for ( int j = 0 ; j < int( vFirstOffs.size()) && ! bFirstOffs ; ++ j)
|
||||
bFirstOffs = vFirstOffs[j]->IsPointOn( ptStart, 100 * EPS_SMALL) ;
|
||||
for ( int j = 0 ; j < ssize( vFirstOffs) && ! bFirstOffs ; ++ j)
|
||||
bFirstOffs = vFirstOffs[j]->IsPointOn( ptStart, 100. * EPS_SMALL) ;
|
||||
}
|
||||
// calcolo gli intervalli di Feed per la curva di Offset
|
||||
if ( ! AssignFeedSpiral( vOffs[i], pSfrTool, false, bFirstOffs, pSfrForOpenEdges, PockParams, 2 * PockParams.dRad / 3))
|
||||
if ( ! AssignFeedSpiral( vOffs[i], pSfrTool, false, bFirstOffs, pSfrForOpenEdges, PockParams, 2. * PockParams.dRad / 3.))
|
||||
return false ;
|
||||
// aggiorno la superificie svuotata
|
||||
PtrOwner<ISurfFlatRegion> pSrfToolOffs( GetSurfFlatRegionFromFatCurve( vOffs[i]->Clone() , PockParams.dRad + 5 * EPS_SMALL, false, false, 10 * EPS_SMALL, false)) ;
|
||||
PtrOwner<ISurfFlatRegion> pSrfToolOffs( GetSurfFlatRegionFromFatCurve( vOffs[i]->Clone() , PockParams.dRad + 5. * EPS_SMALL,
|
||||
false, false, 10. * EPS_SMALL, false)) ;
|
||||
if ( ! IsNull( pSrfToolOffs)) {
|
||||
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
|
||||
pSfrTool.Set( pSrfToolOffs) ;
|
||||
@@ -5464,32 +5500,31 @@ GetUnclearedRegionAndSetFeed( const ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVE
|
||||
vOffs[i]->SetTempParam( dTempPar1, 1) ;
|
||||
|
||||
// ================= LINK ================================
|
||||
int nLink_Ind = ( bFollowOrder ? i + 1 : i) ;
|
||||
int nIndLink = ( bFollowOrder ? i + 1 : i) ;
|
||||
// ( Il primo link è nullo, infatti non vi è nessun raccordo per raggiungere il primo Offset)
|
||||
if ( nLink_Ind < int( vLinks.size()) && ! IsNull( vLinks[nLink_Ind]) &&
|
||||
vLinks[nLink_Ind]->IsValid()) {
|
||||
|
||||
if ( nIndLink < int( vLinks.size()) && ! IsNull( vLinks[nIndLink]) && vLinks[nIndLink]->IsValid()) {
|
||||
// recupero le proprietà temporanee
|
||||
int nProp0 = vLinks[nLink_Ind]->GetTempProp( 0) ;
|
||||
int nProp1 = vLinks[nLink_Ind]->GetTempProp( 1) ;
|
||||
int nProp0 = vLinks[nIndLink]->GetTempProp( 0) ;
|
||||
int nProp1 = vLinks[nIndLink]->GetTempProp( 1) ;
|
||||
// Feed
|
||||
PtrOwner<ICurveComposite> pCrvLink( ConvertCurveToComposite( vLinks[nLink_Ind]->Clone())) ;
|
||||
PtrOwner<ICurveComposite> pCrvLink( ConvertCurveToComposite( vLinks[nIndLink]->Clone())) ;
|
||||
// calcolo gli intervalli di Feed per la curva di Link
|
||||
if ( IsNull( pCrvLink) || ! pCrvLink->IsValid() ||
|
||||
! AssignFeedSpiral( pCrvLink, pSfrTool, true, false, pSfrForOpenEdges, PockParams, 2 * PockParams.dRad / 3))
|
||||
! AssignFeedSpiral( pCrvLink, pSfrTool, true, false, pSfrForOpenEdges, PockParams, 2. * PockParams.dRad / 3.))
|
||||
return false ;
|
||||
// aggiorno la regione svuotata
|
||||
PtrOwner<ISurfFlatRegion> pSfrToolLink( GetSurfFlatRegionFromFatCurve( pCrvLink->Clone(), PockParams.dRad + 10 * EPS_SMALL, false, false, 10 * EPS_SMALL, false)) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrToolLink( GetSurfFlatRegionFromFatCurve( pCrvLink->Clone(), PockParams.dRad + 10. * EPS_SMALL,
|
||||
false, false, 10. * EPS_SMALL, false)) ;
|
||||
if ( ! IsNull( pSfrToolLink)) {
|
||||
if ( ! pSfrTool->IsValid() || pSfrTool->GetChunkCount() == 0)
|
||||
pSfrTool.Set( pSfrToolLink) ;
|
||||
else
|
||||
pSfrTool->Add( *pSfrToolLink) ;
|
||||
}
|
||||
// risetto il Link come curva composita ...
|
||||
// Imposto il Link come Curva Composita
|
||||
pCrvLink->SetTempProp( nProp0, 0) ;
|
||||
pCrvLink->SetTempProp( nProp1, 1) ;
|
||||
vLinks[nLink_Ind].Set( pCrvLink) ;
|
||||
vLinks[nIndLink].Set( pCrvLink) ;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7194,7 +7229,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig,
|
||||
|
||||
bool bIsExtended = false ;
|
||||
if ( bSomeOpen)
|
||||
ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended) ;
|
||||
ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, GetExtendPathLen( PockParams), bIsExtended) ;
|
||||
|
||||
// inserisco le curve nel vettore
|
||||
vCrvCompoRes.emplace_back( Release( pMCrv)) ;
|
||||
@@ -7476,10 +7511,10 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsExtended = false ;
|
||||
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
|
||||
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false, GetExtendPathLen( PockParams), bIsExtended))
|
||||
return false ;
|
||||
vpCrvs[nU]->GetEndDir( vtRef) ;
|
||||
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
|
||||
if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, GetExtendPathLen( PockParams), bIsExtended))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
@@ -7702,10 +7737,10 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsExtended = false ;
|
||||
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
|
||||
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, GetExtendPathLen( PockParams), bIsExtended))
|
||||
return false ;
|
||||
pCrvSegCompo->GetEndDir( vtRef) ;
|
||||
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended))
|
||||
if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, GetExtendPathLen( PockParams), bIsExtended))
|
||||
return false ;
|
||||
}
|
||||
vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ;
|
||||
@@ -8658,7 +8693,7 @@ AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const IS
|
||||
for ( int j = 0 ; j <= MAXTRY ; ++ j) {
|
||||
if ( bOkStartExtension && bOkEndExtension)
|
||||
break ;
|
||||
double dDist = PockParams.dOpenMinSafe + j * ( PockParams.dRad / ( 1. * MAXTRY)) ;
|
||||
double dDist = PockParams.dOpenMinSafe + j * ( GetExtendPathLen( PockParams) / ( 1. * MAXTRY)) ;
|
||||
if ( ! bOkStartExtension) {
|
||||
if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanS, false, dDist, bOkStartExtension))
|
||||
return false ;
|
||||
@@ -9810,6 +9845,90 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsPocketingHole( const ISurfFlatRegion* pSfr, double dToolRad, double dRadialOffs, double dSideStep, int nType, int nLiType,
|
||||
double dLiTang, double dRatioSfrTool)
|
||||
{
|
||||
// verifico validità della superficie
|
||||
if ( pSfr == nullptr || ! pSfr->IsValid())
|
||||
return false ;
|
||||
|
||||
// la superficie deve avere un solo Chunk e non presentare isole
|
||||
if ( pSfr->GetChunkCount() != 1 && pSfr->GetLoopCount( 0) != 1)
|
||||
return false ;
|
||||
|
||||
// porto la superficie nel suo riferimento intrinseco, quindi lavoro nel piano XY
|
||||
Point3d ptC ; pSfr->GetCentroid( ptC) ;
|
||||
Frame3d frXY ;
|
||||
if ( ! frXY.Set( ptC, pSfr->GetNormVersor()))
|
||||
return false ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrCL( CloneSurfFlatRegion( pSfr)) ;
|
||||
if ( IsNull( pSfrCL) || ! pSfrCL->IsValid() || ! pSfrCL->ToLoc( frXY))
|
||||
return false ;
|
||||
|
||||
// recupero l'unica curva di bordo che descrive la regione piana
|
||||
PtrOwner<ICurveComposite> pCrvBorder( ConvertCurveToComposite( pSfrCL->GetLoop( 0, 0))) ;
|
||||
if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid())
|
||||
return false ;
|
||||
pCrvBorder->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ;
|
||||
pCrvBorder->SetExtrusion( pSfrCL->GetNormVersor()) ; // Z_AX()
|
||||
|
||||
// verifico che le proprietà di lato Aperto/Chiuso siano uniformi
|
||||
bool bOkSpiral = true ;
|
||||
const ICurve* pFirstCrv = pCrvBorder->GetCurve( 0) ;
|
||||
if ( pFirstCrv == nullptr || ! pFirstCrv->IsValid())
|
||||
return false ;
|
||||
int nTmpPropRef = pFirstCrv->GetTempProp( 0) ;
|
||||
for ( int nU = 1 ; bOkSpiral && nU < pCrvBorder->GetCurveCount() ; ++ nU) {
|
||||
const ICurve* pCrv = pCrvBorder->GetCurve( nU) ;
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid())
|
||||
return false ;
|
||||
bOkSpiral = ( pCrv->GetTempProp( 0) == nTmpPropRef) ;
|
||||
}
|
||||
if ( ! bOkSpiral)
|
||||
return false ;
|
||||
|
||||
// definisco i parametri di una lavorazione Standard ( solo quelli utili per una svuotatura di un foro)
|
||||
PocketParams PockParam ;
|
||||
PockParam.dRad = dToolRad ;
|
||||
PockParam.dRadialOffset = dRadialOffs ;
|
||||
PockParam.dSideStep = dSideStep ;
|
||||
PockParam.ptStart = P_INVALID ;
|
||||
PockParam.bCalcFeed = false ;
|
||||
PockParam.nType = nType ;
|
||||
PockParam.nLiType = nLiType ;
|
||||
PockParam.dLiTang = dLiTang ;
|
||||
|
||||
// controllo che il Loop sia una circonferenza
|
||||
Point3d ptCen ; double dRad ;
|
||||
if ( ! OptimizedSpiralCircle( pCrvBorder, 50. * EPS_SMALL, dRad, ptCen, bOkSpiral) || ! bOkSpiral)
|
||||
return false ;
|
||||
double dOffs = PockParam.dRad + PockParam.dRadialOffset ;
|
||||
// se curva tutta Open, ingrandisco il raggio della circonferenza trovata
|
||||
if ( nTmpPropRef == TEMP_PROP_OPEN_EDGE)
|
||||
dRad += 1.05 * PockParam.dRad + PockParam.dRadialOffset ;
|
||||
// se curva chiusa, controllo che il raggio sia compatibile con il primo Offset
|
||||
else
|
||||
bOkSpiral = ( dRad - dOffs > 10. * EPS_SMALL) ;
|
||||
if ( ! bOkSpiral)
|
||||
return false ;
|
||||
|
||||
// verifico di rispettare il Ratio
|
||||
if ( dRad > dRatioSfrTool * dToolRad + EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// verifico se l'entrata è compatibile con la geometria e calcolo un eventuale percorso
|
||||
double dIntRad = 0 ;
|
||||
if ( PockParam.nType == POCKET_SPIRALOUT && PockParam.nLiType == LEAD_IN_HELIX)
|
||||
dIntRad = min( 0.5 * min( PockParam.dLiTang, 2. * PockParam.dRad), dRad - dOffs) ;
|
||||
PtrOwner<ICurveComposite> pCrvRes( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvRes))
|
||||
return false ;
|
||||
bOkSpiral = CalcCircleSpiral( ptCen, pSfrCL->GetNormVersor(), dRad - dOffs, dIntRad, PockParam, pCrvRes) ;
|
||||
return ( bOkSpiral && pCrvRes->IsValid() && pCrvRes->GetCurveCount() > 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustZigZagPathTangentLinks( ICurveComposite* pCrvCompo)
|
||||
|
||||
+140
-5
@@ -25,19 +25,24 @@
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkCurveByInterp.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
#define SAVEAPPROX 0
|
||||
#define SAVECURVEPASSED 0
|
||||
#define SAVELINEARAPPROX 0
|
||||
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX
|
||||
#define SAVESYNCLINES 0
|
||||
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX || SAVESYNCLINES
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
static int nCrvPassed = 0 ;
|
||||
std::vector<IGeoObj*> VT ;
|
||||
std::vector<Color> VC ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
@@ -1595,8 +1600,10 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
|
||||
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, const Vector3d& vtStart, const Vector3d& vtEnd)
|
||||
{
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
#if SAVECURVEPASSED
|
||||
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ;
|
||||
@@ -1668,6 +1675,10 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
|
||||
VCT3DVECTOR vPrevDer ;
|
||||
VCT3DVECTOR vNextDer ;
|
||||
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
|
||||
if ( ! AreSameVectorExact(vtStart, V_NULL)) {
|
||||
vNextDer[0] = vtStart ;
|
||||
vPrevDer.back() = vtEnd ;
|
||||
}
|
||||
|
||||
int nOverSampling = ssize( vPntOverSampling) ;
|
||||
vParam.resize( nOverSampling) ;
|
||||
@@ -1718,7 +1729,11 @@ CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int
|
||||
// controllo l'errore effettivo campionando più finemente
|
||||
double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ;
|
||||
double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ;
|
||||
dErr = 0 ;
|
||||
Point3d ptStart0 ; pCrvOri->GetStartPoint( ptStart0) ;
|
||||
Point3d ptStart1 ; pCrvNew->GetStartPoint( ptStart1) ;
|
||||
Point3d ptEnd0 ; pCrvOri->GetEndPoint( ptEnd0) ;
|
||||
Point3d ptEnd1 ; pCrvNew->GetEndPoint( ptEnd1) ;
|
||||
dErr = max( Dist( ptStart1, ptStart0), Dist( ptEnd1, ptEnd0)) ;
|
||||
for ( int i = 1 ; i < nPoints ; ++i) {
|
||||
Point3d ptOri, ptNew ;
|
||||
double dParOri, dParNew ;
|
||||
@@ -2687,3 +2702,123 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
|
||||
double dLenPrev2, double& dLenCurr2, double dLen2)
|
||||
{
|
||||
Point3d ptCurr1 ;
|
||||
Vector3d vtCurr1 ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
// --- Piano di taglio per punto a minima distanza
|
||||
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
|
||||
int nIndParCloser = - 1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo) && aInfo.Ici[0].dU > dUPrev2) {
|
||||
if ( nIndParCloser == -1)
|
||||
nIndParCloser = nInfo ;
|
||||
double dSqDist = SqDist( ptCurr1, aInfo.Ici[0].ptI) ;
|
||||
if ( dSqDist < dSqMinDist) {
|
||||
dSqMinDist = dSqDist ;
|
||||
nIndPointCloser = nInfo ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurr2 = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurr2 = ( SqDist( ptCurr1, aInfoPt.Ici[0].ptI) < SqDist( ptCurr1, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
#if SAVESYNCLINES
|
||||
VT.clear() ; VC.clear() ;
|
||||
VT.emplace_back( pCrvEdge1->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
VT.emplace_back( pCrvEdge2->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
PtrOwner<IGeoPoint3d> ptCurr1Geo( CreateGeoPoint3d()) ; ptCurr1Geo->Set( ptCurr1) ;
|
||||
VT.emplace_back( Release( ptCurr1Geo)) ; VC.emplace_back( BLUE) ;
|
||||
PtrOwner<IGeoPoint3d> ptPar( CreateGeoPoint3d()) ; ptPar->Set( aInfoPar.Ici[0].ptI) ;
|
||||
PtrOwner<IGeoPoint3d> ptPt( CreateGeoPoint3d()) ; ptPt->Set( aInfoPt.Ici[0].ptI) ;
|
||||
VT.emplace_back( Release( ptPar)) ; VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( Release( ptPt)) ; VC.emplace_back( FUCHSIA) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\bezier\\ruled\\TestTrimmingPlane.nge") ;
|
||||
#endif
|
||||
}
|
||||
// Verifico di non essermi allontanato troppo
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkPlane = ( dLen < dLenPrev2 + 2. * dMyDist) ;
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( ptCurr1, *pCrvEdge2) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrev2, dUCurr2, nFlag) && dUCurr2 > dUPrev2) ;
|
||||
// Verifico di non essermi allontanato troppo
|
||||
if ( bOkMinDist) {
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkMinDist = ( dLen < dLenPrev2 + 2. * dMyDist) ;
|
||||
}
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Aumento la distanza corrente del passo di campionamento
|
||||
double dLen = Clamp( dLenPrev2 + dMyDist, 0., dLen2) ;
|
||||
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Recupero il punto corrente e la direzione tangente sul secondo bordo
|
||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
||||
Point3d ptCurr2 ;
|
||||
Vector3d vtCurr2 ;
|
||||
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
||||
vtCurr2.Normalize() ;
|
||||
|
||||
// Verifico se le direzioni tangenti sono tra di loro circa parallele
|
||||
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
|
||||
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
|
||||
double dSearchLen = dMyDist / 2 ;
|
||||
int NUM_STEP = 10 ;
|
||||
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
|
||||
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
|
||||
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
|
||||
dSearchLen = dMyDist ;
|
||||
NUM_STEP = 20 ;
|
||||
}
|
||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
|
||||
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
|
||||
|
||||
double dMin = INFINITO ;
|
||||
const double dCoeff = 0.1 ;
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
||||
double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ;
|
||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||
pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||
double dDist = Dist( ptCurr1, ptCurr2) ;
|
||||
double dVal = (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
|
||||
if ( dVal < dMin) {
|
||||
ptCurr2 = ptStep2 ;
|
||||
vtCurr2 = vtStep2 ;
|
||||
dUCurr2 = dUStep2 ;
|
||||
dMin = dVal ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+1
-1
@@ -35,4 +35,4 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
+166
-1
@@ -1967,7 +1967,120 @@ CurveComposite::AddJoint( double dU)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol)
|
||||
{
|
||||
int nCrvCount = GetCurveCount() ;
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
// salvo le vecchie curve e nel caso le ripristino
|
||||
int nPrevCrv = -1 ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
if ( nU >= 0)
|
||||
nPrevCrv = nU - 1 ;
|
||||
else if ( IsClosed())
|
||||
nPrevCrv = nCrvCount - 1 ;
|
||||
PtrOwner<CurveComposite> pOrigCrv( CreateBasicCurveComposite()) ;
|
||||
if ( nPrevCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nPrevCrv]->Clone()) ;
|
||||
// recupero il puntatore alla curva successiva (se esiste)
|
||||
int nNextCrv = -1 ;
|
||||
if ( nU < nCrvCount)
|
||||
nNextCrv = nU ;
|
||||
else if ( IsClosed())
|
||||
nNextCrv = 0 ;
|
||||
else
|
||||
nNextCrv = - 1 ;
|
||||
if ( nNextCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
|
||||
|
||||
int nCrvNmbr = GetCurveCount() ;
|
||||
int nFlagDel = DeletedCurve::NONE ;
|
||||
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
|
||||
return false ;
|
||||
|
||||
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
|
||||
bool bErasedPrev = ( nFlagDel == DeletedCurve::PREV) ;
|
||||
bool bErasedNext = ( nFlagDel == DeletedCurve::NEXT) ;
|
||||
if ( ( bErasedPrev && nNextCrv == -1) || ( bErasedNext && nPrevCrv == -1)) {
|
||||
// se sono su un estremo di una curva aperta e ho cancellato la sottocurva di estremità devo verificare che fosse più piccola della tolleranza
|
||||
if ( bErasedPrev && nNextCrv == -1) {
|
||||
Point3d ptOrigEnd ; pOrigCrv->GetEndPoint( ptOrigEnd) ;
|
||||
Point3d ptNewEnd ; GetEndPoint( ptNewEnd) ;
|
||||
if ( Dist( ptOrigEnd, ptNewEnd) > dTol)
|
||||
m_CrvSmplS.push_back( Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
if ( bErasedNext && nPrevCrv == -1) {
|
||||
Point3d ptOrigStart ; pOrigCrv->GetStartPoint( ptOrigStart) ;
|
||||
Point3d ptNewStart ; GetStartPoint( ptNewStart) ;
|
||||
if ( Dist( ptOrigStart, ptNewStart) > dTol)
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin(), Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
double dStart ;
|
||||
double dEnd ;
|
||||
if ( bErasedPrev) {
|
||||
dStart = nU ;
|
||||
dEnd = nNextCrv + 1 ;
|
||||
}
|
||||
else if ( bErasedNext) {
|
||||
dStart = nPrevCrv ;
|
||||
dEnd = nU ;
|
||||
if ( nU == 0)
|
||||
dStart -= 1 ;
|
||||
}
|
||||
else { // ! bErasedSomeCrv
|
||||
dStart = ( nPrevCrv != -1 ? nPrevCrv : 0) ;
|
||||
dEnd = ( nNextCrv != -1 ? nNextCrv + 1 : nCrvNmbr) ;
|
||||
}
|
||||
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
|
||||
double dErr = 0 ;
|
||||
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr, 6) || dErr > dTol) {
|
||||
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
|
||||
if ( ! bErasedSomeCrv) {
|
||||
if ( nNextCrv != -1) {
|
||||
delete m_CrvSmplS[nNextCrv] ;
|
||||
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
if ( nPrevCrv != -1) {
|
||||
delete m_CrvSmplS[nPrevCrv] ;
|
||||
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( bErasedNext) {
|
||||
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
|
||||
nPos = 0 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
else {
|
||||
int nPos = nU == 0 ? nU : nPrevCrv ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
nPos = nCrvNmbr - 1 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1977,6 +2090,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NONE ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
int nPrevCrv = -1 ;
|
||||
if ( nU > 0)
|
||||
@@ -2005,6 +2120,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
|
||||
delete pPrevCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::PREV ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -2024,6 +2141,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
|
||||
delete pNextCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NEXT ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -3858,3 +3977,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
ptStart = m_ptStart ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
|
||||
{
|
||||
// prendo il possesso e verifico la curva
|
||||
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
|
||||
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
|
||||
return false ;
|
||||
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico l'indice sia sensato
|
||||
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
|
||||
return false ;
|
||||
|
||||
// verifico che start e end coincidano entro la tolleranza
|
||||
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
|
||||
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
|
||||
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
|
||||
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
|
||||
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
|
||||
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
|
||||
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se presente una tolleranza lungo la curva controllo che sia rispettata
|
||||
if ( dTolAlong < INFINITO) {
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
|
||||
if ( dErr > dTolAlong)
|
||||
return false ;
|
||||
}
|
||||
|
||||
delete m_CrvSmplS[nSubCrv] ;
|
||||
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
+8
-1
@@ -26,6 +26,9 @@ class Voronoi ;
|
||||
//----------------------------------------------------------------------------
|
||||
class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
{
|
||||
public :
|
||||
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
|
||||
|
||||
public : // IGeoObj
|
||||
~CurveComposite( void) override ;
|
||||
CurveComposite* Clone( void) const override ;
|
||||
@@ -156,7 +159,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddJoint( double dU) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override
|
||||
{ return ModifyJoint( nU, ptNewJoint, nullptr) ; }
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
|
||||
bool RemoveJoint( int nU) override ;
|
||||
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
|
||||
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
|
||||
@@ -178,6 +183,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ;
|
||||
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -211,6 +217,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
|
||||
|
||||
Binary file not shown.
@@ -573,6 +573,9 @@
|
||||
<ClCompile Include="CAvSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
||||
@@ -198,13 +198,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// se coincidono U e ptInt tra A e B
|
||||
if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL &&
|
||||
AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) {
|
||||
// se non è alla fine di curva chiusa
|
||||
if ( ! bCrvAClosed || abs( m_Info[j].IciA[0].dU - dCrvBSpan) > EPS_SMALL)
|
||||
// elimino la seconda
|
||||
EraseOtherInfo( i, j) ;
|
||||
else
|
||||
// elimino la prima
|
||||
// se j è alla fine di curva chiusa
|
||||
// se j è alla fine di curva chiusa e la prima intersezione è di overlap con partenza dall'inizio ( compreso nel caso precedente)
|
||||
// oppure se i è all'inizio di curva chiusa e l'intersezione successiva a j è di overlap con lo stesso parametro
|
||||
if ( bCrvAClosed && (( abs( m_Info[j].IciA[0].dU - dCrvBSpan) < EPS_SMALL) ||
|
||||
( i == 0 && ssize(m_Info) > 2 && m_Info[i].IciA[0].dU < EPS_SMALL && m_Info[j+1].bOverlap && abs( m_Info[j].IciA[0].dU - m_Info[j+1].IciA[0].dU) < EPS_SMALL)))
|
||||
// elimino la prima
|
||||
EraseCurrentInfo( i, j) ;
|
||||
else
|
||||
// elimino la seconda
|
||||
EraseOtherInfo( i, j) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -1991,17 +1991,11 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
|
||||
nAddedSpan = 0 ;
|
||||
nCrv1 = 0 ;
|
||||
nCrv2 = 0 ;
|
||||
bool bLast1 = false ;
|
||||
bool bLast2 = false ;
|
||||
while ( nAddedSpan < nPnt) {
|
||||
if ( nCrv1 >= nPnt1) {
|
||||
if ( nCrv1 >= nPnt1)
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
bLast1 = true ;
|
||||
}
|
||||
if ( nCrv2 >= nPnt2) {
|
||||
if ( nCrv2 >= nPnt2)
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bLast2 = true ;
|
||||
}
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
|
||||
|
||||
+172
-69
@@ -393,7 +393,7 @@ typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
|
||||
double dPar, Point5ax& Pt5ax)
|
||||
double dPar, bool bFromVsTo, Point5ax& Pt5ax)
|
||||
{
|
||||
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
@@ -402,23 +402,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla direzione
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la direzione
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,7 +480,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -521,7 +546,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -543,7 +568,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
@@ -558,23 +584,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dal punto
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso il punto
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,7 +663,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -663,7 +714,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -681,7 +732,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
@@ -699,23 +751,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla curva
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la curva
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,7 +815,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
@@ -754,7 +831,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// Sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -805,7 +882,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -823,7 +900,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, stmRef) ;
|
||||
@@ -850,23 +928,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla superficie
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la superficie
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -911,7 +1014,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -983,7 +1086,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
|
||||
+2
-2
@@ -735,7 +735,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double dSampleLen)
|
||||
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
@@ -762,7 +762,7 @@ GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double d
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen))
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
|
||||
+466
-218
@@ -52,11 +52,12 @@
|
||||
#define SAVEMATCHCURVES 0
|
||||
#define SAVEFAILEDTREE 0
|
||||
#define SAVELIMITSURF 0
|
||||
#define SAVEPACEDISO 1
|
||||
#define SAVEPACEDISO 0
|
||||
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES \
|
||||
|| SAVEFAILEDTREE || SAVELIMITSURF || SAVEPACEDISO
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
std::vector<Color> vCol ;
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
@@ -4501,55 +4502,6 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I
|
||||
return true ;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, BOOLVECTOR& vEdgeSplit)
|
||||
{
|
||||
int nPoints = PL.GetPointNbr() ;
|
||||
vEdgeSplit.clear() ;
|
||||
vEdgeSplit.resize( nPoints) ;
|
||||
fill( vEdgeSplit.begin(), vEdgeSplit.end(), false) ;
|
||||
bool bClosed = PL.IsClosed() ;
|
||||
// Recupero l'insieme di punti associati alla PolyLine
|
||||
PNTVECTOR vPoints ; vPoints.reserve( nPoints) ;
|
||||
Point3d ptCurr = P_INVALID ;
|
||||
// aggiungo come primo punto il penultimo punto della polyline in modo da analizzare direttamente anche la chiusura ( se è una polyline chiusa)
|
||||
PL.GetLastPoint( ptCurr) ;
|
||||
PL.GetPrevPoint( ptCurr) ;
|
||||
vPoints.emplace_back( ptCurr) ;
|
||||
bool bFound = PL.GetFirstPoint( ptCurr) ;
|
||||
while ( bFound) {
|
||||
vPoints.emplace_back( ptCurr) ;
|
||||
bFound = PL.GetNextPoint( ptCurr) ;
|
||||
}
|
||||
Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ;
|
||||
// cos della tolleranza angolare massima
|
||||
double dCosTol = cos( dAngTol * DEGTORAD) ;
|
||||
for ( int nP = 0 ; nP < nPoints - 2 ; ++ nP) {
|
||||
// Recupero il punto corrente e i due punti successivi
|
||||
Point3d& ptCurr = vPoints[nP] ;
|
||||
Point3d& ptNext = vPoints[nP + 1] ;
|
||||
Point3d& ptNextNext = vPoints[nP + 2] ;
|
||||
// Recupero i versori tangenti definiti dai tre punti ( ptCurr|ptNext e ptNext|ptNextNext)
|
||||
if ( nP == 0) {
|
||||
vtTanCurr = ptNext - ptCurr ;
|
||||
vtTanCurr.Normalize() ;
|
||||
}
|
||||
else
|
||||
vtTanCurr = vtTanNext ;
|
||||
vtTanNext = ptNextNext - ptNext ; vtTanNext.Normalize() ;
|
||||
// Calcolo il Coseno tra i due versori
|
||||
double dCos = vtTanCurr * vtTanNext ;
|
||||
// Se oltre la tolleranza allora ho incontrato un edge
|
||||
if ( dCos < dCosTol)
|
||||
vEdgeSplit[nP] = true ;
|
||||
}
|
||||
|
||||
if ( ! bClosed)
|
||||
vEdgeSplit[0] = false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetEdgeSplitByAngTol( const ICurveComposite* pCC, double dAngTol, BOOLVECTOR& vEdgeSplit)
|
||||
{
|
||||
@@ -5896,15 +5848,31 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Struttura per Spigolo
|
||||
struct SharpEdge {
|
||||
double dParU ;
|
||||
Point3d ptEdge ;
|
||||
Vector3d vtTanPrev, vtTanAft ;
|
||||
Vector3d vtTanPrev, vtTanNext ;
|
||||
SharpEdge( double dU, const Point3d ptE, const Vector3d& vtTP, const Vector3d& vtTA)
|
||||
: dParU( dU), ptEdge( ptE), vtTanPrev( vtTP), vtTanAft( vtTA) {}
|
||||
: dParU( dU), ptEdge( ptE), vtTanPrev( vtTP), vtTanNext( vtTA) {}
|
||||
} ;
|
||||
typedef vector<SharpEdge> SHARPEDGEVECTOR ;
|
||||
|
||||
// Struttura per Punto a Curvatura Massima
|
||||
struct CurvaturePoint {
|
||||
double dParU ;
|
||||
Point3d ptCurvature ;
|
||||
Vector3d vtTanPrev, vtTanNext ;
|
||||
CurvaturePoint( double dU, const Point3d ptE, const Vector3d& vtTP, const Vector3d& vtTA)
|
||||
: dParU( dU), ptCurvature( ptE), vtTanPrev( vtTP), vtTanNext( vtTA) {}
|
||||
} ;
|
||||
typedef vector<SharpEdge> SHARPEDGEVECTOR ;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Calcolo delle Curve di Sync tra gli spigoli di una curva e l'altra curva nella sua integrità
|
||||
// [Dato un vettore di SharpEdge di una Curva di Bordo si calcola la Linea di Sincronizzazione tra ognuno di essi
|
||||
// e l'altra Curva di Bordo]
|
||||
// -> Restituisce un vettore di Linee di Sincronizzazione
|
||||
static bool
|
||||
CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite* pCompoSubEdge, const SHARPEDGEVECTOR& vSharpSubEdge,
|
||||
BIPNTVECTOR& vSyncLines)
|
||||
@@ -5919,13 +5887,20 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
||||
if ( vSharpEdge.empty())
|
||||
return true ;
|
||||
|
||||
// Se il numero di Spigoli coincide, allora li unisco sequenzialmente tra loro ( considerazione buona ???)
|
||||
if ( ssize( vSharpEdge) == ssize( vSharpSubEdge)) {
|
||||
for ( int i = 0 ; i < ssize( vSharpEdge) ; ++ i)
|
||||
vSyncLines.emplace_back( vSharpEdge[i].ptEdge, vSharpSubEdge[i].ptEdge) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Scorro gli SharpEdges
|
||||
double dUPrevSubEdge = 0., dUCurrSubEdge = 0. ;
|
||||
for ( const SharpEdge& mySharpEdge : vSharpEdge) {
|
||||
|
||||
// Recupero il parametro sulla curva di sincronizzazione
|
||||
// --- Piano di taglio per punto a distanza minima
|
||||
IntersCurvePlane ICP( *pCompoSubEdge, mySharpEdge.ptEdge, Media( mySharpEdge.vtTanPrev, mySharpEdge.vtTanAft)) ;
|
||||
IntersCurvePlane ICP( *pCompoSubEdge, mySharpEdge.ptEdge, Media( mySharpEdge.vtTanPrev, mySharpEdge.vtTanNext)) ;
|
||||
int nIndParCloser = -1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
@@ -5940,7 +5915,7 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
@@ -5948,30 +5923,31 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurrSubEdge = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurrSubEdge = ( SqDist( mySharpEdge.ptEdge, aInfoPt.Ici[0].ptI) < SqDist( mySharpEdge.ptEdge, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
}
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurrSubEdge = ( SqDist( mySharpEdge.ptEdge, aInfoPt.Ici[0].ptI) < SqDist( mySharpEdge.ptEdge, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( mySharpEdge.ptEdge, *pCompoSubEdge) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrevSubEdge, dUCurrSubEdge, nFlag) && dUCurrSubEdge > dUPrevSubEdge) ;
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Eh.... bho ( se arrivo qui non so che fare...)
|
||||
double dUStart, dUEnd ;
|
||||
pCompoSubEdge->GetDomain( dUStart, dUEnd) ;
|
||||
dUCurrSubEdge = ( dUEnd - dUCurrSubEdge) / 2. ;
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( mySharpEdge.ptEdge, *pCompoSubEdge) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrevSubEdge, dUCurrSubEdge, nFlag) && dUCurrSubEdge > dUPrevSubEdge) ;
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Alla peggio mi posiziono a metà tra la posizione corrente e quella finale
|
||||
double dPrevLen ; pCompoSubEdge->GetLengthAtParam( dUPrevSubEdge, dPrevLen) ;
|
||||
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||
pCompoSubEdge->GetParamAtLength( ( dPrevLen + dLen) / 2., dUCurrSubEdge) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Verifico se tale parametro può essere avvicinato ad uno Spigolo presente sulla curva
|
||||
// NB. Come descitto sopra gli spigoli in generale è meglio sincronizzarli tra loro
|
||||
if ( ! vSharpSubEdge.empty()) {
|
||||
const double EDGE_LEN_TOL = 5. ;
|
||||
for ( const SharpEdge& mySharpSubEdge : vSharpSubEdge) {
|
||||
@@ -6001,7 +5977,104 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Debug [Gestione Edge in Quadrangolazioni]
|
||||
// Calcolo della curva di Sync tra un punto di una curva di Bordo (calcolato come il punto a curvatura massima) e il suo
|
||||
// associato sull'altra Curva di Bordo
|
||||
// -> Restituisce la singola Linea di Sincronizzazione
|
||||
static bool
|
||||
CalcSyncPointFromCurvature( const CurvaturePoint& PointK, const ICurveComposite* pCompoSubEdge, BIPOINT& SyncLine)
|
||||
{
|
||||
// Verifico la validità del SubEdge su cui trovare il punto di Sincronizzazione
|
||||
if ( pCompoSubEdge == nullptr || ! pCompoSubEdge->IsValid())
|
||||
return false ;
|
||||
|
||||
// --- Piano di taglio per punto a distanza minima
|
||||
double dUCurrSubEdge = 0. ;
|
||||
IntersCurvePlane ICP( *pCompoSubEdge, PointK.ptCurvature, Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||
int nIndParCloser = -1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo)) {
|
||||
if ( nIndParCloser == -1)
|
||||
nIndParCloser = nInfo ;
|
||||
double dSqDist = SqDist( PointK.ptCurvature, aInfo.Ici[0].ptI) ;
|
||||
if ( dSqDist < dSqMinDist) {
|
||||
dSqMinDist = dSqDist ;
|
||||
nIndPointCloser = nInfo ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurrSubEdge = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurrSubEdge = ( SqDist( PointK.ptCurvature, aInfoPt.Ici[0].ptI) < SqDist( PointK.ptCurvature, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
}
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( PointK.ptCurvature, *pCompoSubEdge) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( 0., dUCurrSubEdge, nFlag)) ;
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Alla peggio mi posiziono a metà tra la posizione corrente e quella finale
|
||||
double dPrevLen ; pCompoSubEdge->GetLengthAtParam( 0., dPrevLen) ;
|
||||
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||
pCompoSubEdge->GetParamAtLength( ( dPrevLen + dLen) / 2., dUCurrSubEdge) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Definisco il primo estremo della linea di Sincronizzazione corrente
|
||||
SyncLine.first = PointK.ptCurvature ;
|
||||
|
||||
// Verifico se posso muovermi attorno al punto trovato per allinearmi meglio con le normali alla curva
|
||||
// NB. Si cerca di privilgiare i punti più vicini ( in parametro) al punto calcolato sopra, in modo da cercare di
|
||||
// non discostare troppo la Linea di sincronizzazione dal punto trovato.
|
||||
const double MAX_DIST = 2.5 ;
|
||||
const int NUM_SAMPLE_PNT = 20 ;
|
||||
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||
double dSyncLen ; pCompoSubEdge->GetLengthAtParam( dUCurrSubEdge, dSyncLen) ;
|
||||
Vector3d vtSyncTanPrev, vtSyncTanNext ;
|
||||
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_MINUS, SyncLine.second, &vtSyncTanPrev) ; vtSyncTanPrev.Normalize() ;
|
||||
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_PLUS, SyncLine.second, &vtSyncTanNext) ; vtSyncTanNext.Normalize() ;
|
||||
double dLimInfLen = Clamp( dSyncLen - MAX_DIST, 0., dLen) ;
|
||||
double dLimSupLen = Clamp( dSyncLen + MAX_DIST, 0., dLen) ;
|
||||
int nSamplePnt = int( ceil( NUM_SAMPLE_PNT / 4.)) ;
|
||||
double dMaxCos = ( Media( PointK.vtTanPrev, PointK.vtTanNext) * Media( vtSyncTanPrev, vtSyncTanNext)) ;
|
||||
double dShiftR = ( dLimSupLen - dSyncLen) / nSamplePnt ;
|
||||
double dShiftL = ( dSyncLen - dLimInfLen) / nSamplePnt ;
|
||||
array<double, 2> vdLens = { dSyncLen, dSyncLen} ;
|
||||
for ( int i = 1 ; i <= nSamplePnt ; ++ i) {
|
||||
vdLens[0] += dShiftR ;
|
||||
vdLens[1] -= dShiftL ;
|
||||
for ( int j = 0 ; j < 2 ; ++ j) {
|
||||
double dU ; pCompoSubEdge->GetParamAtLength( vdLens[j], dU) ;
|
||||
Point3d ptCurr ; Vector3d vtTan ;
|
||||
pCompoSubEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr, &vtTan) ; vtTan.Normalize() ;
|
||||
double dCos = ( vtTan * Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||
if ( dCos > dMaxCos) {
|
||||
dMaxCos = dCos ;
|
||||
SyncLine.second = ptCurr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Gestione degli spigoli all'interno della Quadrangolazione corrente
|
||||
static bool
|
||||
ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines)
|
||||
{
|
||||
@@ -6020,7 +6093,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
SHARPEDGEVECTOR vSharpEdges2 ; vSharpEdges2.reserve( max( 0, nCrv2 - 1)) ;
|
||||
|
||||
// --- Cerco gli Spigoli sul SottoTratto del primo bordo
|
||||
// Se la CurvaA ha solo una sottocurva, non faccio nulla
|
||||
// Se la CurvaA ha più di una sottocurva, verifico l'esistenza di Spigoli (Sharp Edges)
|
||||
if ( nCrv1 > 1) {
|
||||
Point3d ptCurr1 ;
|
||||
// Scorro le sottocurve
|
||||
@@ -6029,17 +6102,17 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
double dU = double( nCrv + 1) ;
|
||||
// Recupero le tangenti prima e dopo tale parametro
|
||||
Vector3d vtTanPrev ; pSubEdge1->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr1, &vtTanPrev) ;
|
||||
Vector3d vtTanAft ; pSubEdge1->GetPointD1D2( dU, ICurve::FROM_PLUS, ptCurr1, &vtTanAft) ;
|
||||
Vector3d vtTanNext ; pSubEdge1->GetPointD1D2( dU, ICurve::FROM_PLUS, ptCurr1, &vtTanNext) ;
|
||||
// Verifico se ho uno spigolo
|
||||
vtTanPrev.Normalize() ;
|
||||
vtTanAft.Normalize() ;
|
||||
if ( vtTanPrev * vtTanAft < COS_EDGE_LIMIT)
|
||||
vSharpEdges1.emplace_back( dU, ptCurr1, vtTanPrev, vtTanAft) ;
|
||||
vtTanNext.Normalize() ;
|
||||
if ( vtTanPrev * vtTanNext < COS_EDGE_LIMIT)
|
||||
vSharpEdges1.emplace_back( dU, ptCurr1, vtTanPrev, vtTanNext) ;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Cerco gli spigoli sul Sottotratto del secondo bordo
|
||||
// Se la Curva B ha solo una sottocurva, non faccio nulla
|
||||
// Se la Curva B ha più di una sottocurva, verifico l'esistena di Spigoli (Sharp Edges)
|
||||
if ( nCrv2 > 1) {
|
||||
Point3d ptCurr2 ;
|
||||
// Scorro le sottocurve
|
||||
@@ -6048,24 +6121,24 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
double dU = double( nCrv + 1) ;
|
||||
// Recupero le tangenti prima e dopo tale parametro
|
||||
Vector3d vtTanPrev ; pSubEdge2->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr2, &vtTanPrev) ;
|
||||
Vector3d vtTanAft ; pSubEdge2->GetPointD1D2( dU, ICurve::FROM_PLUS, ptCurr2, &vtTanAft) ;
|
||||
Vector3d vtTanNext ; pSubEdge2->GetPointD1D2( dU, ICurve::FROM_PLUS, ptCurr2, &vtTanNext) ;
|
||||
// Verifico se ho uno spigolo
|
||||
vtTanPrev.Normalize() ;
|
||||
vtTanAft.Normalize() ;
|
||||
if ( vtTanPrev * vtTanAft < COS_EDGE_LIMIT)
|
||||
vSharpEdges2.emplace_back( dU, ptCurr2, vtTanPrev, vtTanAft) ;
|
||||
vtTanNext.Normalize() ;
|
||||
if ( vtTanPrev * vtTanNext < COS_EDGE_LIMIT)
|
||||
vSharpEdges2.emplace_back( dU, ptCurr2, vtTanPrev, vtTanNext) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se non ho alcuno spigolo, allora non faccio nulla
|
||||
// Se non ho alcuno spigolo per entrambe le curve di Bordo, non faccio nulla
|
||||
if ( vSharpEdges1.empty() && vSharpEdges2.empty())
|
||||
return true ;
|
||||
|
||||
// Recupero le Curve di Sincronizzazione dell'Edge 1 sull'Edge 2
|
||||
// Recupero le Curve di Sincronizzazione associate agli spigoli dal primo Bordo al secondo Bordo
|
||||
BIPNTVECTOR vSyncLines1 ;
|
||||
CalcSyncPointFromEdge( vSharpEdges1, pSubEdge2, vSharpEdges2, vSyncLines1) ;
|
||||
|
||||
// Recupero le Curve di Sincronizzazione dell'Edge 2 sull'Egde 1
|
||||
// Recupero le Curve di Sincronizzazione associate agli spigoli dal secondo Bordo al primo Bordo
|
||||
BIPNTVECTOR vSyncLines2 ;
|
||||
CalcSyncPointFromEdge( vSharpEdges2, pSubEdge1, vSharpEdges1, vSyncLines2) ;
|
||||
|
||||
@@ -6078,7 +6151,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
}) ;
|
||||
}) ;
|
||||
|
||||
// Ordino tutte le curve in base al parametro dU della curva principale
|
||||
// Ordino tutte le curve in base al parametro dU della prima curva di Bordo
|
||||
vector<pair<BIPOINT, double>> vSyncLinesPar ; vSyncLinesPar.reserve( vSyncLines1.size() + vSyncLines2.size()) ;
|
||||
for ( BIPOINT& SyncLine1 : vSyncLines1) {
|
||||
vSyncLinesPar.emplace_back( make_pair( make_pair( SyncLine1.first, SyncLine1.second),
|
||||
@@ -6094,9 +6167,212 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
return SyncLineParA.second < SyncLineParB.second ;
|
||||
}) ;
|
||||
|
||||
// Restituisco il risultato
|
||||
for ( auto Iter = vSyncLinesPar.begin() ; Iter != vSyncLinesPar.end() ; ++ Iter)
|
||||
vSyncLines.emplace_back( Iter->first) ;
|
||||
// Controllo che le linee di sincronizzazione non si intreccino e restituisco il risultato
|
||||
// NB. Inserisco solo che curve che progressivamente non si intrecciano sulla seconda curva di Bordo
|
||||
double dUSecondPrev = EPS_PARAM ;
|
||||
for ( auto Iter = vSyncLinesPar.begin() ; Iter != vSyncLinesPar.end() ; ++ Iter) {
|
||||
double dUSecondCurr ; pSubEdge2->GetParamAtPoint( ( *Iter).first.second, dUSecondCurr, TOL) ;
|
||||
if ( dUSecondCurr > dUSecondPrev + EPS_SMALL) {
|
||||
vSyncLines.emplace_back( Iter->first) ;
|
||||
dUSecondPrev = dUSecondCurr ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Calcolo delle Curve di Sync per evitare Twist
|
||||
static bool
|
||||
ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines)
|
||||
{
|
||||
// Verifica validità delle curve
|
||||
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
|
||||
return false ;
|
||||
|
||||
const double COS_LIMIT = cos( 50. * DEGTORAD) ;
|
||||
const int NUM_SAMPLE_PNT = 20 ;
|
||||
#if DEBUG_CURVATURE
|
||||
vector<pair<Point3d, double>> _vPtK1 ;
|
||||
vector<pair<Point3d, double>> _vPtK2 ;
|
||||
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
||||
VERIFY_GEOMDB( pGeomDB, false)
|
||||
#endif
|
||||
|
||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine della prima curva di Bordo
|
||||
Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ;
|
||||
Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ;
|
||||
double dLen1 = - EPS_SMALL ;
|
||||
bool bSplit1 = ( vtS1 * vtE1 < COS_LIMIT) ;
|
||||
if ( bSplit1) {
|
||||
// Individuo il punto a Curvatura Massima
|
||||
pSubEdge1->GetLength( dLen1) ;
|
||||
double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ;
|
||||
Point3d ptKMax1 ; Vector3d vtTanKMax1Prev, vtTanKMax1Next ;
|
||||
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||
double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ;
|
||||
double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ;
|
||||
// Calcolo la Curvatura
|
||||
Point3d ptCurrSub1 ;
|
||||
Vector3d vtCurrSub1Der1Prev, vtCurrSub1Der2Prev, vtCurrSub1Der1Next, vtCurrSub1Der2Next ;
|
||||
pSubEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurrSub1, &vtCurrSub1Der1Prev, &vtCurrSub1Der2Prev) ;
|
||||
pSubEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_PLUS, ptCurrSub1, &vtCurrSub1Der1Next, &vtCurrSub1Der2Next) ;
|
||||
Vector3d vtCurrSub1Der1 = Media( vtCurrSub1Der1Prev, vtCurrSub1Der1Next) ;
|
||||
Vector3d vtCurrSub1Der2 = Media( vtCurrSub1Der2Prev, vtCurrSub1Der2Next) ;
|
||||
double dCurrK1 = ( vtCurrSub1Der1 ^ vtCurrSub1Der2).Len() / max( EPS_SMALL, Pow( vtCurrSub1Der1.Len(), 3)) ;
|
||||
// Se maggiore della massima trovata, aggiorno la massima
|
||||
if ( dCurrK1 > dKMax1) {
|
||||
dKMax1 = dCurrK1 ;
|
||||
ptKMax1 = ptCurrSub1 ;
|
||||
dUK1Max = dUCurr1 ;
|
||||
vtTanKMax1Prev = vtCurrSub1Der1Prev ;
|
||||
vtTanKMax1Next = vtCurrSub1Der1Next ;
|
||||
}
|
||||
#if DEBUG_CURVATURE
|
||||
_vPtK1.emplace_back( make_pair( ptCurrSub1, dCurrK1)) ;
|
||||
#endif
|
||||
}
|
||||
vtTanKMax1Prev.Normalize() ;
|
||||
vtTanKMax1Next.Normalize() ;
|
||||
// Calcolo la nuova linea di sincronizzazione
|
||||
CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ;
|
||||
BIPOINT SyncLine ;
|
||||
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge2, SyncLine) ;
|
||||
vSyncLines.emplace_back( SyncLine) ;
|
||||
}
|
||||
|
||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo
|
||||
Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ;
|
||||
Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ;
|
||||
double dLen2 = - EPS_SMALL ;
|
||||
bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ;
|
||||
if ( bSplit2) {
|
||||
// Individuo il punto a Curvatura Massima
|
||||
pSubEdge2->GetLength( dLen2) ;
|
||||
double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ;
|
||||
Point3d ptKMax2 ; Vector3d vtTanKMax2Prev, vtTanKMax2Next ;
|
||||
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||
double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ;
|
||||
double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ;
|
||||
// Calcolo la Curvatura
|
||||
Point3d ptCurrSub2 ;
|
||||
Vector3d vtCurrSub2Der1Prev, vtCurrSub2Der2Prev, vtCurrSub2Der1Next, vtCurrSub2Der2Next ;
|
||||
pSubEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurrSub2, &vtCurrSub2Der1Prev, &vtCurrSub2Der2Prev) ;
|
||||
pSubEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_PLUS, ptCurrSub2, &vtCurrSub2Der1Next, &vtCurrSub2Der2Next) ;
|
||||
Vector3d vtCurrSub2Der1 = Media( vtCurrSub2Der1Prev, vtCurrSub2Der1Next) ;
|
||||
Vector3d vtCurrSub2Der2 = Media( vtCurrSub2Der2Prev, vtCurrSub2Der2Next) ;
|
||||
double dCurrK2 = ( vtCurrSub2Der1 ^ vtCurrSub2Der2).Len() / max( EPS_SMALL, Pow( vtCurrSub2Der1.Len(), 3)) ;
|
||||
// Se maggiore della massima trovata, aggiorno la massima
|
||||
if ( dCurrK2 > dKMax2) {
|
||||
dKMax2 = dCurrK2 ;
|
||||
ptKMax2 = ptCurrSub2 ;
|
||||
dUK2Max = dUCurr2 ;
|
||||
vtTanKMax2Prev = vtCurrSub2Der1Prev ;
|
||||
vtTanKMax2Next = vtCurrSub2Der1Next ;
|
||||
}
|
||||
#if DEBUG_CURVATURE
|
||||
_vPtK1.emplace_back( make_pair( ptCurrSub2, dCurrK2)) ;
|
||||
#endif
|
||||
}
|
||||
vtTanKMax2Prev.Normalize() ;
|
||||
vtTanKMax2Next.Normalize() ;
|
||||
// Calcolo la nuova linea di sincronizzazione
|
||||
CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ;
|
||||
BIPOINT SyncLine ;
|
||||
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge1, SyncLine) ;
|
||||
// !<-- Inverto la curva di Sincronizzaione per coerenza con la prima -->!
|
||||
swap( SyncLine.first, SyncLine.second) ;
|
||||
vSyncLines.emplace_back( SyncLine) ;
|
||||
}
|
||||
|
||||
#if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE
|
||||
auto [itMin1, itMax1] = std::minmax_element( _vPtK1.begin(), _vPtK1.end(), [](auto const& A, auto const& B) {
|
||||
return A.second < B.second ;
|
||||
}) ;
|
||||
double _dK1Max = itMax1->second ;
|
||||
double _dK1Min = itMin1->second ;
|
||||
for ( int i = 0 ; i < ssize( _vPtK1) ; ++ i) {
|
||||
double _t = 0. ;
|
||||
if ( _dK1Max > _dK1Min)
|
||||
_t = ( _vPtK1[i].second - _dK1Min) / ( _dK1Max - _dK1Min) ;
|
||||
double _dh = 30 - 180. ; // AQUA -> HSV( 180, 1, 1) | ORANGE -> HSV( 30, 1, 1)
|
||||
if ( _dh > 180.) _dh -= 360.0 ;
|
||||
if ( _dh < -180.0) _dh += 360.0 ;
|
||||
double _h = 180. + _t * _dh ;
|
||||
if ( _h < 0.0) _h += 360.0 ;
|
||||
if ( _h >= 360.0) _h -= 360.0 ;
|
||||
PtrOwner<IGeoPoint3d> _ptC( CreateGeoPoint3d()) ; _ptC->Set( _vPtK1[i].first) ;
|
||||
int _nId = pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, Release( _ptC)) ;
|
||||
pGeomDB->SetMaterial( _nId, Color( GetColorFromHSV( HSV( _h, 1., 1.)))) ;
|
||||
}
|
||||
auto [itMin2, itMax2] = std::minmax_element( _vPtK2.begin(), _vPtK2.end(), [](auto const& A, auto const& B) {
|
||||
return A.second < B.second ;
|
||||
}) ;
|
||||
double _dK2Max = itMax2->second ;
|
||||
double _dK2Min = itMin2->second ;
|
||||
for ( int i = 0 ; i < ssize( _vPtK2) ; ++ i) {
|
||||
double _t = 0. ;
|
||||
if ( _dK2Max > _dK2Min)
|
||||
_t = ( _vPtK2[i].second - _dK2Min) / ( _dK2Max - _dK2Min) ;
|
||||
double _dh = 30 - 180. ; // CYAN -> HSV( 180, 1, 1) | ORANGE -> HSV( 30, 1, 1)
|
||||
if ( _dh > 180.) _dh -= 360.0 ;
|
||||
if ( _dh < -180.0) _dh += 360.0 ;
|
||||
double _h = 180. + _t * _dh ;
|
||||
if ( _h < 0.0) _h += 360.0 ;
|
||||
if ( _h >= 360.0) _h -= 360.0 ;
|
||||
PtrOwner<IGeoPoint3d> _ptC( CreateGeoPoint3d()) ; _ptC->Set( _vPtK2[i].first) ;
|
||||
int _nId = pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, Release( _ptC)) ;
|
||||
pGeomDB->SetMaterial( _nId, Color( GetColorFromHSV( HSV( _h, 1., 1.)))) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Se non ho alcuna linea di sincronizzazione, non faccio nulla
|
||||
if ( vSyncLines.empty())
|
||||
return true ;
|
||||
|
||||
const double TOL = 250. * EPS_SMALL ;
|
||||
|
||||
// Elimino tutte le curve di Sincronizzazione a ridosso degli estremi della Quadrangolazione
|
||||
// NB. Risultano ridondanti, creano SottoQuadrangolazioni molto strette o possono Inclinare eccssivamente l'Utensile
|
||||
// NB. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione
|
||||
const double LEN_TOL = 2. ;
|
||||
for ( int i = 0 ; i < ssize( vSyncLines) ; ++ i) {
|
||||
double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ;
|
||||
bool bErase = ( dSyncLen1 < max( LEN_TOL, 0.2 * dLen1) || dSyncLen1 > min( dLen1 - LEN_TOL, 0.8 * dLen1)) ;
|
||||
if ( ! bErase) {
|
||||
double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ;
|
||||
bErase = ( dSyncLen2 < max( LEN_TOL, 0.2 * dLen2) || dSyncLen2 > min( dLen2 - LEN_TOL, 0.8 * dLen2)) ;
|
||||
}
|
||||
if ( bErase) {
|
||||
vSyncLines.erase( vSyncLines.begin() + i) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
if ( vSyncLines.empty())
|
||||
return true ;
|
||||
|
||||
// Se due curve di Sincronizzazione rimaste
|
||||
if ( ssize( vSyncLines) == 2) {
|
||||
// Se si sovrappongono, ne elimino una
|
||||
if ( AreSamePointEpsilon( vSyncLines[0].first, vSyncLines[1].first, LEN_TOL) &&
|
||||
AreSamePointEpsilon( vSyncLines[0].second, vSyncLines[1].second, LEN_TOL))
|
||||
vSyncLines.pop_back() ;
|
||||
}
|
||||
// Se due curve di Sincronizzazione rimaste
|
||||
if ( ssize( vSyncLines) == 2) {
|
||||
// Ordino tutte le linee di sincronizzazione in base al parametro dU della curva principale
|
||||
double dU0 ; pSubEdge1->GetParamAtPoint( vSyncLines[0].first, dU0, TOL) ;
|
||||
double dU1 ; pSubEdge1->GetParamAtPoint( vSyncLines[1].first, dU1, TOL) ;
|
||||
if ( dU0 > dU1 - EPS_SMALL)
|
||||
swap( vSyncLines[0], vSyncLines[1]) ;
|
||||
// Verifico che le curve non si intreccino
|
||||
pSubEdge2->GetParamAtPoint( vSyncLines[0].second, dU0, TOL) ;
|
||||
pSubEdge2->GetParamAtPoint( vSyncLines[1].second, dU1, TOL) ;
|
||||
if ( dU0 > dU1 - EPS_SMALL)
|
||||
vSyncLines.pop_back() ; // lascio solo la prima... ( bisognerebbe scegliere quale lasciare con un criterio migliore ?)
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -6104,14 +6380,29 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen)
|
||||
{
|
||||
BIPNTVECTOR vSyncLines ;
|
||||
return CreateSmoothRuledByTwoCurves( pCurve0, pCurve1, dSampleLen, vSyncLines) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines)
|
||||
{
|
||||
// converto in bezier le curve iniziali
|
||||
PtrOwner<ICurveBezier> pCrvEdge1( GetCurveBezier( CurveToBezierCurve( pCurve0, 3, false))) ;
|
||||
PtrOwner<ICurveBezier> pCrvEdge2( GetCurveBezier( CurveToBezierCurve( pCurve1, 3, false))) ;
|
||||
PtrOwner<ICurveComposite> pCrvEdge1( ConvertCurveToComposite(CurveToBezierCurve( pCurve0, 3, false))) ;
|
||||
PtrOwner<ICurveComposite> pCrvEdge2( ConvertCurveToComposite(CurveToBezierCurve( pCurve1, 3, false))) ;
|
||||
|
||||
if ( IsNull( pCrvEdge1) || IsNull( pCrvEdge2))
|
||||
return false ;
|
||||
|
||||
#if SAVEPACEDISO
|
||||
vGeo.clear() ;
|
||||
vCol.clear() ;
|
||||
#endif
|
||||
|
||||
// Verifico che la distanza di campionamento sia ammissibile
|
||||
double dMyDist = Clamp( dSampleLen, 2., 30.) ; // 20.0 sembra un passo di campionamento ideale
|
||||
// Recupero parametri iniziali
|
||||
double dLen1 ; pCrvEdge1->GetLength( dLen1) ;
|
||||
double dLen2 ; pCrvEdge2->GetLength( dLen2) ;
|
||||
@@ -6124,155 +6415,112 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
Point3d ptPrev1, ptCurr1 ; pCrvEdge1->GetStartPoint( ptPrev1) ;
|
||||
Point3d ptPrev2, ptCurr2 ; pCrvEdge2->GetStartPoint( ptPrev2) ;
|
||||
Vector3d vtCurr1 = V_NULL, vtCurr2 = V_NULL ;
|
||||
BIPNTVECTOR vEdgeSyncLines ;
|
||||
while ( dLenPrev1 + dSampleLen < dLen1 - EPS_ZERO) {
|
||||
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
|
||||
dLenCurr1 = Clamp( dLenPrev1 + dSampleLen, 0., dLen1) ;
|
||||
|
||||
while ( dLenPrev1 + dMyDist < dLen1 - EPS_ZERO) {
|
||||
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
|
||||
dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ;
|
||||
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
|
||||
//// se sono abbastanza vicino ad una joint allora prendo quel punto
|
||||
//double dUClosestJoint1 = round( dUCurr1) ;
|
||||
//double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
|
||||
//if ( abs( dLenCurr1 - dLenAlt1) < 1)
|
||||
// dUCurr1 = dUClosestJoint1 ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
|
||||
#if DEBUG_SYNCLINES
|
||||
PtrOwner<IGeoPoint3d> ptGeo1( CreateGeoPoint3d()) ; ptGeo1->Set( ptCurr1) ;
|
||||
PtrOwner<IGeoVector3d> vtGeo1( CreateGeoVector3d()) ; vtGeo1->Set( 5. * vtCurr1, ptCurr1) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, Release( ptGeo1)) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, Release( vtGeo1)) ;
|
||||
#endif
|
||||
#if DEBUG_SYNCLINES
|
||||
PtrOwner<IGeoPoint3d> ptGeo1( CreateGeoPoint3d()) ; ptGeo1->Set( ptCurr1) ;
|
||||
PtrOwner<IGeoVector3d> vtGeo1( CreateGeoVector3d()) ; vtGeo1->Set( 5. * vtCurr1, ptCurr1) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, Release( ptGeo1)) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay1, Release( vtGeo1)) ;
|
||||
#endif
|
||||
|
||||
// --- Piano di taglio per punto a minima distanza
|
||||
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
|
||||
int nIndParCloser = - 1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo) && aInfo.Ici[0].dU > dUPrev2) {
|
||||
if ( nIndParCloser == -1)
|
||||
nIndParCloser = nInfo ;
|
||||
double dSqDist = SqDist( ptCurr1, aInfo.Ici[0].ptI) ;
|
||||
if ( dSqDist < dSqMinDist) {
|
||||
dSqMinDist = dSqDist ;
|
||||
nIndPointCloser = nInfo ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurr2 = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurr2 = ( SqDist( ptCurr1, aInfoPt.Ici[0].ptI) < SqDist( ptCurr1, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
#if DEBUG_SYNCLINES && 0
|
||||
VT.clear() ; VC.clear() ;
|
||||
VT.emplace_back( pCrvEdge1->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
VT.emplace_back( pCrvEdge2->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
PtrOwner<IGeoPoint3d> ptCurr1Geo( CreateGeoPoint3d()) ; ptCurr1Geo->Set( ptCurr1) ;
|
||||
VT.emplace_back( Release( ptCurr1Geo)) ; VC.emplace_back( BLUE) ;
|
||||
PtrOwner<IGeoPoint3d> ptPar( CreateGeoPoint3d()) ; ptPar->Set( aInfoPar.Ici[0].ptI) ;
|
||||
PtrOwner<IGeoPoint3d> ptPt( CreateGeoPoint3d()) ; ptPt->Set( aInfoPt.Ici[0].ptI) ;
|
||||
VT.emplace_back( Release( ptPar)) ; VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( Release( ptPt)) ; VC.emplace_back( FUCHSIA) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\TestTrimmingPlane.nge") ;
|
||||
#endif
|
||||
}
|
||||
// Verifico di non essermi allontanato troppo
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkPlane = ( dLen < dLenPrev2 + 2. * dSampleLen) ;
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( ptCurr1, *pCrvEdge2) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrev2, dUCurr2, nFlag) && dUCurr2 > dUPrev2) ;
|
||||
// Verifico di non essermi allontanato troppo
|
||||
if ( bOkMinDist) {
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkMinDist = ( dLen < dLenPrev2 + 2. * dSampleLen) ;
|
||||
}
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Aumento la distanza corrente del passo di campionamento
|
||||
double dLen = Clamp( dLenPrev2 + dSampleLen, 0., dLen2) ;
|
||||
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
|
||||
}
|
||||
}
|
||||
GetIsoPointOnSecondCurve( pCrvEdge1, pCrvEdge2, dUCurr1, dUCurr2, dMyDist, dUPrev2, dLenPrev2, dLenCurr2, dLen2) ;
|
||||
|
||||
// Recupero il punto corrente e la direzione tangente sul secondo bordo
|
||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
||||
//// verifico se sono vicino ad una joint esistente allora modifico la curva 2
|
||||
//double dUClosestJoint2 = round( dUCurr2) ;
|
||||
//double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ;
|
||||
//if ( abs( dLenCurr1 - dLenAlt2) < 1) {
|
||||
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUClosestJoint2, ICurve::FROM_MINUS, ptNewJoint) ;
|
||||
// pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint) ;
|
||||
// dUCurr2 = dUClosestJoint2 ;
|
||||
//}
|
||||
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
||||
vtCurr2.Normalize() ;
|
||||
|
||||
// Verifico se le direzioni tangenti sono tra di loro circa parallele
|
||||
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
|
||||
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
|
||||
// Se fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dSampleLen)
|
||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSampleLen, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSampleLen, dLenPrev2, dLen2) ;
|
||||
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
|
||||
const int NUM_STEP = 20 ;
|
||||
double dMinCos = - 1. - EPS_ZERO ;
|
||||
const double DEGTOL = 5. ;
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
||||
double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ;
|
||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||
pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||
double dAngTol = ( i < NUM_STEP / 2 ? ( 2. * DEGTOL) / NUM_STEP * i :
|
||||
( - 2. * DEGTOL) / NUM_STEP * ( i - NUM_STEP)) ;
|
||||
double dCosTol = 1. - cos( dAngTol * DEGTORAD) ;
|
||||
if ( dStepCos2 + dCosTol > dMinCos) {
|
||||
ptCurr2 = ptStep2 ;
|
||||
vtCurr2 = vtStep2 ;
|
||||
dUCurr2 = dUStep2 ;
|
||||
dMinCos = dStepCos2 + dCosTol ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_SYNCLINES
|
||||
PtrOwner<IGeoPoint3d> ptGeo2( CreateGeoPoint3d()) ; ptGeo2->Set( ptCurr2) ;
|
||||
PtrOwner<IGeoVector3d> vtGeo2( CreateGeoVector3d()) ; vtGeo2->Set( 5. * vtCurr2, ptCurr2) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay2, Release( ptGeo2)) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay2, Release( vtGeo2)) ;
|
||||
#endif
|
||||
#if DEBUG_SYNCLINES
|
||||
PtrOwner<IGeoPoint3d> ptGeo2( CreateGeoPoint3d()) ; ptGeo2->Set( ptCurr2) ;
|
||||
PtrOwner<IGeoVector3d> vtGeo2( CreateGeoVector3d()) ; vtGeo2->Set( 5. * vtCurr2, ptCurr2) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay2, Release( ptGeo2)) ;
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay2, Release( vtGeo2)) ;
|
||||
#endif
|
||||
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
|
||||
|
||||
// debug
|
||||
//// Inserisco le curve di sincronizzazione nel Layer di destinazine
|
||||
// PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ;
|
||||
// pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
//// Inserisco le curve di sincronizzazione nel Layer di destinazine
|
||||
//PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ;
|
||||
//pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
|
||||
// --- Analisi degli spigoli all'interno della Quadrangolazione ---
|
||||
// Perchè si fa questa cosa ? Perchè parametrizzando per la lunghezza i SottoTratti ricavati, non è sempre detto
|
||||
// che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)... Pertanto
|
||||
// la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo
|
||||
// --- Analisi degli spigoli all'interno della Quadrangolazione corrente ---
|
||||
// NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)...
|
||||
// Pertanto la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo
|
||||
PtrOwner<ICurveComposite> pCrvQuad1( ConvertCurveToComposite( pCrvEdge1->CopyParamRange( dUPrev1, dUCurr1))) ;
|
||||
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
|
||||
BIPNTVECTOR vEdgeSyncLines ;
|
||||
ManageEdgesInQuadrangulation( pCrvQuad1, pCrvQuad2, vEdgeSyncLines) ;
|
||||
|
||||
//debug
|
||||
//for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||
// PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vEdgeSyncLines[i].first, vEdgeSyncLines[i].second) ;
|
||||
// int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
// pGeomDB->SetMaterial( nNewId, GREEN) ;
|
||||
//}
|
||||
|
||||
// --- Aggiunta di Linee di Sync all'interno della Quandrangolazione corrente ---
|
||||
// Perchè parametrizzando per la lunghezza i SottoTratti ricavati, nel caso di elevate variazioni angolari tra l'inizio e la fine
|
||||
// ( tra due curva di Sync) si potrebbero generare delle torsioni non volute
|
||||
// -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<--
|
||||
BIPNTVECTOR vTwistSyncLines ;
|
||||
if ( vEdgeSyncLines.empty())
|
||||
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines) ;
|
||||
else {
|
||||
BIPOINT SyncLinePrev, SyncLineNext ;
|
||||
pCrvQuad1->GetStartPoint( SyncLinePrev.first) ;
|
||||
pCrvQuad2->GetStartPoint( SyncLinePrev.second) ;
|
||||
for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||
if ( i == ssize( vEdgeSyncLines) - 1) {
|
||||
pCrvQuad1->GetEndPoint( SyncLineNext.first) ;
|
||||
pCrvQuad2->GetEndPoint( SyncLineNext.second) ;
|
||||
}
|
||||
else {
|
||||
SyncLineNext.first = vEdgeSyncLines[i].first ;
|
||||
SyncLineNext.second = vEdgeSyncLines[i].second ;
|
||||
}
|
||||
// Recupero i parametri correnti
|
||||
double dUS1, dUE1, dUS2, dUE2 ;
|
||||
pCrvQuad1->GetParamAtPoint( SyncLinePrev.first, dUS1) ;
|
||||
pCrvQuad2->GetParamAtPoint( SyncLinePrev.second, dUS2) ;
|
||||
pCrvQuad1->GetParamAtPoint( SyncLineNext.first, dUE1) ;
|
||||
pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ;
|
||||
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
|
||||
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ;
|
||||
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ;
|
||||
// Aggiorno i parametri
|
||||
SyncLinePrev = SyncLineNext ;
|
||||
}
|
||||
}
|
||||
// aggiungo le nuove curve ( non importa che siano in ordine di parametro)
|
||||
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ;
|
||||
vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ;
|
||||
|
||||
// Aggiorno i parametri
|
||||
// Aggiorno i parametri
|
||||
ptPrev1 = ptCurr1 ; dUPrev1 = dUCurr1 ; dLenPrev1 = dLenCurr1 ;
|
||||
ptPrev2 = ptCurr2 ; dUPrev2 = dUCurr2 ; dLenPrev2 = dLenCurr2 ;
|
||||
}
|
||||
|
||||
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vEdgeSyncLines) ;
|
||||
#if SAVEPACEDISO
|
||||
SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ;
|
||||
#endif
|
||||
|
||||
|
||||
// devo riempire vSyncLines
|
||||
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -155,6 +155,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool SwapParameters( void) ;
|
||||
bool LimitSurfToTrimmedRegion( void) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+521
-75
@@ -36,13 +36,13 @@
|
||||
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
|
||||
// -------------------------- Debug --------------------------------------------
|
||||
#define DEBUG 0
|
||||
#define DEBUG_BASIC_BORDERS 0
|
||||
#define DEBUG_CHAIN_CURVES 0
|
||||
#define DEBUG_ANG_APPROX 0
|
||||
@@ -63,11 +63,12 @@
|
||||
#define DEBUG_EDGES 0
|
||||
#define DEBUG_SHAPE_STM 0
|
||||
#define DEBUG_HOLES 0
|
||||
#define DEBUG_SMOOTH_CURVATURE 0
|
||||
#if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \
|
||||
DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \
|
||||
DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \
|
||||
DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \
|
||||
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG
|
||||
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG_SMOOTH_CURVATURE
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
@@ -284,58 +285,6 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Funzione per spezzare una curva compo in diversi tratti in corrispondenza
|
||||
// di cambi di direzione maggiori della tolleranza angolare passata
|
||||
static bool
|
||||
SplitCurveCompoByAngTol( const ICurveComposite* pCC, double dAngTol, ICRVCOMPOPOVECTOR& vCC)
|
||||
{
|
||||
int nCurves = pCC->GetCurveCount() ;
|
||||
vCC.emplace_back( CreateCurveComposite()) ;
|
||||
vCC.back()->AddCurve( pCC->GetCurve(0)->Clone()) ;
|
||||
// Cos della tolleranza angolare massima
|
||||
double dCosTol = cos( dAngTol * DEGTORAD) ;
|
||||
|
||||
for ( int nC = 0 ; nC < nCurves - 2; ++ nC) {
|
||||
// Recupero l'angolo tra la fine della curva corrente e l'inizio della successiva
|
||||
const ICurve* pCrvCurr = pCC->GetCurve( nC) ;
|
||||
const ICurve* pCrvNext = pCC->GetCurve( nC + 1) ;
|
||||
Vector3d vtCurrEnd ; pCrvCurr->GetEndDir( vtCurrEnd) ;
|
||||
Vector3d vtNextStart ; pCrvNext->GetStartDir( vtNextStart) ;
|
||||
// Calcolo il Coseno tra i due versori
|
||||
double dCos = vtCurrEnd * vtNextStart ;
|
||||
// Se dentro alla tolleranza, allora i punti apparterranno alla stessa curva
|
||||
if ( dCos > dCosTol) {
|
||||
// Aggiungo la curva
|
||||
vCC.back()->AddCurve( pCrvNext->Clone()) ;
|
||||
}
|
||||
// Se tratto al di fuori della tolleranza, devo definire una nuova curva
|
||||
else {
|
||||
vCC.emplace_back( CreateCurveComposite()) ;
|
||||
vCC.back()->AddCurve( pCrvNext->Clone()) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se curva originale chiusa
|
||||
if ( pCC->IsClosed() && ssize( vCC) > 1) {
|
||||
// Se ho più tratti, potrei riunire il primo con l'ultimo
|
||||
const ICurve* pCrvFirst = pCC->GetCurve( 0) ;
|
||||
const ICurve* pCrvLast = pCC->GetCurve( nCurves - 1) ;
|
||||
Vector3d vtFirstStart ; pCrvFirst->GetEndDir( vtFirstStart) ;
|
||||
Vector3d vtLastEnd ; pCrvLast->GetStartDir( vtLastEnd) ;
|
||||
// Calcolo il Coseno tra i due versori
|
||||
double dCos = vtFirstStart * vtLastEnd ;
|
||||
// Se dentro alla tolleranza, allora i punti appartengono alla stessa curva
|
||||
if ( dCos > dCosTol) {
|
||||
// Aggiungo la curva
|
||||
vCC.back()->AddCurve( Release( vCC.front())) ;
|
||||
vCC.erase( vCC.begin()) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
|
||||
//// Patches di curve di Bezier
|
||||
@@ -3947,8 +3896,8 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid())
|
||||
return false ;
|
||||
|
||||
// Controllo sulla tolleranza lineare
|
||||
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
//// Controllo sulla tolleranza lineare
|
||||
//double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
|
||||
#if DEBUG_SYNC_POINTS
|
||||
VT.clear() ; VC.clear() ;
|
||||
@@ -3959,26 +3908,26 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
#endif
|
||||
|
||||
// Definisco la superficie di Bezier rigata
|
||||
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol))) ;
|
||||
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncPoints, 20.0))) ;
|
||||
if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid())
|
||||
return false ;
|
||||
|
||||
// Recupero i punti di sincronizzazione e li restituisco
|
||||
ICURVEPOVECTOR vCrv ;
|
||||
pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
|
||||
vSyncPoints.reserve( vCrv.size()) ;
|
||||
for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
|
||||
if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
|
||||
#if DEBUG_SYNC_POINTS
|
||||
VT.emplace_back( vCrv[i]->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
#endif
|
||||
Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
|
||||
if ( ! AreSamePointApprox( ptStart, ptEnd))
|
||||
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
|
||||
}
|
||||
}
|
||||
//// Recupero i punti di sincronizzazione e li restituisco
|
||||
// ICURVEPOVECTOR vCrv ;
|
||||
// pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
|
||||
// vSyncPoints.reserve( vCrv.size()) ;
|
||||
// for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
|
||||
// if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
|
||||
// #if DEBUG_SYNC_POINTS
|
||||
// VT.emplace_back( vCrv[i]->Clone()) ;
|
||||
// VC.emplace_back( LIME) ;
|
||||
// #endif
|
||||
// Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
|
||||
// Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
|
||||
// if ( ! AreSamePointApprox( ptStart, ptEnd))
|
||||
// vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
|
||||
// }
|
||||
// }
|
||||
|
||||
#if DEBUG_SYNC_POINTS
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ;
|
||||
@@ -4009,7 +3958,7 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
|
||||
// Verifico i valori delle tolleranze
|
||||
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
|
||||
//double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
|
||||
|
||||
// Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo
|
||||
Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ;
|
||||
@@ -4219,7 +4168,8 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
|
||||
|
||||
// Se non ho punti di controllo forzati
|
||||
if ( vSyncPoints.empty()) {
|
||||
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10)) ;
|
||||
BIPNTVECTOR vSyncLines ;
|
||||
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncLines, 20.0)) ;
|
||||
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
|
||||
return nullptr ;
|
||||
@@ -4950,3 +4900,499 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
struct PntInfo{
|
||||
Point3d pt ;
|
||||
double dDist ;
|
||||
Vector3d vtPos ;
|
||||
PntInfo( const Point3d& _pt, double _dDist, const Vector3d& _vtPos) :
|
||||
pt( _pt), dDist( _dDist), vtPos( _vtPos) {;}
|
||||
};
|
||||
typedef vector<PntInfo> PNTINFOVECTOR ;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool
|
||||
FillPntInfo( const PNTVECTOR& vPnt, const ICurveComposite* pCC, PNTINFOVECTOR& vPntInfo)
|
||||
{
|
||||
for ( int i = 0 ; i < ssize( vPnt) - 3 ; i+=3) {
|
||||
bool bOk = false ;
|
||||
const ICurveBezier* pSubCrv = GetCurveBezier( pCC->GetCurve( i / 3)) ;
|
||||
for ( int j = i == 0 ? 0 : 1 ; j <= 3 ; ++j) {
|
||||
Point3d pt = pSubCrv->GetControlPoint( j, &bOk) ;
|
||||
double dDist = 0 ;
|
||||
Vector3d vtPos = V_NULL ;
|
||||
if ( j > 0 && j < 3){
|
||||
DistPointCurve dpc( pt, *pSubCrv) ;
|
||||
dpc.GetDist( dDist) ;
|
||||
int nFlag = - 1 ;
|
||||
Point3d ptMinDist ;
|
||||
dpc.GetMinDistPoint( 0., ptMinDist, nFlag) ;
|
||||
vtPos = pt - ptMinDist ;
|
||||
}
|
||||
vPntInfo.emplace_back( pt, dDist, vtPos) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool
|
||||
RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& vPntRefInfo)
|
||||
{
|
||||
// se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la
|
||||
// normale alla superficie in modo da evitare cambi di concavità
|
||||
bool bSameSideAsPrev = true ;
|
||||
double dSmallDist = 5 * EPS_SMALL ;
|
||||
for ( int i = 2 ; i < ssize( vPntInfo) - 2 ; ++i) {
|
||||
// se è un punto di split o sta sulla curva vado avanti
|
||||
if ( vPntInfo[i].dDist < dSmallDist)
|
||||
continue ;
|
||||
int nPrev = vPntInfo[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ;
|
||||
double dProj = vPntInfo[i].vtPos * vPntInfo[nPrev].vtPos ;
|
||||
bSameSideAsPrev = dProj > EPS_ZERO ;
|
||||
if ( abs(dProj) < EPS_ZERO){
|
||||
int nPrevPrev = nPrev - 1 ;
|
||||
dProj = vPntInfo[i].vtPos * vPntInfo[nPrevPrev].vtPos ;
|
||||
bSameSideAsPrev = dProj > EPS_ZERO ;
|
||||
}
|
||||
if ( ! bSameSideAsPrev) {
|
||||
// devo verificare anche che sia diverso anche dal successivo ( o dal quello dopo ancora, se il successivo sta sulla curva)
|
||||
bool bCurrOrPrev = vPntInfo[i+1].dDist < EPS_ZERO ;
|
||||
int nFirst, nSecond, nThird ;
|
||||
if ( bCurrOrPrev) {
|
||||
nFirst = i ;
|
||||
nSecond = i + 1 ;
|
||||
nThird = i + 2 ;
|
||||
}
|
||||
else {
|
||||
nFirst = i - 2 ;
|
||||
nSecond = i - 1 ;
|
||||
nThird = i ;
|
||||
}
|
||||
int nNext = bCurrOrPrev ? i + 2 : i + 1 ;
|
||||
// se il successivo è diverso ho un terzetto anomalo da aggiustare
|
||||
// altrimenti ho un cambio naturale di concavità
|
||||
if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0 || vPntInfo[nNext].dDist < dSmallDist) {
|
||||
// ruoto il terzetto fino a matchare la tangente sull'altra curva
|
||||
// ruoto il punto solo se non stava già esattamente sulla SubCrv ( che suppongo essere un tratto rettilineo)
|
||||
if ( vPntInfo[nFirst].dDist > dSmallDist) {
|
||||
Vector3d vtCurr = vPntInfo[nSecond].pt - vPntInfo[nFirst].pt ;
|
||||
Vector3d vtRef = vPntRefInfo[nSecond].pt - vPntRefInfo[nFirst].pt ;
|
||||
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
|
||||
bool bDet = false ;
|
||||
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
|
||||
if ( abs(dAng) > 170)
|
||||
dAng = 180 - dAng ;
|
||||
vPnt[nFirst].Rotate( vPnt[nSecond], vtAx, dAng) ;
|
||||
}
|
||||
if ( vPntInfo[nThird].dDist > dSmallDist) {
|
||||
Vector3d vtCurr = vPntInfo[nThird].pt - vPntInfo[nSecond].pt ;
|
||||
Vector3d vtRef = vPntRefInfo[nThird].pt - vPntRefInfo[nSecond].pt ;
|
||||
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
|
||||
bool bDet = false ;
|
||||
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
|
||||
if ( abs(dAng) > 170)
|
||||
dAng = 180 - dAng ;
|
||||
vPnt[nThird].Rotate( vPnt[nSecond], vtAx, dAng) ;
|
||||
}
|
||||
if ( bCurrOrPrev)
|
||||
i += 2 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
|
||||
// Le curve vengono modificate entro una data tolleranza, in modo che
|
||||
ISurfBezier*
|
||||
RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol)
|
||||
{
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
#endif
|
||||
|
||||
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
|
||||
Point3d ptS1 = bpIsoStart.first ;
|
||||
Point3d ptS2 = bpIsoEnd.first ;
|
||||
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
|
||||
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
|
||||
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
if ( nDegU != 3)
|
||||
return nullptr ;
|
||||
// individuo quali isocurve sono state indicate come inizio e fine
|
||||
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
|
||||
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
|
||||
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
|
||||
pCrv2->Invert() ;
|
||||
double dParS1 = -1 ; double dParS2 = -1 ;
|
||||
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
|
||||
return nullptr ;
|
||||
int nUS1 = int ( dParS1) * nDegU ;
|
||||
int nUS2 = int ( dParS2) * nDegU ;
|
||||
if ( nUS1 > nUS2) {
|
||||
swap( nUS1, nUS2) ;
|
||||
swap( dParS1, dParS2) ;
|
||||
swap( ptS1, ptS2) ;
|
||||
swap( vtDir1, vtDir2) ;
|
||||
}
|
||||
PtrOwner<ICurveComposite> pCrvOrig1( ConvertCurveToComposite( pCrv1->CopyParamRange( dParS1, dParS2))) ;
|
||||
PtrOwner<ICurveComposite> pCrvOrig2( ConvertCurveToComposite( pCrv2->CopyParamRange( dParS1, dParS2))) ;
|
||||
|
||||
/////////////////////// versione con RMF
|
||||
// campiono finemente la prima curva e ottengo il punto che dovrebbe stare sull'altra curva
|
||||
Vector3d vtTang1 ; pCrvOrig1->GetStartDir( vtTang1) ;
|
||||
Frame3d frStart1 ; frStart1.Set( ptS1, vtTang1, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
|
||||
RotationMinimizingFrame rmf ; rmf.Set( pCrvOrig1, frStart1) ;
|
||||
double dLenTot = 0. ; pCrvOrig1->GetLength( dLenTot) ;
|
||||
double dStep = dLenTot / ceil( dLenTot) ;
|
||||
FRAME3DVECTOR vRMF ;
|
||||
rmf.GetFramesByStep( dStep, true, vRMF) ;
|
||||
PNTVECTOR vPnt1 ;
|
||||
PolyLine PL2 ;
|
||||
double dLenCurr = 0. ;
|
||||
double dWidth = vtDir1.Len() ;
|
||||
for ( int i = 0 ; i < ssize( vRMF) ; ++i) {
|
||||
double dPar ; pCrvOrig1->GetParamAtLength( dLenCurr, dPar) ;
|
||||
Point3d pt0 ; pCrvOrig1->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt0) ;
|
||||
Point3d pt1 = pt0 + vRMF[i].VersX() * dWidth ;
|
||||
vPnt1.push_back( pt1) ;
|
||||
PL2.AddUPoint( i, pt1) ;
|
||||
|
||||
dLenCurr += dStep ;
|
||||
}
|
||||
|
||||
CurveComposite CCToApprox2 ; CCToApprox2.FromPolyLine( PL2) ;
|
||||
Vector3d vtStart2 ; pCrvOrig2->GetStartDir( vtStart2) ;
|
||||
Vector3d vtEnd2 ; pCrvOrig2->GetEndDir( vtEnd2) ;
|
||||
PtrOwner<ICurveComposite> pCC2( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox2, 0.05, vtStart2, vtEnd2))) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// dalla seconda ricostruisco la prima
|
||||
Vector3d vtTang2 ; pCC2->GetStartDir( vtTang2) ;
|
||||
Frame3d frStart2 ; frStart2.Set( bpIsoStart.second, vtTang2, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
|
||||
RotationMinimizingFrame rmf2 ; rmf2.Set( pCC2, frStart2) ;
|
||||
double dLenTot2 = 0. ; pCC2->GetLength( dLenTot2) ;
|
||||
double dStep2 = dLenTot2 / ceil( dLenTot2) ;
|
||||
FRAME3DVECTOR vRMF2 ;
|
||||
rmf2.GetFramesByStep( dStep2, true, vRMF2) ;
|
||||
PNTVECTOR vPnt0 ;
|
||||
PolyLine PL1 ;
|
||||
double dLenCurr2 = 0. ;
|
||||
for ( int i = 0 ; i < ssize( vRMF2) ; ++i) {
|
||||
double dPar ; pCC2->GetParamAtLength( dLenCurr2, dPar) ;
|
||||
Point3d pt1 ; pCC2->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt1) ;
|
||||
Point3d pt0 = pt1 - vRMF2[i].VersX() * dWidth ;
|
||||
vPnt0.push_back( pt0) ;
|
||||
PL1.AddUPoint( i, pt0) ;
|
||||
|
||||
dLenCurr2 += dStep2 ;
|
||||
}
|
||||
|
||||
CurveComposite CCToApprox1 ; CCToApprox1.FromPolyLine( PL1) ;
|
||||
Vector3d vtStart1 ; pCrvOrig1->GetStartDir( vtStart1) ;
|
||||
Vector3d vtEnd1 ; pCrvOrig1->GetEndDir( vtEnd1) ;
|
||||
PtrOwner<ICurveComposite> pCC1( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox1, 0.05, vtStart1, vtEnd1))) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
for( int i = 0 ; i < ssize( vPnt1) ; ++i) {
|
||||
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ;
|
||||
VT.push_back( Release( pPT)) ;
|
||||
}
|
||||
for( int i = 0 ; i < ssize( vPnt0) ; ++i) {
|
||||
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt0[i]) ;
|
||||
VT.push_back( Release( pPT)) ;
|
||||
}
|
||||
VT.push_back( pCC1->Clone()) ;
|
||||
VT.push_back( pCC2->Clone()) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_RMF.nge") ;
|
||||
#endif
|
||||
|
||||
// controllo di essere rimasto in tolleranza
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
|
||||
// creo una surf di bezier uguale a quella di partenza, ma a cui cambio la parte da modificare
|
||||
PtrOwner<SurfBezier> pNewSurf( CreateBasicSurfBezier()) ;
|
||||
int nNewCrvs = pCC1->GetCurveCount() ;
|
||||
if ( pCC2->GetCurveCount() != nNewCrvs)
|
||||
return nullptr ;
|
||||
int nDiff = nNewCrvs - pCrvOrig1->GetCurveCount() ;
|
||||
pNewSurf->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
// copio la parte uguale
|
||||
for ( int i = 0 ; i < nSpanU * nDegU + 1 ; ++i) {
|
||||
if ( i > nUS1 && i < nUS2)
|
||||
continue ;
|
||||
bool bOk = false ;
|
||||
Point3d pt = pSurfBz->GetControlPoint( i, 0, &bOk) ;
|
||||
int nNewI = i ;
|
||||
if ( i > nUS2)
|
||||
nNewI = i + nDiff ;
|
||||
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
|
||||
pt = pSurfBz->GetControlPoint( i, 1, &bOk) ;
|
||||
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
|
||||
}
|
||||
// aggiungo la parte diversa
|
||||
for ( int i = 0 ; i < nNewCrvs * nDegU + 1 ; ++i) {
|
||||
int nSub = i / 3 ;
|
||||
int nPnt = i % 3 ;
|
||||
if ( nSub == nNewCrvs) {
|
||||
--nSub ;
|
||||
nPnt = 3 ;
|
||||
}
|
||||
const ICurveBezier* pSubCrv1 = GetCurveBezier( pCC1->GetCurve( nSub)) ;
|
||||
Point3d pt = pSubCrv1->GetControlPoint( nPnt) ;
|
||||
int nNewI = i + nUS1 ;
|
||||
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
|
||||
const ICurveBezier* pSubCrv2 = GetCurveBezier( pCC2->GetCurve( nSub)) ;
|
||||
pt = pSubCrv2->GetControlPoint( nPnt) ;
|
||||
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
|
||||
}
|
||||
|
||||
return Release( pNewSurf) ;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
|
||||
// Le curve vengono modificate entro una data tolleranza, in modo che
|
||||
ISurfBezier*
|
||||
RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol, int nType)
|
||||
{
|
||||
if ( nType == RegolarizeType::RMF)
|
||||
return RegolarizeBordersLocallyRMF( pSurfBz, bpIsoStart, bpIsoEnd, dTol) ;
|
||||
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
#endif
|
||||
|
||||
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
|
||||
Point3d ptS1 = bpIsoStart.first ;
|
||||
Point3d ptS2 = bpIsoEnd.first ;
|
||||
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
|
||||
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
|
||||
//double dInterpolateAngTol = 4 ;
|
||||
//double dAngInterp = 0 ;
|
||||
//vtDir1.GetAngle( vtDir2, dAngInterp) ;
|
||||
//bool bInterpolate = dAngInterp > dInterpolateAngTol ;
|
||||
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
if ( nDegU != 3)
|
||||
return nullptr ;
|
||||
// individuo quali isocurve sono state indicate come inizio e fine
|
||||
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
|
||||
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
|
||||
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
|
||||
pCrv2->Invert() ;
|
||||
double dParS1 = -1 ; double dParS2 = -1 ;
|
||||
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
|
||||
return nullptr ;
|
||||
int nUS1 = int ( dParS1) * nDegU ;
|
||||
int nUS2 = int ( dParS2) * nDegU ;
|
||||
bool bInverted = false ;
|
||||
if ( nUS1 > nUS2) {
|
||||
swap( nUS1, nUS2) ;
|
||||
swap( dParS1, dParS2) ;
|
||||
swap( ptS1, ptS2) ;
|
||||
swap( vtDir1, vtDir2) ;
|
||||
bInverted = true ;
|
||||
}
|
||||
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
|
||||
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ;
|
||||
double dLen = 0 ; pCrvOrig1->GetLength( dLen) ;
|
||||
|
||||
///// versione con correzioni a mano
|
||||
Point3d ptPrevS = ptS1 ;
|
||||
Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ;
|
||||
Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ;
|
||||
Point3d ptBez ; Vector3d vtNCurr ;
|
||||
pSurfBz->GetPointNrmD1D2( dParS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNCurr) ;
|
||||
int nPoints = ( nUS2 - nUS1) * nDegU + 1 ;
|
||||
PNTVECTOR vPnt0 ; vPnt0.reserve( nPoints) ; vPnt0.push_back( ptPrevS) ;
|
||||
PNTVECTOR vPnt1 ; vPnt1.reserve( nPoints) ; vPnt1.push_back( ptPrevE) ;
|
||||
// salvo il secondo punto di controllo della patch
|
||||
bool bOk = false ;
|
||||
Point3d ptSecond1Curr = pSurfBz->GetControlPoint( nUS1 + 1, 0, &bOk) ;
|
||||
vPnt0.push_back( ptSecond1Curr) ;
|
||||
Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ;
|
||||
vPnt1.push_back( ptSecond2Curr) ;
|
||||
// scorro le isocurve di separazione tra patch
|
||||
for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) {
|
||||
// recupero precedente e successivo
|
||||
Point3d ptThird1Prev = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ;
|
||||
Point3d ptThird2Prev = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ;
|
||||
Point3d ptSecond1Next = pSurfBz->GetControlPoint( i + 1, 0, &bOk) ;
|
||||
Point3d ptSecond2Next = pSurfBz->GetControlPoint( i + 1, 1, &bOk) ;
|
||||
// recupero corrente e verifico la torsione
|
||||
Point3d ptCurr1 = pSurfBz->GetControlPoint( i, 0, &bOk) ;
|
||||
Point3d ptCurr2 = pSurfBz->GetControlPoint( i, 1, &bOk) ;
|
||||
Vector3d vtIsoCurr = ptCurr2 - ptCurr1 ;
|
||||
double dDist = vtIsoCurr.Len() ;
|
||||
vtIsoCurr.Normalize() ;
|
||||
//Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ;
|
||||
Vector3d vtDirCurr = ptSecond1Next - ptCurr1 ; vtDirCurr.Normalize() ;
|
||||
double dLenCurr = 0 ; pCrvOrig1->GetLengthAtParam( i, dLenCurr) ;
|
||||
double dCoeff = dLenCurr / dLen ;
|
||||
Vector3d vtIsoInterp = Media( vtDir1, vtDir2, dCoeff) ; vtIsoInterp.Normalize() ;
|
||||
bool bDet = false ;
|
||||
//double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoPrev, vtDirPrev, dAng, bDet) ;
|
||||
double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoInterp, vtDirCurr, dAng, bDet) ;
|
||||
vtNCurr = vtDirCurr ^ vtIsoCurr ; vtNCurr.Rotate( vtDirCurr, dAng) ;
|
||||
double dSinAngTol = sin( 5 * DEGTORAD) ;
|
||||
Vector3d vtPrev1 = ptCurr1 - ptThird1Prev ; vtPrev1.Normalize() ;
|
||||
Vector3d vtNext1 = ptSecond1Next - ptCurr1 ; vtNext1.Normalize() ;
|
||||
bool bAngularPoint1 = ! AreSameVectorEpsilon( vtPrev1, vtNext1, dSinAngTol) ;
|
||||
Vector3d vtPrev2 = ptCurr2 - ptThird2Prev ; vtPrev2.Normalize() ;
|
||||
Vector3d vtNext2 = ptSecond2Next - ptCurr2 ; vtNext2.Normalize() ;
|
||||
bool bAngularPoint2 = ! AreSameVectorEpsilon( vtPrev2, vtNext2, dSinAngTol) ;
|
||||
if ( abs( dAng) > 0) {
|
||||
// se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente
|
||||
// allora prendo il penultimo punto della curva precedente, il punto di joint e il secondo della prossima e li sposto lungo la normale della superficie
|
||||
dDist *= dAng * DEGTORAD / 2 ;
|
||||
if ( ! bAngularPoint1) {
|
||||
// se non ho un punto angoloso muovo tutto il terzetto insieme
|
||||
ptThird1Prev -= vtNCurr * dDist ;
|
||||
ptSecond1Next -= vtNCurr * dDist ;
|
||||
ptCurr1 -= vtNCurr * dDist ;
|
||||
}
|
||||
else {
|
||||
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
|
||||
DistPointLine dpl( ptCurr1, ptThird1Prev, ptSecond1Next, true) ;
|
||||
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
|
||||
Vector3d vtCorrDir = ptMinDist - ptCurr1 ; vtCorrDir.Normalize() ;
|
||||
double dProjDir = vtNCurr * vtCorrDir ;
|
||||
if ( dProjDir < 0)
|
||||
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv0 near an angular point") ;
|
||||
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr1)) ;
|
||||
ptCurr1 -= vtCorrDir * dDistCorr ;
|
||||
}
|
||||
if ( ! bAngularPoint2) {
|
||||
ptThird2Prev += vtNCurr * dDist ;
|
||||
ptSecond2Next += vtNCurr * dDist ;
|
||||
ptCurr2 += vtNCurr * dDist ;
|
||||
}
|
||||
else {
|
||||
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
|
||||
DistPointLine dpl( ptCurr2, ptThird2Prev, ptSecond2Next, true) ;
|
||||
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
|
||||
Vector3d vtCorrDir = ptMinDist - ptCurr2 ; vtCorrDir.Normalize() ;
|
||||
double dProjDir = vtNCurr * vtCorrDir ;
|
||||
if ( dProjDir < 0)
|
||||
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv1 near an angular point") ;
|
||||
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr2)) ;
|
||||
ptCurr2 += vtCorrDir * dDistCorr ;
|
||||
}
|
||||
}
|
||||
vPnt0.push_back( ptThird1Prev) ;
|
||||
vPnt0.push_back( ptCurr1) ;
|
||||
vPnt0.push_back( ptSecond1Next) ;
|
||||
|
||||
vPnt1.push_back( ptThird2Prev) ;
|
||||
vPnt1.push_back( ptCurr2) ;
|
||||
vPnt1.push_back( ptSecond2Next) ;
|
||||
|
||||
//vtIsoPrev = ptCurr2 - ptCurr1 ; vtIsoPrev.Normalize() ;
|
||||
//vtNPrev = ( ptSecond1Next - ptCurr1) ^ vtIsoPrev ; vtNPrev.Normalize() ;
|
||||
}
|
||||
// aggiungo gli ultimi due punti
|
||||
Point3d ptThird1Prev = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ;
|
||||
vPnt0.push_back( ptThird1Prev) ;
|
||||
Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ;
|
||||
vPnt0.push_back( ptFourth1Curr) ;
|
||||
Point3d ptThird2Prev = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ;
|
||||
vPnt1.push_back( ptThird2Prev) ;
|
||||
Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ;
|
||||
vPnt1.push_back( ptFourth2Curr) ;
|
||||
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
|
||||
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
|
||||
cb1->SetControlPoint( 0, vPnt0[i]) ;
|
||||
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
|
||||
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
|
||||
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
|
||||
pCC1->AddCurve( Release( cb1)) ;
|
||||
|
||||
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
|
||||
cb2->SetControlPoint( 0, vPnt1[i]) ;
|
||||
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
|
||||
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
|
||||
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
|
||||
pCC2->AddCurve( Release( cb2)) ;
|
||||
}
|
||||
|
||||
////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.push_back( pCC1->Clone()) ;
|
||||
VT.push_back( pCC2->Clone()) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ;
|
||||
#endif
|
||||
|
||||
// ora verifico l'eventuale presenza di cambi di concavità non desiderati
|
||||
// se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo
|
||||
// da matchare la tangente dell'altra curva
|
||||
PNTINFOVECTOR vPntInfo1, vPntInfo2 ;
|
||||
FillPntInfo( vPnt0, pCC1, vPntInfo1) ;
|
||||
FillPntInfo( vPnt1, pCC2, vPntInfo2) ;
|
||||
|
||||
RemoveInflexionPoints( vPnt0, vPntInfo1, vPntInfo2) ;
|
||||
RemoveInflexionPoints( vPnt1, vPntInfo2, vPntInfo1) ;
|
||||
|
||||
pCC1->Clear() ;
|
||||
pCC2->Clear() ;
|
||||
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
|
||||
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
|
||||
cb1->SetControlPoint( 0, vPnt0[i]) ;
|
||||
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
|
||||
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
|
||||
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
|
||||
pCC1->AddCurve( Release( cb1)) ;
|
||||
|
||||
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
|
||||
cb2->SetControlPoint( 0, vPnt1[i]) ;
|
||||
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
|
||||
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
|
||||
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
|
||||
pCC2->AddCurve( Release( cb2)) ;
|
||||
}
|
||||
|
||||
// controllo di essere rimasto in tolleranza
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<ISurfBezier> pNewSurf( pSurfBz->Clone()) ;
|
||||
// aggiorno i punti di controllo della superficie di bezier
|
||||
for ( int i = 0 ; i < ssize( vPnt0) ; ++i) {
|
||||
pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
|
||||
pNewSurf->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ;
|
||||
}
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
VT.push_back( Release(pCC1)) ;
|
||||
VT.push_back( Release(pCC2)) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
|
||||
#endif
|
||||
|
||||
return Release( pNewSurf) ;
|
||||
}
|
||||
@@ -1770,6 +1770,8 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
|
||||
if ( bInverse)
|
||||
nTotSurf += 4 ;
|
||||
if ( bSmallMovement)
|
||||
nTotSurf += 2 ;
|
||||
|
||||
int nSurfInd = 0 ;
|
||||
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
||||
|
||||
+10
-1
@@ -1014,8 +1014,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
||||
|
||||
// aggiungo la curva alla lista degli offset
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) {
|
||||
// forzo chiusura
|
||||
if ( ! pCrvOffs->IsClosed()) {
|
||||
Point3d ptS ; pCrvOffs->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrvOffs->GetEndPoint( ptE) ;
|
||||
if ( SqDist( ptS, ptE) > 100. * SQ_EPS_SMALL)
|
||||
return false ;
|
||||
pCrvOffs->Close() ;
|
||||
}
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni dedicata agli offset
|
||||
|
||||
Reference in New Issue
Block a user