Merge branch 'master' into Trimming

This commit is contained in:
Daniele Bariletti
2026-05-08 17:25:43 +02:00
6 changed files with 202 additions and 180 deletions
+24 -7
View File
@@ -4052,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
@@ -4070,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) ;
@@ -4105,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)) {
@@ -4118,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) ;
@@ -4130,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 ;
}
}
@@ -4141,6 +4157,7 @@ GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockPara
// vado alla successiva
pPrevCrv = pCrv ;
pCrv = ( bNextOk ? pNextCrv : nullptr) ;
bFirst = false ;
}
return bFound ;
@@ -4606,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
+120 -3
View File
@@ -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
@@ -2697,3 +2702,115 @@ 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) ;
// --- 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) ;
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
// 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 - dMyDist, dLenPrev2, dLen2) ;
double dLimSupLen2 = Clamp( dLenCurr2 + dMyDist, 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 ;
}
}
}
return true ;
}
+1 -1
View File
@@ -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) ;
BIN
View File
Binary file not shown.
+49 -157
View File
@@ -6402,7 +6402,7 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
#endif
// Verifico che la distanza di campionamento sia ammissibile
double dSampleDist = Clamp( dSampleLen, 2., 30.) ; // 20.0 sembra un passo di campionamento ideale
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) ;
@@ -6415,168 +6415,67 @@ 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 ;
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 + dSampleDist, 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 ;
//// 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. * dSampleDist) ;
}
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. * dSampleDist) ;
}
if ( ! bOkMinDist) {
// --- Aumento la distanza corrente del passo di campionamento
double dLen = Clamp( dLenPrev2 + dSampleDist, 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. * dMyDist)
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
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 ;
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 ;
}
}
}
// 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 ;
}
#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 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) ;
#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) ;
// --- 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
//// 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 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
//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. !<--
// --- 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) ;
@@ -6593,7 +6492,7 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
SyncLineNext.first = vEdgeSyncLines[i].first ;
SyncLineNext.second = vEdgeSyncLines[i].second ;
}
// Recupero i parametri correnti
// Recupero i parametri correnti
double dUS1, dUE1, dUS2, dUE2 ;
pCrvQuad1->GetParamAtPoint( SyncLinePrev.first, dUS1) ;
pCrvQuad2->GetParamAtPoint( SyncLinePrev.second, dUS2) ;
@@ -6602,22 +6501,15 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ;
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ;
// Aggiorno i parametri
// 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()) ;
#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
// Aggiorno i parametri
ptPrev1 = ptCurr1 ; dUPrev1 = dUCurr1 ; dLenPrev1 = dLenCurr1 ;
ptPrev2 = ptCurr2 ; dUPrev2 = dUCurr2 ; dLenPrev2 = dLenCurr2 ;
}
+8 -12
View File
@@ -63,7 +63,7 @@
#define DEBUG_EDGES 0
#define DEBUG_SHAPE_STM 0
#define DEBUG_HOLES 0
#define DEBUG_SMOOTH_CURVATURE 1
#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 || \
@@ -3896,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() ;
@@ -3958,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) ;
@@ -5019,10 +5019,6 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta
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 ;
@@ -5039,13 +5035,11 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta
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<ICurveComposite> pCrvOrig1( ConvertCurveToComposite( pCrv1->CopyParamRange( dParS1, dParS2))) ;
PtrOwner<ICurveComposite> pCrvOrig2( ConvertCurveToComposite( pCrv2->CopyParamRange( dParS1, dParS2))) ;
@@ -5138,7 +5132,6 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta
if ( pCC2->GetCurveCount() != nNewCrvs)
return nullptr ;
int nDiff = nNewCrvs - pCrvOrig1->GetCurveCount() ;
int nSpanUNew = nSpanU + nDiff ;
pNewSurf->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
// copio la parte uguale
for ( int i = 0 ; i < nSpanU * nDegU + 1 ; ++i) {
@@ -5155,7 +5148,6 @@ RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoSta
}
// aggiungo la parte diversa
for ( int i = 0 ; i < nNewCrvs * nDegU + 1 ; ++i) {
bool bOk = false ;
int nSub = i / 3 ;
int nPnt = i % 3 ;
if ( nSub == nNewCrvs) {
@@ -5192,6 +5184,10 @@ RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart,
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 ;