Merge branch 'Trimming'
This commit is contained in:
+7
-1
@@ -1595,8 +1595,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 +1670,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) ;
|
||||
|
||||
@@ -557,6 +557,9 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="MultiGeomDB.cpp">
|
||||
<Filter>File di origine\Gdb</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoTrimming</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DistPointSurfBz.cpp">
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
|
||||
+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
|
||||
|
||||
+459
-68
@@ -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,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 +6429,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<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) ;
|
||||
@@ -6124,10 +6464,9 @@ 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) {
|
||||
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() ;
|
||||
@@ -6186,7 +6525,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
|
||||
@@ -6196,11 +6535,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) ;
|
||||
}
|
||||
}
|
||||
@@ -6213,10 +6552,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 ;
|
||||
@@ -6246,33 +6585,85 @@ 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
|
||||
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
|
||||
|
||||
// --- 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è 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()) ;
|
||||
#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
|
||||
|
||||
|
||||
// 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 ;
|
||||
|
||||
+182
-72
@@ -42,7 +42,6 @@
|
||||
#include <numeric>
|
||||
|
||||
// -------------------------- Debug --------------------------------------------
|
||||
#define DEBUG 0
|
||||
#define DEBUG_BASIC_BORDERS 0
|
||||
#define DEBUG_CHAIN_CURVES 0
|
||||
#define DEBUG_ANG_APPROX 0
|
||||
@@ -63,11 +62,12 @@
|
||||
#define DEBUG_EDGES 0
|
||||
#define DEBUG_SHAPE_STM 0
|
||||
#define DEBUG_HOLES 0
|
||||
#define DEBUG_SMOOTH_CURVATURE 1
|
||||
#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 +284,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
|
||||
@@ -3959,26 +3907,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, 10))) ;
|
||||
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") ;
|
||||
@@ -4219,7 +4167,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, 10)) ;
|
||||
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
|
||||
return nullptr ;
|
||||
@@ -4291,6 +4240,10 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
|
||||
}
|
||||
}
|
||||
|
||||
//////debug
|
||||
//RegolarizeBordersLocally(pCrvEdge1,pCrvEdge2, pSurfBz, 0.2) ;
|
||||
//return nullptr ;
|
||||
|
||||
return ( IsNull( pSurfBz) || ! pSurfBz->IsValid() ? nullptr : Release( pSurfBz)) ;
|
||||
}
|
||||
|
||||
@@ -4950,3 +4903,160 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
struct PntInfo{
|
||||
Point3d pt ;
|
||||
int nSubCurve ;
|
||||
int nPnt ;
|
||||
double dDist ;
|
||||
Vector3d vtN ;
|
||||
int nSide ;
|
||||
PntInfo( const Point3d& _pt, int _nSubCrv, int _nPnt, double _dDist, const Vector3d& _vtN, int _nSide) :
|
||||
pt( _pt), nSubCurve( _nSubCrv), nPnt( _nPnt), dDist( _dDist), vtN( _vtN), nSide( _nSide) {;}
|
||||
};
|
||||
typedef vector<PntInfo> PNTINFOVECTOR ;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
|
||||
// Le curve vengono modificate entro una data tolleranza, in modo che
|
||||
bool
|
||||
RegolarizeBordersLocally( 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
|
||||
const Point3d& ptS1 = bpIsoStart.first ;
|
||||
const Point3d& ptS2 = bpIsoEnd.first ;
|
||||
const Point3d& ptE1 = bpIsoStart.second ;
|
||||
const Point3d& ptE2 = bpIsoEnd.second ;
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
if ( nDegU != 3)
|
||||
return false ;
|
||||
// individuo quali isocurve sono state indicate come inizio e fine
|
||||
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
|
||||
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
|
||||
double dParS1 = -1 ; double dParS2 = -1 ;
|
||||
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
|
||||
return false ;
|
||||
double dParE1 = -1 ; double dParE2 = -1 ;
|
||||
if ( ! pCrv2->GetParamAtPoint( ptE1, dParE1) || ! pCrv2->GetParamAtPoint( ptE2, dParE2))
|
||||
return false ;
|
||||
int nUS1 = int ( dParS1) ;
|
||||
int nUS2 = int ( dParS2) ;
|
||||
bool bInverted = false ;
|
||||
if ( nUS1 > nUS2) {
|
||||
swap( nUS1, nUS2) ;
|
||||
swap( dParE1, dParE2) ;
|
||||
bInverted = true ;
|
||||
}
|
||||
|
||||
// scorro le isocurve a partire dallo start e dell'end della zona indicata
|
||||
// controllo il twist rispetto alla isocurva precedente
|
||||
Point3d ptPrevS = ptS1 ;
|
||||
Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ;
|
||||
Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ;
|
||||
Point3d ptBez ; Vector3d vtNPrev ;
|
||||
pSurfBz->GetPointNrmD1D2( nUS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNPrev) ;
|
||||
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 ptThird1Curr = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ;
|
||||
Point3d ptThird2Curr = 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 ptCurrS = pSurfBz->GetControlPoint( i, 0, &bOk) ;
|
||||
Point3d ptCurrE = pSurfBz->GetControlPoint( i, 1, &bOk) ;
|
||||
Vector3d vtIsoCurr = ptCurrE - ptCurrS ;
|
||||
double dDist = vtIsoCurr.Len() ;
|
||||
vtIsoCurr.Normalize() ;
|
||||
Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ;
|
||||
Vector3d vtCurrInPlane = OrthoCompo( vtIsoCurr, vtDirPrev) ;
|
||||
bool bDet = false ;
|
||||
double dAng = 0 ; vtIsoPrev.GetRotation( vtCurrInPlane, vtDirPrev, dAng, bDet) ;
|
||||
if ( abs( dAng) > 0) {
|
||||
// se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente
|
||||
// allora prendo il penultimo punto della curva corrente, l'ultimo e il secondo della prossima e li sposto lungo la normale della superficie
|
||||
dDist *= dAng * DEGTORAD / 2 ;
|
||||
ptThird1Curr += vtNPrev * dDist ;
|
||||
ptCurrS += vtNPrev * dDist ;
|
||||
ptSecond1Next += vtNPrev * dDist ;
|
||||
ptThird2Curr -= vtNPrev * dDist ;
|
||||
ptCurrE -= vtNPrev * dDist ;
|
||||
ptSecond2Next -= vtNPrev * dDist ;
|
||||
}
|
||||
vPnt0.push_back( ptThird1Curr) ;
|
||||
vPnt0.push_back( ptCurrS) ;
|
||||
vPnt0.push_back( ptSecond1Next) ;
|
||||
|
||||
vPnt1.push_back( ptThird2Curr) ;
|
||||
vPnt1.push_back( ptCurrE) ;
|
||||
vPnt1.push_back( ptSecond2Next) ;
|
||||
|
||||
vtIsoPrev = ptCurrE - ptCurrS ; vtIsoPrev.Normalize() ;
|
||||
vtNPrev = ( ptSecond1Next - ptCurrS) ^ vtIsoPrev ; vtNPrev.Normalize() ;
|
||||
}
|
||||
|
||||
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)) ;
|
||||
}
|
||||
|
||||
// controllo di essere rimasto in tolleranza
|
||||
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( nUS1, dParE1)) ;
|
||||
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( nUS2, dParE2)) ;
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return false ;
|
||||
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return false ;
|
||||
|
||||
// controllo di non aver creato dei cambi di concavità
|
||||
// se ne trovo allora ruoto i terzetti attorno alla nuova isocurva
|
||||
////////////////// DA IMPLEMENTARE (prendendo dalla versione precedente della Regolarize)
|
||||
|
||||
// aggiorno i punti di controllo della superficie di bezier
|
||||
for ( int i = 0 ; i < ssize( vPnt0) ; ++i) {
|
||||
pSurfBz->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
|
||||
pSurfBz->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ;
|
||||
}
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.push_back( Release(pCC1)) ;
|
||||
VT.push_back( Release(pCC2)) ;
|
||||
VT.push_back( Release(pCrv1)) ;
|
||||
VT.push_back( Release(pCrv2)) ;
|
||||
VT.push_back(pSurfBz->Clone());
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
|
||||
#endif
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user