EgtGeomKernel :
- aggiornamento versione di RuledSmooth. - aggiunta controlli. - prima versione della regolarizzazione di curve bezier composte.
This commit is contained in:
+396
-139
@@ -57,6 +57,7 @@
|
||||
|| SAVEFAILEDTREE || SAVELIMITSURF || SAVEPACEDISO
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
std::vector<Color> vCol ;
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
@@ -5896,15 +5897,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 +5936,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 +5964,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 +5972,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 +6026,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 +6142,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 +6151,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 +6170,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 +6200,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 +6216,16 @@ 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 ;
|
||||
}
|
||||
@@ -6110,75 +6239,188 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
|
||||
return false ;
|
||||
|
||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto ( ne basta uno dei due fuori dalla tolleranza)
|
||||
const double COS_LIMIT = cos( 50. * DEGTORAD) ;
|
||||
Vector3d vtStart1 ; pSubEdge1->GetStartDir( vtStart1) ;
|
||||
Vector3d vtEnd1 ; pSubEdge1->GetEndDir( vtEnd1) ;
|
||||
bool bSplit = ( vtStart1 * vtEnd1 < COS_LIMIT) ;
|
||||
if ( ! bSplit) {
|
||||
Vector3d vtStart2 ; pSubEdge2->GetStartDir( vtStart2) ;
|
||||
Vector3d vtEnd2 ; pSubEdge2->GetEndDir( vtEnd2) ;
|
||||
bSplit = ( vtStart2 * vtEnd2 < COS_LIMIT) ;
|
||||
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) ;
|
||||
}
|
||||
// Sew non devo Splittare, non faccio nulla
|
||||
if ( ! bSplit)
|
||||
|
||||
// --- 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 ;
|
||||
|
||||
double dLen1 ; pSubEdge1->GetLength( dLen1) ;
|
||||
double dLen2 ; pSubEdge2->GetLength( dLen2) ;
|
||||
// Individuo sulle due curve i punti a curvatura massima e definisco una Curva di Sync tra essi
|
||||
Point3d ptKMax1, ptKMax2 ;
|
||||
double dUKMax1, dUKMin1 ;
|
||||
double dKMax1 = - INFINITO + 1, dKMax2 = - INFINITO + 1 ;
|
||||
const int NUM_SAMPLE_PNT = 20 ;
|
||||
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||
// Ricavo i parametri
|
||||
double dU1 ; pSubEdge1->GetParamAtLength( Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1), dU1) ;
|
||||
double dU2 ; pSubEdge2->GetParamAtLength( Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2), dU2) ;
|
||||
// Calcolo la Curvatura
|
||||
Point3d ptSub1 ; Vector3d vtSub1Der1, vtSub1Der2 ;
|
||||
pSubEdge1->GetPointD1D2( dU1, ICurve::FROM_MINUS, ptSub1, &vtSub1Der1, &vtSub1Der2) ;
|
||||
double dK1 = ( vtSub1Der1 ^ vtSub1Der2).Len() / max( EPS_SMALL, Pow( vtSub1Der1.Len(), 3)) ;
|
||||
if ( dK1 > dKMax1) {
|
||||
dKMax1 = dK1 ;
|
||||
ptKMax1 = ptSub1 ;
|
||||
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)) ;
|
||||
}
|
||||
Point3d ptSub2 ; Vector3d vtSub2Der1, vtSub2Der2 ;
|
||||
pSubEdge2->GetPointD1D2( dU2, ICurve::FROM_MINUS, ptSub2, &vtSub2Der1, &vtSub2Der2) ;
|
||||
double dK2 = ( vtSub2Der1 ^ vtSub2Der2).Len() / max( EPS_SMALL, Pow( vtSub2Der1.Len(), 3)) ;
|
||||
if ( dK2 > dKMax2) {
|
||||
dKMax2 = dK2 ;
|
||||
ptKMax2 = ptSub2 ;
|
||||
if ( bErase) {
|
||||
vSyncLines.erase( vSyncLines.begin() + i) ;
|
||||
-- i ;
|
||||
}
|
||||
}
|
||||
if ( vSyncLines.empty())
|
||||
return true ;
|
||||
|
||||
// Avendo fissato il punto a curvatura massima su entrambe le curve, cerco di sportarmi lungo la seconda curva
|
||||
// ( nell'intorno del suo punto a massima curvatura) per cercare una direzione coerente
|
||||
Point3d ptCurr1 ; Vector3d vtCurr1 ;
|
||||
|
||||
const double MAX_DIST = 2.5 ;
|
||||
double dLenAtK2 ; pSubEdge2->GetLengthAtPoint( ptKMax2, dLenAtK2) ;
|
||||
//double dLimInfLen = Clamp( dLenAtK2 - MAX_DIST, 0., dLen2) ;
|
||||
//double dLimSupLen = Clamp( dLenAtK2 + MAX_DIST, 0., dLen2) ;
|
||||
//int nSamplePnt = int( ceil( NUM_SAMPLE_PNT / 2.)) ;
|
||||
//double dMinCos = -1 - EPS_SMALL ;
|
||||
//for ( int i = 0 ; i <= nSamplePnt ; ++ i) {
|
||||
// double dCurrLen = dLimInfLen + i * ( dLimSupLen - dLimInfLen) / nSamplePnt ;
|
||||
// double dU ; pSubEdge2->GetParamAtLength( dCurrLen, dU) ;
|
||||
// Point3d ptCurr ; Vector3d vtTan ;
|
||||
// pSubEdge2->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr, &vtTan) ; vtTan.Normalize() ;
|
||||
// double dCos = ( vtTan *
|
||||
//}
|
||||
|
||||
// Verifico che entrambi gli estremi della Linea di Sync siano distanti dai bordi della Quadrangolazione corrente
|
||||
double dLenAtK1 ; pSubEdge1->GetLengthAtPoint( ptKMax1, dLenAtK1) ;
|
||||
const double DIST_TOL = 2. ;
|
||||
if ( ( dLenAtK1 > DIST_TOL - EPS_SMALL && dLenAtK1 < dLen1 - DIST_TOL + EPS_SMALL) &&
|
||||
( dLenAtK2 > DIST_TOL - EPS_SMALL && dLenAtK2 < dLen2 - DIST_TOL + EPS_SMALL)) {
|
||||
// Verifico che la Linea di Sicnronizzazione non tagli in diagonale la Quadrangolazione corrente
|
||||
if ( ( dLenAtK1 < dLen1 - dLenAtK1 && dLenAtK2 < dLen2 - dLenAtK2) ||
|
||||
( dLenAtK1 > dLen1 - dLenAtK1 && dLenAtK2 > dLen2 - dLenAtK2))
|
||||
vSyncLines.emplace_back( make_pair( ptKMax1, ptKMax2)) ;
|
||||
// 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 ;
|
||||
@@ -6189,12 +6431,20 @@ bool
|
||||
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen)
|
||||
{
|
||||
// converto in bezier le curve iniziali
|
||||
PtrOwner<ICurveBezier> pCrvEdge1( GetCurveBezier( CurveToBezierCurve( pCurve0, 3, false))) ;
|
||||
PtrOwner<ICurveBezier> pCrvEdge2( GetCurveBezier( CurveToBezierCurve( pCurve1, 3, false))) ;
|
||||
PtrOwner<ICurve> pCrvEdge1( CurveToBezierCurve( pCurve0, 3, false)) ;
|
||||
PtrOwner<ICurve> pCrvEdge2( 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 dSampleDist = 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) ;
|
||||
@@ -6207,10 +6457,10 @@ 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) {
|
||||
BIPNTVECTOR vSyncLines ;
|
||||
while ( dLenPrev1 + dSampleDist < 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) ;
|
||||
dLenCurr1 = Clamp( dLenPrev1 + dSampleDist, 0., dLen1) ;
|
||||
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
@@ -6269,7 +6519,7 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
}
|
||||
// Verifico di non essermi allontanato troppo
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkPlane = ( dLen < dLenPrev2 + 2. * dSampleLen) ;
|
||||
bOkPlane = ( dLen < dLenPrev2 + 2. * dSampleDist) ;
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
@@ -6279,11 +6529,11 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
// Verifico di non essermi allontanato troppo
|
||||
if ( bOkMinDist) {
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkMinDist = ( dLen < dLenPrev2 + 2. * dSampleLen) ;
|
||||
bOkMinDist = ( dLen < dLenPrev2 + 2. * dSampleDist) ;
|
||||
}
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Aumento la distanza corrente del passo di campionamento
|
||||
double dLen = Clamp( dLenPrev2 + dSampleLen, 0., dLen2) ;
|
||||
double dLen = Clamp( dLenPrev2 + dSampleDist, 0., dLen2) ;
|
||||
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
|
||||
}
|
||||
}
|
||||
@@ -6296,10 +6546,10 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
// 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)
|
||||
// Se fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSampleLen, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSampleLen, dLenPrev2, dLen2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSampleDist, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSampleDist, dLenPrev2, dLen2) ;
|
||||
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
|
||||
const int NUM_STEP = 20 ;
|
||||
double dMinCos = - 1. - EPS_ZERO ;
|
||||
@@ -6329,30 +6579,32 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
pGeomDB->AddGeoObj( GDB_ID_NULL, nLay2, Release( vtGeo2)) ;
|
||||
#endif
|
||||
|
||||
// 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)) ;
|
||||
#if SAVEPACEDISO
|
||||
// Inserisco le curve di sincronizzazione nel Layer di destinazine
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ;
|
||||
vGeo.push_back( Release( pLine)) ;
|
||||
vCol.push_back( LIME) ;
|
||||
#endif
|
||||
|
||||
// --- 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) ;
|
||||
#if SAVEPACEDISO
|
||||
for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vEdgeSyncLines[i].first, vEdgeSyncLines[i].second) ;
|
||||
vGeo.push_back( Release( pLine)) ;
|
||||
vCol.push_back( GREEN) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
//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è si fa questa cosa ? 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.
|
||||
// --- 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) ;
|
||||
@@ -6382,19 +6634,24 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
SyncLinePrev = SyncLineNext ;
|
||||
}
|
||||
}
|
||||
//for ( int i = 0 ; i < ssize( vTwistSyncLines) ; ++ i) {
|
||||
// PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vTwistSyncLines[i].first, vTwistSyncLines[i].second) ;
|
||||
// int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
// pGeomDB->SetMaterial( nNewId, OLIVE) ;
|
||||
//}
|
||||
|
||||
#if SAVEPACEDISO
|
||||
for ( int i = 0 ; i < ssize( vTwistSyncLines) ; ++ i) {
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vTwistSyncLines[i].first, vTwistSyncLines[i].second) ;
|
||||
vGeo.push_back( Release( pLine)) ;
|
||||
vCol.push_back( OLIVE) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user