Merge branch 'master' into Trimming

This commit is contained in:
Daniele Bariletti
2026-04-27 15:04:02 +02:00
5 changed files with 370 additions and 43 deletions
+144 -1
View File
@@ -1967,7 +1967,98 @@ CurveComposite::AddJoint( double dU)
//----------------------------------------------------------------------------
bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol)
{
int nCrvCount = GetCurveCount() ;
// verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount)
return false ;
// salvo le vecchie curve e nel caso le ripristino
int nPrevCrv = -1 ;
// recupero l'indice e il puntatore alla curva precedente (se esiste)
if ( nU > 0)
nPrevCrv = nU - 1 ;
else if ( IsClosed())
nPrevCrv = nCrvCount - 1 ;
else
return false ;
PtrOwner<ICurveComposite> pOrigCrv( ConvertCurveToComposite(m_CrvSmplS[ nPrevCrv]->Clone())) ;
// recupero il puntatore alla curva successiva (se esiste)
int nNextCrv = -1 ;
if ( nU < nCrvCount)
nNextCrv = nU ;
else if ( IsClosed())
nNextCrv = 0 ;
else
return false ;
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
int nCrvNmbr = GetCurveCount() ;
int nFlagDel = DeletedCurve::NONE ;
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
return false ;
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
bool bErasedPrev = nFlagDel == DeletedCurve::PREV ;
bool bErasedNext = nFlagDel == DeletedCurve::NEXT ;
double dStart ;
double dEnd ;
if ( bErasedPrev) {
dStart = nU ;
dEnd = nNextCrv + 1 ;
}
else if ( bErasedNext) {
dStart = nPrevCrv ;
dEnd = nU ;
if ( nU == 0)
dStart -= 1 ;
}
else { // ! bErasedSomeCrv
dStart = nPrevCrv ;
dEnd = nNextCrv + 1 ;
}
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
double dErr = 0 ;
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr) || dErr > dTol) {
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
if ( ! bErasedSomeCrv) {
delete m_CrvSmplS[nNextCrv] ;
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
delete m_CrvSmplS[nPrevCrv] ;
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
}
else {
if ( bErasedNext) {
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
nPos = 0 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
else {
int nPos = nU == 0 ? nU : nPrevCrv ;
delete m_CrvSmplS[nPos] ;
if ( nU == 0) {
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
nPos = nCrvNmbr - 1 ;
}
else
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
{
// verifico lo stato
if ( m_nStatus != OK)
@@ -1977,6 +2068,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
// verifico l'indice della giunzione
if ( nU < 0 || nU > nCrvCount)
return false ;
if ( pnFlagDel != nullptr)
*pnFlagDel = 0 ;
// recupero l'indice e il puntatore alla curva precedente (se esiste)
int nPrevCrv = -1 ;
if ( nU > 0)
@@ -2005,6 +2098,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = 1 ;
}
// altrimenti diventa un segmento di retta
else {
@@ -2024,6 +2119,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
if ( pnFlagDel != nullptr)
*pnFlagDel = 2 ;
}
// altrimenti diventa un segmento di retta
else {
@@ -3858,3 +3955,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
ptStart = m_ptStart ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ModifySingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
{
// prendo il possesso e verifico la curva
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
return false ;
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico l'indice sia sensato
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
return false ;
// verifico che start e end coincidano entro la tolleranza
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
return false ;
}
else
return false ;
}
// se presente una tolleranza lungo la curva controllo che sia rispettata
if ( dTolAlong < INFINITO) {
double dErr = 0 ;
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
if ( dErr > dTolAlong)
return false ;
}
delete m_CrvSmplS[nSubCrv] ;
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
return true ;
}
+3 -1
View File
@@ -156,7 +156,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddJoint( double dU) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel = nullptr) override ;
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
bool RemoveJoint( int nU) override ;
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
@@ -178,6 +179,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool GetOnlyPoint( Point3d& ptStart) const override ;
bool ModifySingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+3 -3
View File
@@ -557,9 +557,6 @@
</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>
@@ -576,6 +573,9 @@
<ClCompile Include="CAvSurfFrMove.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="Trimming.cpp">
<Filter>File di origine\GeoStriping</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
+16 -2
View File
@@ -6439,8 +6439,8 @@ bool
SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines)
{
// converto in bezier le curve iniziali
PtrOwner<ICurve> pCrvEdge1( CurveToBezierCurve( pCurve0, 3, false)) ;
PtrOwner<ICurve> pCrvEdge2( CurveToBezierCurve( pCurve1, 3, false)) ;
PtrOwner<ICurveComposite> pCrvEdge1( ConvertCurveToComposite(CurveToBezierCurve( pCurve0, 3, false))) ;
PtrOwner<ICurveComposite> pCrvEdge2( ConvertCurveToComposite(CurveToBezierCurve( pCurve1, 3, false))) ;
if ( IsNull( pCrvEdge1) || IsNull( pCrvEdge2))
return false ;
@@ -6468,6 +6468,11 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
dLenCurr1 = Clamp( dLenPrev1 + dSampleDist, 0., dLen1) ;
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
// se sono abbastanza vicino ad una joint allora prendo quel punto
double dUClosestJoint1 = round( dUCurr1) ;
double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
if ( abs( dLenCurr1 - dLenAlt1) < 1)
dUCurr1 = dUClosestJoint1 ;
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
vtCurr1.Normalize() ;
@@ -6577,6 +6582,15 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
}
}
}
// 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) ;
+204 -36
View File
@@ -37,6 +37,7 @@
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
#include <thread>
#include <future>
#include <numeric>
@@ -62,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 || \
@@ -4240,10 +4241,6 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
}
}
//////debug
//RegolarizeBordersLocally(pCrvEdge1,pCrvEdge2, pSurfBz, 0.2) ;
//return nullptr ;
return ( IsNull( pSurfBz) || ! pSurfBz->IsValid() ? nullptr : Release( pSurfBz)) ;
}
@@ -4910,50 +4907,135 @@ struct PntInfo{
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) {;}
Vector3d vtPos ;
PntInfo( const Point3d& _pt, int _nSubCrv, int _nPnt, double _dDist, const Vector3d& _vtPos) :
pt( _pt), nSubCurve( _nSubCrv), nPnt( _nPnt), dDist( _dDist), vtPos( _vtPos) {;}
};
typedef vector<PntInfo> PNTINFOVECTOR ;
//------------------------------------------------------------------------------
static bool
FillPntInfo( const PNTVECTOR& vPnt, const ICurveComposite* pCC, PNTINFOVECTOR& vPntInfo)
{
for ( int i = 0 ; i < ssize( vPnt) - 3 ; i+=3) {
bool bOk = false ;
const ICurveBezier* pSubCrv = GetCurveBezier( pCC->GetCurve( i / 3)) ;
for ( int j = i == 0 ? 0 : 1 ; j <= 3 ; ++j) {
Point3d pt = pSubCrv->GetControlPoint( j, &bOk) ;
double dDist = 0 ;
Vector3d vtPos = V_NULL ;
if ( j > 0 && j < 3){
DistPointCurve dpc( pt, *pSubCrv) ;
dpc.GetDist( dDist) ;
int nFlag = - 1 ;
Point3d ptMinDist ;
dpc.GetMinDistPoint( 0., ptMinDist, nFlag) ;
vtPos = pt - ptMinDist ;
}
vPntInfo.emplace_back( pt, i, j, dDist, vtPos) ;
}
}
return true ;
}
//------------------------------------------------------------------------------
static bool
RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& vPntRefInfo)
{
// se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la
// normale alla superficie in modo da evitare cambi di concavità
bool bSameSideAsPrev = true ;
for ( int i = 2 ; i < ssize( vPntInfo) - 2 ; ++i) {
int nPrev = vPntInfo[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ;
double dProj = vPntInfo[i].vtPos * vPntInfo[nPrev].vtPos ;
bSameSideAsPrev = vPntInfo[i].dDist < EPS_ZERO || dProj >= 0 ;
if ( ! bSameSideAsPrev) {
// devo verificare anche che sia diverso anche dal successivo ( o dal quello dopo ancora, se il successivo sta sulla curva)
bool bCurrOrPrev = vPntInfo[i+1].dDist < EPS_ZERO ;
int nFirst, nSecond, nThird ;
if ( bCurrOrPrev) {
nFirst = i ;
nSecond = i + 1 ;
nThird = i + 2 ;
}
else {
nFirst = i - 2 ;
nSecond = i - 1 ;
nThird = i ;
}
int nNext = bCurrOrPrev ? i + 2 : i + 1 ;
// se il successivo è diverso ho un terzetto anomalo da aggiustare
// altrimenti ho un cambio naturale di concavità
if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0) {
// ruoto il terzetto fino a matchare la tangente sull'altra curva
Vector3d vtCurr = vPntInfo[nNext].pt - vPntInfo[i].pt ;
Vector3d vtRef = vPntRefInfo[nNext].pt - vPntRefInfo[i].pt ;
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
bool bDet = false ;
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
if ( dAng > 170) {
dAng = 180 - dAng ;
// devo capire quale delle due curve ha i punti di controllo incrociati (come conseguenza della correzione precedente) e rimediare
// DA IMPLEMENTARE, eventualmente
}
vPnt[nFirst].Rotate( vPnt[nSecond], vtAx, dAng) ;
vPnt[nThird].Rotate( vPnt[nSecond], vtAx, dAng) ;
if ( bCurrOrPrev)
i += 2 ;
}
}
}
}
//------------------------------------------------------------------------------
// 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)
ISurfBezier*
RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol)
{
#if DEBUG_SMOOTH_CURVATURE
VT.clear() ;
#endif
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
const Point3d& ptS1 = bpIsoStart.first ;
const Point3d& ptS2 = bpIsoEnd.first ;
const Point3d& ptE1 = bpIsoStart.second ;
const Point3d& ptE2 = bpIsoEnd.second ;
Point3d ptS1 = bpIsoStart.first ;
Point3d ptS2 = bpIsoEnd.first ;
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
double dInterpolateAngTol = 4 ;
double dAngInterp = 0 ;
vtDir1.GetAngle( vtDir2, dAngInterp) ;
bool bInterpolate = dAngInterp > dInterpolateAngTol ;
int nDegU, nDegV, nSpanU, nSpanV ;
bool bRat, bTrimmed ;
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
if ( nDegU != 3)
return false ;
return nullptr ;
// individuo quali isocurve sono state indicate come inizio e fine
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
pCrv2->Invert() ;
double dParS1 = -1 ; double dParS2 = -1 ;
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
return 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) ;
return nullptr ;
int nUS1 = int ( dParS1) * nDegU ;
int nUS2 = int ( dParS2) * nDegU ;
bool bInverted = false ;
if ( nUS1 > nUS2) {
swap( nUS1, nUS2) ;
swap( dParE1, dParE2) ;
swap( dParS1, dParS2) ;
swap( ptS1, ptS2) ;
swap( vtDir1, vtDir2) ;
bInverted = true ;
}
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ;
Vector3d vtTang1 ; pCrvOrig1->GetStartDir( vtTang1) ;
Frame3d frStart ; frStart.Set( ptS1, vtTang1, vtDir1) ; // uso la tangente e l'isocurva in V per il frame iniziale
RotationMinimizingFrame rmf ; rmf.Set( pCrvOrig1, frStart) ;
// scorro le isocurve a partire dallo start e dell'end della zona indicata
// controllo il twist rispetto alla isocurva precedente
@@ -4961,7 +5043,7 @@ RegolarizeBordersLocally( ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const
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) ;
pSurfBz->GetPointNrmD1D2( dParS1, 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) ;
@@ -5010,6 +5092,15 @@ RegolarizeBordersLocally( ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const
vtIsoPrev = ptCurrE - ptCurrS ; vtIsoPrev.Normalize() ;
vtNPrev = ( ptSecond1Next - ptCurrS) ^ vtIsoPrev ; vtNPrev.Normalize() ;
}
// aggiungo gli ultimi due punti
Point3d ptThird1Curr = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ;
vPnt0.push_back( ptThird1Curr) ;
Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ;
vPnt0.push_back( ptFourth1Curr) ;
Point3d ptThird2Curr = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ;
vPnt1.push_back( ptThird2Curr) ;
Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ;
vPnt1.push_back( ptFourth2Curr) ;
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
@@ -5029,34 +5120,111 @@ RegolarizeBordersLocally( ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const
pCC2->AddCurve( Release( cb2)) ;
}
////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona
#if DEBUG_SMOOTH_CURVATURE
VT.push_back( pCC1->Clone()) ;
VT.push_back( pCC2->Clone()) ;
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ;
#endif
// ora verifico l'eventuale presenza di cambi di concavità non desiderati
// se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo
// da matchare la tangente dell'altra curva
PNTINFOVECTOR vPntInfo1, vPntInfo2 ;
FillPntInfo( vPnt0, pCC1, vPntInfo1) ;
FillPntInfo( vPnt1, pCC2, vPntInfo2) ;
RemoveInflexionPoints( ) ;
// se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la
// normale alla superficie in modo da evitare cambi di concavità
bool bSameSideAsPrev = true ;
for ( int i = 2 ; i < ssize( vPntInfo1) - 2 ; ++i) {
int nPrev = vPntInfo1[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ;
double dProj = vPntInfo1[i].vtPos * vPntInfo1[nPrev].vtPos ;
bSameSideAsPrev = vPntInfo1[i].dDist < EPS_ZERO || dProj >= 0 ;
if ( ! bSameSideAsPrev) {
// devo verificare anche che sia diverso anche dal successivo ( o dal quello dopo ancora, se il successivo sta sulla curva)
bool bCurrOrPrev = vPntInfo1[i+1].dDist < EPS_ZERO ;
int nFirst, nSecond, nThird ;
if ( bCurrOrPrev) {
nFirst = i ;
nSecond = i + 1 ;
nThird = i + 2 ;
}
else {
nFirst = i - 2 ;
nSecond = i - 1 ;
nThird = i ;
}
int nNext = bCurrOrPrev ? i + 2 : i + 1 ;
// se il successivo è diverso ho un terzetto anomalo da aggiustare
// altrimenti ho un cambio naturale di concavità
if ( vPntInfo1[i].vtPos * vPntInfo1[nNext].vtPos < 0) {
// ruoto il terzetto fino a matchare la tangente sull'altra curva
Vector3d vtCurr = vPntInfo1[nNext].pt - vPntInfo1[i].pt ;
Vector3d vtRef = vPntInfo2[nNext].pt - vPntInfo2[i].pt ;
Vector3d vtAx = vPntInfo2[nSecond].pt - vPntInfo1[nSecond].pt ;
bool bDet = false ;
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
if ( dAng > 170) {
dAng = 180 - dAng ;
// devo capire quale delle due curve ha i punti di controllo incrociati (come conseguenza della correzione precedente) e rimediare
// DA IMPLEMENTARE, eventualmente
}
vPnt0[nFirst].Rotate(vPnt0[nSecond], vtAx, dAng) ;
vPnt0[nThird].Rotate(vPnt0[nSecond], vtAx, dAng) ;
if ( bCurrOrPrev)
i += 2 ;
}
}
}
// invece di rifare le curve da capo posso creare un metodo per le curve compo e modificare solo le curve necessarie
pCC1->Clear() ;
pCC2->Clear() ;
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
cb1->SetControlPoint( 0, vPnt0[i]) ;
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
pCC1->AddCurve( Release( cb1)) ;
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
cb2->SetControlPoint( 0, vPnt1[i]) ;
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
pCC2->AddCurve( Release( cb2)) ;
}
// controllo di essere rimasto in tolleranza
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 ;
//if ( dErr > dTol)
// return nullptr ;
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
if ( dErr > dTol)
return false ;
//if ( dErr > dTol)
// return nullptr ;
// 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)
PtrOwner<ISurfBezier> pNewSurf( pSurfBz->Clone()) ;
// 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]) ;
pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
pNewSurf->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 ;
return Release( pNewSurf) ;
}