Merge branch 'NewRuled'

This commit is contained in:
Daniele Bariletti
2026-04-10 18:20:59 +02:00
4 changed files with 420 additions and 28 deletions
+36
View File
@@ -733,6 +733,42 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, double dSampleLen)
{
// verifica parametri
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
if ( pCurve1->GetType() != CRV_BEZIER)
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
else
pCC1->AddCurve( pCurve1->Clone()) ;
if ( IsNull( pCC1) || ! pCC1->IsValid())
return nullptr ;
// se la curva è già una bezier singola la tengo, sennò la converto
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
if ( pCurve2->GetType() != CRV_BEZIER)
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
else
pCC2->AddCurve( pCurve2->Clone()) ;
if ( IsNull( pCC2) || ! pCC2->IsValid())
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen))
return nullptr ;
// restituisco la superficie
return Release( pSbz) ;
}
//-------------------------------------------------------------------------------
ISurfBezier*
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
+382 -27
View File
@@ -52,7 +52,9 @@
#define SAVEMATCHCURVES 0
#define SAVEFAILEDTREE 0
#define SAVELIMITSURF 0
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES || SAVEFAILEDTREE || SAVELIMITSURF
#define SAVEPACEDISO 1
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES \
|| SAVEFAILEDTREE || SAVELIMITSURF || SAVEPACEDISO
#include "/EgtDev/Include/EGkGeoObjSave.h"
std::vector<IGeoObj*> vGeo ;
#endif
@@ -5213,19 +5215,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
i = c ;
}
}
//// faccio un merge di regioni adiacenti di mismatch
//int nCurr = 0, nNext = 1 ;
//while ( nNext < ssize( vMismatch0)) {
// if ( vMismatch0[nNext].first - vMismatch0[nCurr].second < 2 + EPS_SMALL) {
// vMismatch0[nCurr].second = vMismatch0[nNext].second ;
// }
// else {
// ++nCurr ;
// vMismatch0[nCurr] = vMismatch0[nNext] ;
// }
// ++nNext ;
//}
//vMismatch0.resize( nCurr + 1) ;
DBLVECTOR vdDistMismatch1 ;
int nPnt1 = CrvU1.GetCurveCount() ;
@@ -5248,19 +5237,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
i = c ;
}
}
//// faccio un merge di regioni adiacenti di mismatch
//nCurr = 0, nNext = 1 ;
//while ( nNext < ssize( vMismatch1)) {
// if ( vMismatch1[nNext].first - vMismatch1[nCurr].second < 2 + EPS_SMALL) {
// vMismatch1[nCurr].second = vMismatch1[nNext].second ;
// }
// else {
// ++nCurr ;
// vMismatch1[nCurr] = vMismatch1[nNext] ;
// }
// ++nNext ;
//}
//vMismatch1.resize( nCurr + 1) ;
// verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline)
BOOLVECTOR vEdgeSplit0, vEdgeSplit1 ;
@@ -5920,6 +5896,385 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
return true ;
}
struct SharpEdge {
double dParU ;
Point3d ptEdge ;
Vector3d vtTanPrev, vtTanAft ;
SharpEdge( double dU, const Point3d ptE, const Vector3d& vtTP, const Vector3d& vtTA)
: dParU( dU), ptEdge( ptE), vtTanPrev( vtTP), vtTanAft( vtTA) {}
} ;
typedef vector<SharpEdge> SHARPEDGEVECTOR ;
static bool
CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite* pCompoSubEdge, const SHARPEDGEVECTOR& vSharpSubEdge,
BIPNTVECTOR& vSyncLines)
{
vSyncLines.clear() ;
// Verifico la validità del SubEdge su cui trovare il punto di Sincronizzazione
if ( pCompoSubEdge == nullptr || ! pCompoSubEdge->IsValid())
return false ;
// Se non ho spigoli da controllare, non devo fare nulla
if ( vSharpEdge.empty())
return true ;
// 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)) ;
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 > dUPrevSubEdge) {
if ( nIndParCloser == -1)
nIndParCloser = nInfo ;
double dSqDist = SqDist( mySharpEdge.ptEdge, 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( 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. ;
}
}
}
// Verifico se tale parametro può essere avvicinato ad uno Spigolo presente sulla curva
if ( ! vSharpSubEdge.empty()) {
const double EDGE_LEN_TOL = 5. ;
for ( const SharpEdge& mySharpSubEdge : vSharpSubEdge) {
// Se la linea di sincronizzazione è progressiva in parametro (ovvero non si attorciglia)
if ( mySharpSubEdge.dParU > dUPrevSubEdge) {
double dLenSub ; pCompoSubEdge->GetLengthAtParam( mySharpSubEdge.dParU, dLenSub) ;
double dLenSync ; pCompoSubEdge->GetLengthAtParam( dUCurrSubEdge, dLenSync) ;
// E Sufficientemente vicina ad uno Spigolo sull'altra
if ( abs( dLenSync - dLenSub) < EDGE_LEN_TOL) {
// Sposto il suo punto finale sullo Spigolo
dUCurrSubEdge = mySharpSubEdge.dParU ;
break ; // prendo la prima dato che sono ordinate per parametro
}
}
}
}
// Definisco una nuova linea dallo spigolo corrente al parametro trovato sull'altra curva di bordo
vSyncLines.emplace_back( mySharpEdge.ptEdge, P_INVALID) ;
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_MINUS, vSyncLines.back().second) ;
// aggiorno i parametri
dUPrevSubEdge = dUCurrSubEdge ;
}
return true ;
}
// ---------------------------------------------------------------------------
// Debug [Gestione Edge in Quadrangolazioni]
static bool
ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines)
{
// Verifica validità delle curve
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
return false ;
// Recupero il numero delle curve dei Sottotratti correnti dei bordi
int nCrv1 = pSubEdge1->GetCurveCount() ;
int nCrv2 = pSubEdge2->GetCurveCount() ;
if ( nCrv1 < 2 && nCrv2 < 2)
return true ;
const double COS_EDGE_LIMIT = cos( 35. * DEGTORAD) ;
SHARPEDGEVECTOR vSharpEdges1 ; vSharpEdges1.reserve( max( 0, nCrv1 - 1)) ;
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
if ( nCrv1 > 1) {
Point3d ptCurr1 ;
// Scorro le sottocurve
for ( int nCrv = 0 ; nCrv < nCrv1 - 1 ; ++ nCrv) {
// Recupero il parametro corrente sulla curva ( estremo finale)
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) ;
// Verifico se ho uno spigolo
vtTanPrev.Normalize() ;
vtTanAft.Normalize() ;
if ( vtTanPrev * vtTanAft < COS_EDGE_LIMIT)
vSharpEdges1.emplace_back( dU, ptCurr1, vtTanPrev, vtTanAft) ;
}
}
// --- Cerco gli spigoli sul Sottotratto del secondo bordo
// Se la Curva B ha solo una sottocurva, non faccio nulla
if ( nCrv2 > 1) {
Point3d ptCurr2 ;
// Scorro le sottocurve
for ( int nCrv = 0 ; nCrv < nCrv2 - 1 ; ++ nCrv) {
// Recupero il parametro corrente sulla curva ( estremo finale)
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) ;
// Verifico se ho uno spigolo
vtTanPrev.Normalize() ;
vtTanAft.Normalize() ;
if ( vtTanPrev * vtTanAft < COS_EDGE_LIMIT)
vSharpEdges2.emplace_back( dU, ptCurr2, vtTanPrev, vtTanAft) ;
}
}
// Se non ho alcuno spigolo, allora non faccio nulla
if ( vSharpEdges1.empty() && vSharpEdges2.empty())
return true ;
// Recupero le Curve di Sincronizzazione dell'Edge 1 sull'Edge 2
BIPNTVECTOR vSyncLines1 ;
CalcSyncPointFromEdge( vSharpEdges1, pSubEdge2, vSharpEdges2, vSyncLines1) ;
// Recupero le Curve di Sincronizzazione dell'Edge 2 sull'Egde 1
BIPNTVECTOR vSyncLines2 ;
CalcSyncPointFromEdge( vSharpEdges2, pSubEdge1, vSharpEdges1, vSyncLines2) ;
// Rimuovo eventuali linee sovrapposte ( le rimuovo da vSyncLines2)
const double TOL = 250. * EPS_SMALL ;
erase_if( vSyncLines2, [&]( const BIPOINT& SyncLine2) {
return any_of( vSyncLines1.begin(), vSyncLines1.end(), [&]( const BIPOINT& SyncLine1) {
return ( AreSamePointEpsilon( SyncLine1.first, SyncLine2.second, TOL) &&
AreSamePointEpsilon( SyncLine1.second, SyncLine2.first, TOL)) ;
}) ;
}) ;
// Ordino tutte le curve in base al parametro dU della curva principale
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),
vSyncLinesPar.empty() ? 0. : vSyncLinesPar.back().second)) ;
pSubEdge1->GetParamAtPoint( SyncLine1.first, vSyncLinesPar.back().second, TOL) ;
}
for ( BIPOINT& SyncLine2 : vSyncLines2) {
vSyncLinesPar.emplace_back( make_pair( make_pair( SyncLine2.second, SyncLine2.first),
vSyncLinesPar.empty() ? 0. : vSyncLinesPar.back().second)) ;
pSubEdge1->GetParamAtPoint( SyncLine2.second, vSyncLinesPar.back().second, TOL) ;
}
sort( vSyncLinesPar.begin(), vSyncLinesPar.end(), []( const auto& SyncLineParA, const auto& SyncLineParB) {
return SyncLineParA.second < SyncLineParB.second ;
}) ;
// Restituisco il risultato
for ( auto Iter = vSyncLinesPar.begin() ; Iter != vSyncLinesPar.end() ; ++ Iter)
vSyncLines.emplace_back( Iter->first) ;
return true ;
}
//----------------------------------------------------------------------------
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))) ;
if ( IsNull( pCrvEdge1) || IsNull( pCrvEdge2))
return false ;
// Recupero parametri iniziali
double dLen1 ; pCrvEdge1->GetLength( dLen1) ;
double dLen2 ; pCrvEdge2->GetLength( dLen2) ;
double dUS1, dUE1 ; pCrvEdge1->GetDomain( dUS1, dUE1) ;
double dUS2, dUE2 ; pCrvEdge2->GetDomain( dUS2, dUE2) ;
double dLenPrev1 = 0., dLenCurr1 = 0. ;
double dLenPrev2 = 0., dLenCurr2 = 0. ;
double dUPrev1 = 0., dUCurr1 = 0. ;
double dUPrev2 = 0., dUCurr2 = 0. ;
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) ;
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
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
// --- 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) ;
}
}
// Recupero il punto corrente e la direzione tangente sul secondo bordo
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
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
// 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)) ;
// --- 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
PtrOwner<ICurveComposite> pCrvQuad1( ConvertCurveToComposite( pCrvEdge1->CopyParamRange( dUPrev1, dUCurr1))) ;
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
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) ;
//}
// Aggiorno i parametri
ptPrev1 = ptCurr1 ; dUPrev1 = dUCurr1 ; dLenPrev1 = dLenCurr1 ;
ptPrev2 = ptCurr2 ; dUPrev2 = dUCurr2 ; dLenPrev2 = dLenCurr2 ;
}
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vEdgeSyncLines) ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const
+1
View File
@@ -154,6 +154,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool RemoveCollapsedSpans( void) override ;
bool SwapParameters( void) ;
bool LimitSurfToTrimmedRegion( void) override ;
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+1 -1
View File
@@ -4219,7 +4219,7 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
// Se non ho punti di controllo forzati
if ( vSyncPoints.empty()) {
pSurfBz.Set( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol)) ;
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, 10)) ;
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
return nullptr ;